From e85cdacbc58dedacb7fcbb119efd2b44db4bcdd6 Mon Sep 17 00:00:00 2001 From: Daniel Ratcliffe Date: Mon, 1 May 2017 14:32:39 +0100 Subject: [PATCH] ComputerCraft 1.79 initial upload Added the complete source code to ComputerCraft 1.79 for Minecraft 1.8.9, plus newly written README and LICENSE files for the open source release. --- .gitignore | 8 + LICENSE | 98 + LICENSE-luaj | 19 + README.md | 25 +- build.gradle | 85 + build_luaj.sh | 12 + deploy.sh | 46 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 52271 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 164 + libs/luaj-jse-2.0.3.jar | Bin 0 -> 290203 bytes luaj-2.0.3/.classpath | 19 + luaj-2.0.3/.project | 17 + luaj-2.0.3/LICENSE.txt | 19 + luaj-2.0.3/README.html | 780 ++ luaj-2.0.3/build-coverage.xml | 119 + luaj-2.0.3/build-libs.xml | 56 + luaj-2.0.3/build.xml | 172 + luaj-2.0.3/docs/api/allclasses-frame.html | 143 + luaj-2.0.3/docs/api/allclasses-noframe.html | 143 + luaj-2.0.3/docs/api/constant-values.html | 960 ++ luaj-2.0.3/docs/api/deprecated-list.html | 146 + luaj-2.0.3/docs/api/help-doc.html | 223 + luaj-2.0.3/docs/api/index-all.html | 4272 +++++++++ luaj-2.0.3/docs/api/index.html | 39 + luaj-2.0.3/docs/api/org/luaj/vm2/Buffer.html | 602 ++ .../org/luaj/vm2/LoadState.LuaCompiler.html | 230 + .../docs/api/org/luaj/vm2/LoadState.html | 821 ++ luaj-2.0.3/docs/api/org/luaj/vm2/LocVars.html | 342 + luaj-2.0.3/docs/api/org/luaj/vm2/Lua.html | 2109 +++++ .../docs/api/org/luaj/vm2/LuaBoolean.html | 601 ++ .../docs/api/org/luaj/vm2/LuaClosure.html | 857 ++ .../docs/api/org/luaj/vm2/LuaDouble.html | 3317 +++++++ .../docs/api/org/luaj/vm2/LuaError.html | 355 + .../docs/api/org/luaj/vm2/LuaFunction.html | 598 ++ .../docs/api/org/luaj/vm2/LuaInteger.html | 3095 ++++++ luaj-2.0.3/docs/api/org/luaj/vm2/LuaNil.html | 1063 +++ .../docs/api/org/luaj/vm2/LuaNumber.html | 747 ++ .../docs/api/org/luaj/vm2/LuaString.html | 3786 ++++++++ .../docs/api/org/luaj/vm2/LuaTable.html | 1563 ++++ .../api/org/luaj/vm2/LuaThread.CallStack.html | 279 + .../docs/api/org/luaj/vm2/LuaThread.html | 910 ++ .../docs/api/org/luaj/vm2/LuaUserdata.html | 1010 ++ .../docs/api/org/luaj/vm2/LuaValue.html | 8292 +++++++++++++++++ .../docs/api/org/luaj/vm2/OrphanedThread.html | 256 + luaj-2.0.3/docs/api/org/luaj/vm2/Print.html | 451 + .../docs/api/org/luaj/vm2/Prototype.html | 543 ++ .../api/org/luaj/vm2/TailcallVarargs.html | 416 + luaj-2.0.3/docs/api/org/luaj/vm2/UpValue.html | 333 + luaj-2.0.3/docs/api/org/luaj/vm2/Varargs.html | 1743 ++++ .../docs/api/org/luaj/vm2/WeakTable.html | 733 ++ .../api/org/luaj/vm2/class-use/Buffer.html | 311 + .../vm2/class-use/LoadState.LuaCompiler.html | 239 + .../api/org/luaj/vm2/class-use/LoadState.html | 144 + .../api/org/luaj/vm2/class-use/LocVars.html | 180 + .../docs/api/org/luaj/vm2/class-use/Lua.html | 209 + .../org/luaj/vm2/class-use/LuaBoolean.html | 204 + .../org/luaj/vm2/class-use/LuaClosure.html | 283 + .../api/org/luaj/vm2/class-use/LuaDouble.html | 196 + .../api/org/luaj/vm2/class-use/LuaError.html | 144 + .../org/luaj/vm2/class-use/LuaFunction.html | 651 ++ .../org/luaj/vm2/class-use/LuaInteger.html | 334 + .../api/org/luaj/vm2/class-use/LuaNil.html | 144 + .../api/org/luaj/vm2/class-use/LuaNumber.html | 457 + .../api/org/luaj/vm2/class-use/LuaString.html | 855 ++ .../api/org/luaj/vm2/class-use/LuaTable.html | 535 ++ .../vm2/class-use/LuaThread.CallStack.html | 180 + .../api/org/luaj/vm2/class-use/LuaThread.html | 335 + .../org/luaj/vm2/class-use/LuaUserdata.html | 214 + .../api/org/luaj/vm2/class-use/LuaValue.html | 5645 +++++++++++ .../luaj/vm2/class-use/OrphanedThread.html | 144 + .../api/org/luaj/vm2/class-use/Print.html | 144 + .../api/org/luaj/vm2/class-use/Prototype.html | 358 + .../luaj/vm2/class-use/TailcallVarargs.html | 144 + .../api/org/luaj/vm2/class-use/UpValue.html | 180 + .../api/org/luaj/vm2/class-use/Varargs.html | 1649 ++++ .../api/org/luaj/vm2/class-use/WeakTable.html | 144 + .../docs/api/org/luaj/vm2/compiler/LuaC.html | 543 ++ .../org/luaj/vm2/compiler/class-use/LuaC.html | 180 + .../org/luaj/vm2/compiler/package-frame.html | 32 + .../luaj/vm2/compiler/package-summary.html | 157 + .../org/luaj/vm2/compiler/package-tree.html | 156 + .../org/luaj/vm2/compiler/package-use.html | 170 + .../docs/api/org/luaj/vm2/lib/BaseLib.html | 615 ++ .../api/org/luaj/vm2/lib/CoroutineLib.html | 383 + .../docs/api/org/luaj/vm2/lib/DebugLib.html | 672 ++ .../docs/api/org/luaj/vm2/lib/IoLib.File.html | 643 ++ .../docs/api/org/luaj/vm2/lib/IoLib.html | 1150 +++ .../api/org/luaj/vm2/lib/LibFunction.html | 596 ++ .../docs/api/org/luaj/vm2/lib/MathLib.html | 528 ++ .../api/org/luaj/vm2/lib/OneArgFunction.html | 571 ++ .../docs/api/org/luaj/vm2/lib/OsLib.html | 772 ++ .../docs/api/org/luaj/vm2/lib/PackageLib.html | 772 ++ .../api/org/luaj/vm2/lib/ResourceFinder.html | 234 + .../docs/api/org/luaj/vm2/lib/StringLib.html | 445 + .../docs/api/org/luaj/vm2/lib/TableLib.html | 393 + .../org/luaj/vm2/lib/ThreeArgFunction.html | 568 ++ .../api/org/luaj/vm2/lib/TwoArgFunction.html | 571 ++ .../api/org/luaj/vm2/lib/VarArgFunction.html | 590 ++ .../api/org/luaj/vm2/lib/ZeroArgFunction.html | 566 ++ .../org/luaj/vm2/lib/class-use/BaseLib.html | 210 + .../luaj/vm2/lib/class-use/CoroutineLib.html | 144 + .../org/luaj/vm2/lib/class-use/DebugLib.html | 144 + .../luaj/vm2/lib/class-use/IoLib.File.html | 399 + .../api/org/luaj/vm2/lib/class-use/IoLib.html | 211 + .../luaj/vm2/lib/class-use/LibFunction.html | 406 + .../org/luaj/vm2/lib/class-use/MathLib.html | 210 + .../vm2/lib/class-use/OneArgFunction.html | 311 + .../api/org/luaj/vm2/lib/class-use/OsLib.html | 180 + .../luaj/vm2/lib/class-use/PackageLib.html | 180 + .../vm2/lib/class-use/ResourceFinder.html | 226 + .../org/luaj/vm2/lib/class-use/StringLib.html | 144 + .../org/luaj/vm2/lib/class-use/TableLib.html | 144 + .../vm2/lib/class-use/ThreeArgFunction.html | 144 + .../vm2/lib/class-use/TwoArgFunction.html | 180 + .../vm2/lib/class-use/VarArgFunction.html | 235 + .../vm2/lib/class-use/ZeroArgFunction.html | 144 + .../api/org/luaj/vm2/lib/jme/JmeIoLib.html | 544 ++ .../api/org/luaj/vm2/lib/jme/JmePlatform.html | 336 + .../luaj/vm2/lib/jme/class-use/JmeIoLib.html | 144 + .../vm2/lib/jme/class-use/JmePlatform.html | 144 + .../org/luaj/vm2/lib/jme/package-frame.html | 34 + .../org/luaj/vm2/lib/jme/package-summary.html | 163 + .../org/luaj/vm2/lib/jme/package-tree.html | 165 + .../api/org/luaj/vm2/lib/jme/package-use.html | 144 + .../org/luaj/vm2/lib/jse/CoerceJavaToLua.html | 297 + .../org/luaj/vm2/lib/jse/CoerceLuaToJava.html | 285 + .../api/org/luaj/vm2/lib/jse/JseBaseLib.html | 409 + .../api/org/luaj/vm2/lib/jse/JseIoLib.html | 543 ++ .../vm2/lib/jse/JseMathLib.JseMathLib1.html | 364 + .../vm2/lib/jse/JseMathLib.JseMathLib2.html | 366 + .../api/org/luaj/vm2/lib/jse/JseMathLib.html | 462 + .../api/org/luaj/vm2/lib/jse/JseOsLib.html | 572 ++ .../api/org/luaj/vm2/lib/jse/JsePlatform.html | 326 + .../api/org/luaj/vm2/lib/jse/JseProcess.html | 323 + .../api/org/luaj/vm2/lib/jse/LuajavaLib.html | 412 + .../lib/jse/class-use/CoerceJavaToLua.html | 144 + .../lib/jse/class-use/CoerceLuaToJava.html | 144 + .../vm2/lib/jse/class-use/JseBaseLib.html | 144 + .../luaj/vm2/lib/jse/class-use/JseIoLib.html | 144 + .../jse/class-use/JseMathLib.JseMathLib1.html | 144 + .../jse/class-use/JseMathLib.JseMathLib2.html | 144 + .../vm2/lib/jse/class-use/JseMathLib.html | 144 + .../luaj/vm2/lib/jse/class-use/JseOsLib.html | 144 + .../vm2/lib/jse/class-use/JsePlatform.html | 144 + .../vm2/lib/jse/class-use/JseProcess.html | 144 + .../vm2/lib/jse/class-use/LuajavaLib.html | 144 + .../org/luaj/vm2/lib/jse/package-frame.html | 52 + .../org/luaj/vm2/lib/jse/package-summary.html | 201 + .../org/luaj/vm2/lib/jse/package-tree.html | 176 + .../api/org/luaj/vm2/lib/jse/package-use.html | 144 + .../api/org/luaj/vm2/lib/package-frame.html | 71 + .../api/org/luaj/vm2/lib/package-summary.html | 239 + .../api/org/luaj/vm2/lib/package-tree.html | 171 + .../api/org/luaj/vm2/lib/package-use.html | 333 + .../docs/api/org/luaj/vm2/luajc/LuaJC.html | 369 + .../org/luaj/vm2/luajc/class-use/LuaJC.html | 180 + .../api/org/luaj/vm2/luajc/package-frame.html | 32 + .../org/luaj/vm2/luajc/package-summary.html | 158 + .../api/org/luaj/vm2/luajc/package-tree.html | 154 + .../api/org/luaj/vm2/luajc/package-use.html | 171 + .../docs/api/org/luaj/vm2/package-frame.html | 109 + .../api/org/luaj/vm2/package-summary.html | 291 + .../docs/api/org/luaj/vm2/package-tree.html | 179 + .../docs/api/org/luaj/vm2/package-use.html | 490 + luaj-2.0.3/docs/api/overview-frame.html | 52 + luaj-2.0.3/docs/api/overview-summary.html | 176 + luaj-2.0.3/docs/api/overview-tree.html | 197 + luaj-2.0.3/docs/api/package-list | 6 + luaj-2.0.3/docs/api/resources/inherit.gif | Bin 0 -> 57 bytes luaj-2.0.3/docs/api/serialized-form.html | 202 + luaj-2.0.3/docs/api/stylesheet.css | 29 + luaj-2.0.3/examples/jme/SampleMIDlet.java | 34 + luaj-2.0.3/examples/jse/SampleJseMain.java | 18 + luaj-2.0.3/examples/jse/SampleParser.java | 49 + .../examples/jse/ScriptEngineSample.java | 128 + luaj-2.0.3/examples/jse/hyperbolic.java | 63 + luaj-2.0.3/examples/lua/hello.lua | 1 + luaj-2.0.3/examples/lua/hyperbolicapp.lua | 19 + luaj-2.0.3/examples/lua/logo.gif | Bin 0 -> 2694 bytes luaj-2.0.3/examples/lua/swingapp.lua | 132 + luaj-2.0.3/names.csv | 89 + luaj-2.0.3/src/core/org/luaj/vm2/Buffer.java | 260 + .../src/core/org/luaj/vm2/LoadState.java | 428 + luaj-2.0.3/src/core/org/luaj/vm2/LocVars.java | 52 + luaj-2.0.3/src/core/org/luaj/vm2/Lua.java | 337 + .../src/core/org/luaj/vm2/LuaBoolean.java | 103 + .../src/core/org/luaj/vm2/LuaClosure.java | 521 ++ .../src/core/org/luaj/vm2/LuaDouble.java | 288 + .../src/core/org/luaj/vm2/LuaError.java | 132 + .../src/core/org/luaj/vm2/LuaFunction.java | 82 + .../src/core/org/luaj/vm2/LuaInteger.java | 215 + luaj-2.0.3/src/core/org/luaj/vm2/LuaNil.java | 104 + .../src/core/org/luaj/vm2/LuaNumber.java | 81 + .../src/core/org/luaj/vm2/LuaString.java | 749 ++ .../src/core/org/luaj/vm2/LuaTable.java | 718 ++ .../src/core/org/luaj/vm2/LuaThread.java | 433 + .../src/core/org/luaj/vm2/LuaUserdata.java | 126 + .../src/core/org/luaj/vm2/LuaValue.java | 3648 ++++++++ .../src/core/org/luaj/vm2/OrphanedThread.java | 44 + luaj-2.0.3/src/core/org/luaj/vm2/Print.java | 417 + .../src/core/org/luaj/vm2/Prototype.java | 77 + .../core/org/luaj/vm2/TailcallVarargs.java | 97 + luaj-2.0.3/src/core/org/luaj/vm2/UpValue.java | 77 + luaj-2.0.3/src/core/org/luaj/vm2/Varargs.java | 537 ++ .../src/core/org/luaj/vm2/WeakTable.java | 349 + .../core/org/luaj/vm2/compiler/DumpState.java | 267 + .../core/org/luaj/vm2/compiler/FuncState.java | 1084 +++ .../org/luaj/vm2/compiler/InstructionPtr.java | 37 + .../core/org/luaj/vm2/compiler/IntPtr.java | 31 + .../core/org/luaj/vm2/compiler/LexState.java | 1905 ++++ .../src/core/org/luaj/vm2/compiler/LuaC.java | 251 + .../src/core/org/luaj/vm2/lib/BaseLib.java | 430 + .../core/org/luaj/vm2/lib/CoroutineLib.java | 134 + .../src/core/org/luaj/vm2/lib/DebugLib.java | 977 ++ .../src/core/org/luaj/vm2/lib/IoLib.java | 607 ++ .../core/org/luaj/vm2/lib/LibFunction.java | 200 + .../src/core/org/luaj/vm2/lib/MathLib.java | 251 + .../core/org/luaj/vm2/lib/OneArgFunction.java | 79 + .../src/core/org/luaj/vm2/lib/OsLib.java | 323 + .../src/core/org/luaj/vm2/lib/PackageLib.java | 466 + .../core/org/luaj/vm2/lib/ResourceFinder.java | 57 + .../src/core/org/luaj/vm2/lib/StringLib.java | 1190 +++ .../src/core/org/luaj/vm2/lib/TableLib.java | 124 + .../org/luaj/vm2/lib/ThreeArgFunction.java | 80 + .../core/org/luaj/vm2/lib/TwoArgFunction.java | 80 + .../core/org/luaj/vm2/lib/VarArgFunction.java | 100 + .../org/luaj/vm2/lib/ZeroArgFunction.java | 77 + .../jme/org/luaj/vm2/lib/jme/JmeIoLib.java | 227 + .../jme/org/luaj/vm2/lib/jme/JmePlatform.java | 130 + .../services/javax.script.ScriptEngineFactory | 1 + luaj-2.0.3/src/jse/lua.java | 223 + luaj-2.0.3/src/jse/lua2java.java | 213 + luaj-2.0.3/src/jse/luac.java | 181 + luaj-2.0.3/src/jse/luajc.java | 245 + .../src/jse/org/luaj/vm2/ast/Block.java | 41 + .../src/jse/org/luaj/vm2/ast/Chunk.java | 34 + luaj-2.0.3/src/jse/org/luaj/vm2/ast/Exp.java | 313 + .../src/jse/org/luaj/vm2/ast/FuncArgs.java | 66 + .../src/jse/org/luaj/vm2/ast/FuncBody.java | 36 + .../src/jse/org/luaj/vm2/ast/FuncName.java | 49 + luaj-2.0.3/src/jse/org/luaj/vm2/ast/Name.java | 31 + .../jse/org/luaj/vm2/ast/NameResolver.java | 127 + .../src/jse/org/luaj/vm2/ast/NameScope.java | 85 + .../src/jse/org/luaj/vm2/ast/ParList.java | 42 + luaj-2.0.3/src/jse/org/luaj/vm2/ast/Stat.java | 250 + luaj-2.0.3/src/jse/org/luaj/vm2/ast/Str.java | 93 + .../org/luaj/vm2/ast/TableConstructor.java | 32 + .../src/jse/org/luaj/vm2/ast/TableField.java | 51 + .../src/jse/org/luaj/vm2/ast/Variable.java | 62 + .../src/jse/org/luaj/vm2/ast/Visitor.java | 176 + .../org/luaj/vm2/lib/jse/CoerceJavaToLua.java | 157 + .../org/luaj/vm2/lib/jse/CoerceLuaToJava.java | 367 + .../jse/org/luaj/vm2/lib/jse/JavaArray.java | 71 + .../jse/org/luaj/vm2/lib/jse/JavaClass.java | 138 + .../org/luaj/vm2/lib/jse/JavaConstructor.java | 116 + .../org/luaj/vm2/lib/jse/JavaInstance.java | 79 + .../jse/org/luaj/vm2/lib/jse/JavaMember.java | 84 + .../jse/org/luaj/vm2/lib/jse/JavaMethod.java | 163 + .../jse/org/luaj/vm2/lib/jse/JseBaseLib.java | 99 + .../jse/org/luaj/vm2/lib/jse/JseIoLib.java | 222 + .../jse/org/luaj/vm2/lib/jse/JseMathLib.java | 107 + .../jse/org/luaj/vm2/lib/jse/JseOsLib.java | 126 + .../jse/org/luaj/vm2/lib/jse/JsePlatform.java | 117 + .../jse/org/luaj/vm2/lib/jse/JseProcess.java | 116 + .../jse/org/luaj/vm2/lib/jse/LuajavaLib.java | 195 + .../org/luaj/vm2/lua2java/JavaCodeGen.java | 1094 +++ .../jse/org/luaj/vm2/lua2java/JavaScope.java | 189 + .../jse/org/luaj/vm2/lua2java/Lua2Java.java | 166 + .../jse/org/luaj/vm2/luajc/BasicBlock.java | 180 + .../jse/org/luaj/vm2/luajc/JavaBuilder.java | 791 ++ .../src/jse/org/luaj/vm2/luajc/JavaGen.java | 463 + .../jse/org/luaj/vm2/luajc/JavaLoader.java | 76 + .../src/jse/org/luaj/vm2/luajc/LuaJC.java | 125 + .../src/jse/org/luaj/vm2/luajc/ProtoInfo.java | 461 + .../src/jse/org/luaj/vm2/luajc/UpvalInfo.java | 144 + .../src/jse/org/luaj/vm2/luajc/VarInfo.java | 132 + .../jse/org/luaj/vm2/parser/LuaParser.java | 1848 ++++ .../luaj/vm2/parser/LuaParserConstants.java | 225 + .../vm2/parser/LuaParserTokenManager.java | 2045 ++++ .../org/luaj/vm2/parser/ParseException.java | 187 + .../org/luaj/vm2/parser/SimpleCharStream.java | 469 + .../src/jse/org/luaj/vm2/parser/Token.java | 131 + .../org/luaj/vm2/parser/TokenMgrError.java | 147 + .../org/luaj/vm2/script/LuaScriptEngine.java | 286 + .../vm2/script/LuaScriptEngineFactory.java | 134 + .../test/java/org/luaj/luajc/TestLuaJ.java | 71 + .../test/java/org/luaj/luajc/TestLuaJC.java | 107 + .../test/junit/org/luaj/vm2/AllTests.java | 91 + .../junit/org/luaj/vm2/CompatibiltyTest.java | 128 + .../test/junit/org/luaj/vm2/ErrorsTest.java | 65 + .../junit/org/luaj/vm2/FragmentsTest.java | 583 ++ .../junit/org/luaj/vm2/LuaOperationsTest.java | 261 + .../test/junit/org/luaj/vm2/MathLibTest.java | 251 + .../junit/org/luaj/vm2/MetatableTest.java | 366 + .../org/luaj/vm2/OrphanedThreadTest.java | 184 + .../junit/org/luaj/vm2/RequireClassTest.java | 84 + .../junit/org/luaj/vm2/ScriptDrivenTest.java | 258 + .../test/junit/org/luaj/vm2/StringTest.java | 117 + .../junit/org/luaj/vm2/TableArrayTest.java | 355 + .../junit/org/luaj/vm2/TableHashTest.java | 245 + .../test/junit/org/luaj/vm2/TableTest.java | 358 + .../test/junit/org/luaj/vm2/TypeTest.java | 1242 +++ .../luaj/vm2/UnaryBinaryOperatorsTest.java | 1149 +++ .../junit/org/luaj/vm2/WeakTableTest.java | 254 + .../luaj/vm2/compiler/AbstractUnitTests.java | 123 + .../luaj/vm2/compiler/CompilerUnitTests.java | 35 + .../vm2/compiler/DumpLoadEndianIntTest.java | 135 + .../luaj/vm2/compiler/RegressionTests.java | 30 + .../org/luaj/vm2/compiler/SimpleTests.java | 101 + .../luaj/vm2/lib/jse/LuaJavaCoercionTest.java | 407 + .../lib/jse/LuajavaAccessibleMembersTest.java | 70 + .../vm2/lib/jse/LuajavaClassMembersTest.java | 226 + .../junit/org/luaj/vm2/lib/jse/TestClass.java | 18 + .../org/luaj/vm2/lib/jse/TestInterface.java | 5 + .../require/RequireSampleClassCastExcep.java | 17 + .../require/RequireSampleLoadLuaError.java | 20 + .../RequireSampleLoadRuntimeExcep.java | 18 + .../vm2/require/RequireSampleSuccess.java | 17 + luaj-2.0.3/test/lua/baselib.lua | 312 + luaj-2.0.3/test/lua/coroutinelib.lua | 125 + luaj-2.0.3/test/lua/debuglib.lua | 232 + luaj-2.0.3/test/lua/errors.lua | 137 + luaj-2.0.3/test/lua/errors/args.lua | 197 + luaj-2.0.3/test/lua/errors/baselibargs.lua | 171 + .../test/lua/errors/coroutinelibargs.lua | 47 + luaj-2.0.3/test/lua/errors/iolibargs.lua | 85 + luaj-2.0.3/test/lua/errors/mathlibargs.lua | 112 + luaj-2.0.3/test/lua/errors/modulelibargs.lua | 46 + luaj-2.0.3/test/lua/errors/operators.lua | 157 + luaj-2.0.3/test/lua/errors/stringlibargs.lua | 120 + luaj-2.0.3/test/lua/errors/tablelibargs.lua | 66 + luaj-2.0.3/test/lua/foo.log | 242 + luaj-2.0.3/test/lua/functions.lua | 74 + luaj-2.0.3/test/lua/iolib.lua | 141 + luaj-2.0.3/test/lua/luaj2.0-tests.zip | Bin 0 -> 234243 bytes luaj-2.0.3/test/lua/manyupvals.lua | 38 + luaj-2.0.3/test/lua/mathlib.lua | 223 + luaj-2.0.3/test/lua/metatags.lua | 286 + luaj-2.0.3/test/lua/oslib.lua | 40 + luaj-2.0.3/test/lua/perf/binarytrees.lua | 50 + luaj-2.0.3/test/lua/perf/fannkuch.lua | 51 + luaj-2.0.3/test/lua/perf/nbody.lua | 123 + luaj-2.0.3/test/lua/perf/nsieve.lua | 35 + luaj-2.0.3/test/lua/repack.sh | 46 + luaj-2.0.3/test/lua/stringlib.lua | 184 + luaj-2.0.3/test/lua/tablelib.lua | 274 + luaj-2.0.3/test/lua/tailcalls.lua | 153 + luaj-2.0.3/test/lua/upvalues.lua | 97 + luaj-2.0.3/test/lua/vm.lua | 250 + luaj-2.0.3/version.properties | 1 + luaj-2.0.3/wtk.xml | 25 + setup.sh | 13 + .../dan200/computercraft/ComputerCraft.java | 790 ++ .../computercraft/api/ComputerCraftAPI.java | 317 + .../computercraft/api/filesystem/IMount.java | 57 + .../api/filesystem/IWritableMount.java | 52 + .../api/filesystem/package-info.java | 10 + .../computercraft/api/lua/ILuaContext.java | 58 + .../computercraft/api/lua/ILuaObject.java | 26 + .../computercraft/api/lua/ILuaTask.java | 12 + .../computercraft/api/lua/LuaException.java | 36 + .../computercraft/api/lua/package-info.java | 10 + .../computercraft/api/media/IMedia.java | 59 + .../api/media/IMediaProvider.java | 23 + .../computercraft/api/media/package-info.java | 10 + .../computercraft/api/package-info.java | 10 + .../api/peripheral/IComputerAccess.java | 102 + .../api/peripheral/IPeripheral.java | 98 + .../api/peripheral/IPeripheralProvider.java | 25 + .../api/peripheral/package-info.java | 10 + .../ITurtlePermissionProvider.java | 20 + .../api/permissions/package-info.java | 10 + .../redstone/IBundledRedstoneProvider.java | 25 + .../api/redstone/package-info.java | 10 + .../api/turtle/ITurtleAccess.java | 169 + .../api/turtle/ITurtleCommand.java | 25 + .../api/turtle/ITurtleUpgrade.java | 108 + .../api/turtle/TurtleAnimation.java | 22 + .../api/turtle/TurtleCommandResult.java | 73 + .../computercraft/api/turtle/TurtleSide.java | 23 + .../api/turtle/TurtleUpgradeType.java | 27 + .../computercraft/api/turtle/TurtleVerb.java | 26 + .../api/turtle/package-info.java | 10 + .../client/gui/FixedWidthFontRenderer.java | 151 + .../computercraft/client/gui/GuiComputer.java | 195 + .../client/gui/GuiDiskDrive.java | 46 + .../client/gui/GuiPocketComputer.java | 24 + .../computercraft/client/gui/GuiPrinter.java | 54 + .../computercraft/client/gui/GuiPrintout.java | 212 + .../computercraft/client/gui/GuiTurtle.java | 166 + .../client/gui/widgets/MousePos.java | 19 + .../client/gui/widgets/Widget.java | 386 + .../client/gui/widgets/WidgetContainer.java | 344 + .../client/gui/widgets/WidgetTerminal.java | 477 + .../client/proxy/CCTurtleProxyClient.java | 190 + .../proxy/ComputerCraftProxyClient.java | 492 + .../render/TileEntityMonitorRenderer.java | 287 + .../render/TileEntityTurtleRenderer.java | 398 + .../client/render/TurtleMultiModel.java | 195 + .../client/render/TurtleSmartItemModel.java | 211 + .../computercraft/core/apis/BitAPI.java | 112 + .../computercraft/core/apis/BufferAPI.java | 210 + .../dan200/computercraft/core/apis/FSAPI.java | 630 ++ .../computercraft/core/apis/HTTPAPI.java | 246 + .../computercraft/core/apis/HTTPRequest.java | 273 + .../core/apis/IAPIEnvironment.java | 45 + .../computercraft/core/apis/ILuaAPI.java | 17 + .../dan200/computercraft/core/apis/OSAPI.java | 370 + .../core/apis/PeripheralAPI.java | 534 ++ .../computercraft/core/apis/RedstoneAPI.java | 198 + .../computercraft/core/apis/TermAPI.java | 290 + .../computercraft/core/computer/Computer.java | 894 ++ .../core/computer/ComputerThread.java | 230 + .../core/computer/IComputerEnvironment.java | 22 + .../computercraft/core/computer/ITask.java | 13 + .../core/computer/MainThread.java | 65 + .../core/filesystem/ComboMount.java | 128 + .../core/filesystem/EmptyMount.java | 51 + .../core/filesystem/FileMount.java | 386 + .../core/filesystem/FileSystem.java | 985 ++ .../core/filesystem/FileSystemException.java | 13 + .../core/filesystem/IMountedFile.java | 13 + .../core/filesystem/IMountedFileBinary.java | 16 + .../core/filesystem/IMountedFileNormal.java | 16 + .../core/filesystem/JarMount.java | 249 + .../core/filesystem/SubMount.java | 69 + .../computercraft/core/lua/ILuaMachine.java | 28 + .../core/lua/LuaJLuaMachine.java | 682 ++ .../computercraft/core/terminal/Terminal.java | 348 + .../core/terminal/TextBuffer.java | 208 + .../server/proxy/CCTurtleProxyServer.java | 24 + .../proxy/ComputerCraftProxyServer.java | 106 + .../shared/common/BlockDirectional.java | 43 + .../shared/common/BlockGeneric.java | 340 + .../shared/common/ClientTerminal.java | 92 + .../DefaultBundledRedstoneProvider.java | 40 + .../shared/common/IDirectionalTile.java | 15 + .../shared/common/ITerminal.java | 15 + .../shared/common/ITerminalTile.java | 12 + .../shared/common/ServerTerminal.java | 100 + .../shared/common/TileGeneric.java | 210 + .../shared/computer/apis/CommandAPI.java | 325 + .../computer/blocks/BlockCommandComputer.java | 147 + .../shared/computer/blocks/BlockComputer.java | 179 + .../computer/blocks/BlockComputerBase.java | 80 + .../computer/blocks/ComputerPeripheral.java | 104 + .../shared/computer/blocks/ComputerState.java | 36 + .../shared/computer/blocks/IComputerTile.java | 20 + .../computer/blocks/TileCommandComputer.java | 182 + .../shared/computer/blocks/TileComputer.java | 111 + .../computer/blocks/TileComputerBase.java | 511 + .../shared/computer/core/ClientComputer.java | 197 + .../computer/core/ClientComputerRegistry.java | 47 + .../shared/computer/core/ComputerFamily.java | 15 + .../computer/core/ComputerRegistry.java | 97 + .../shared/computer/core/IComputer.java | 25 + .../computer/core/IComputerContainer.java | 12 + .../shared/computer/core/ServerComputer.java | 402 + .../computer/core/ServerComputerRegistry.java | 76 + .../computer/inventory/ContainerComputer.java | 27 + .../computer/items/ComputerItemFactory.java | 51 + .../shared/computer/items/IComputerItem.java | 17 + .../computer/items/ItemCommandComputer.java | 76 + .../shared/computer/items/ItemComputer.java | 159 + .../computer/items/ItemComputerBase.java | 114 + .../media/common/DefaultMediaProvider.java | 30 + .../media/inventory/ContainerHeldItem.java | 44 + .../shared/media/items/ItemDiskExpanded.java | 67 + .../shared/media/items/ItemDiskLegacy.java | 158 + .../shared/media/items/ItemPrintout.java | 243 + .../shared/media/items/ItemTreasureDisk.java | 264 + .../shared/media/items/RecordMedia.java | 53 + .../shared/media/recipes/DiskRecipe.java | 167 + .../shared/media/recipes/PrintoutRecipe.java | 160 + .../shared/network/ComputerCraftPacket.java | 227 + .../shared/network/INetworkedThing.java | 13 + .../shared/network/PacketHandler.java | 45 + .../shared/peripheral/PeripheralType.java | 38 + .../commandblock/CommandBlockPeripheral.java | 123 + .../CommandBlockPeripheralProvider.java | 30 + .../shared/peripheral/common/BlockCable.java | 247 + .../common/BlockCableModemVariant.java | 79 + .../peripheral/common/BlockPeripheral.java | 586 ++ .../common/BlockPeripheralBase.java | 73 + .../common/BlockPeripheralVariant.java | 149 + .../common/DefaultPeripheralProvider.java | 57 + .../peripheral/common/IPeripheralItem.java | 15 + .../peripheral/common/IPeripheralTile.java | 19 + .../peripheral/common/ItemAdvancedModem.java | 61 + .../shared/peripheral/common/ItemCable.java | 174 + .../peripheral/common/ItemPeripheral.java | 108 + .../peripheral/common/ItemPeripheralBase.java | 108 + .../common/PeripheralItemFactory.java | 48 + .../peripheral/common/TilePeripheralBase.java | 192 + .../diskdrive/ContainerDiskDrive.java | 85 + .../diskdrive/DiskDrivePeripheral.java | 199 + .../peripheral/diskdrive/TileDiskDrive.java | 683 ++ .../peripheral/modem/BlockAdvancedModem.java | 117 + .../shared/peripheral/modem/INetwork.java | 18 + .../shared/peripheral/modem/IReceiver.java | 20 + .../peripheral/modem/ModemPeripheral.java | 406 + .../peripheral/modem/TileAdvancedModem.java | 84 + .../shared/peripheral/modem/TileCable.java | 1041 +++ .../peripheral/modem/TileModemBase.java | 136 + .../peripheral/modem/TileWirelessModem.java | 127 + .../modem/WirelessModemPeripheral.java | 63 + .../peripheral/modem/WirelessNetwork.java | 104 + .../peripheral/monitor/MonitorPeripheral.java | 250 + .../peripheral/monitor/TileMonitor.java | 865 ++ .../peripheral/printer/ContainerPrinter.java | 161 + .../peripheral/printer/PrinterPeripheral.java | 174 + .../peripheral/printer/TilePrinter.java | 597 ++ .../shared/pocket/apis/PocketAPI.java | 56 + .../pocket/items/ItemPocketComputer.java | 460 + .../items/PocketComputerItemFactory.java | 28 + .../peripherals/PocketModemPeripheral.java | 61 + .../recipes/PocketComputerUpgradeRecipe.java | 137 + .../shared/proxy/CCTurtleProxyCommon.java | 449 + .../proxy/ComputerCraftProxyCommon.java | 665 ++ .../shared/proxy/ICCTurtleProxy.java | 29 + .../shared/proxy/IComputerCraftProxy.java | 45 + .../shared/turtle/apis/TurtleAPI.java | 502 + .../shared/turtle/blocks/BlockTurtle.java | 176 + .../turtle/blocks/BlockTurtleDyeVariant.java | 84 + .../shared/turtle/blocks/ITurtleTile.java | 28 + .../shared/turtle/blocks/TileTurtle.java | 665 ++ .../turtle/blocks/TileTurtleAdvanced.java | 14 + .../turtle/blocks/TileTurtleExpanded.java | 14 + .../shared/turtle/core/InteractDirection.java | 37 + .../shared/turtle/core/MoveDirection.java | 42 + .../shared/turtle/core/TurnDirection.java | 13 + .../turtle/core/TurtleAttackCommand.java | 19 + .../shared/turtle/core/TurtleBrain.java | 1176 +++ .../core/TurtleCheckRedstoneCommand.java | 59 + .../turtle/core/TurtleCommandQueueEntry.java | 21 + .../turtle/core/TurtleCompareCommand.java | 141 + .../turtle/core/TurtleCompareToCommand.java | 38 + .../turtle/core/TurtleCraftCommand.java | 64 + .../turtle/core/TurtleDetectCommand.java | 48 + .../shared/turtle/core/TurtleDigCommand.java | 19 + .../shared/turtle/core/TurtleDropCommand.java | 89 + .../turtle/core/TurtleEquipCommand.java | 92 + .../turtle/core/TurtleInspectCommand.java | 90 + .../shared/turtle/core/TurtleMoveCommand.java | 174 + .../turtle/core/TurtlePlaceCommand.java | 422 + .../shared/turtle/core/TurtlePlayer.java | 94 + .../turtle/core/TurtleRefuelCommand.java | 92 + .../turtle/core/TurtleSelectCommand.java | 28 + .../turtle/core/TurtleSetRedstoneCommand.java | 56 + .../shared/turtle/core/TurtleSuckCommand.java | 161 + .../shared/turtle/core/TurtleToolCommand.java | 75 + .../turtle/core/TurtleTransferToCommand.java | 57 + .../shared/turtle/core/TurtleTurnCommand.java | 47 + .../turtle/entity/TurtleVisionCamera.java | 106 + .../turtle/inventory/ContainerTurtle.java | 181 + .../shared/turtle/items/ITurtleItem.java | 22 + .../turtle/items/ItemTurtleAdvanced.java | 29 + .../shared/turtle/items/ItemTurtleBase.java | 184 + .../shared/turtle/items/ItemTurtleLegacy.java | 152 + .../shared/turtle/items/ItemTurtleNormal.java | 197 + .../turtle/items/TurtleItemFactory.java | 89 + .../shared/turtle/recipes/TurtleRecipe.java | 104 + .../turtle/recipes/TurtleUpgradeRecipe.java | 171 + .../upgrades/CraftingTablePeripheral.java | 94 + .../shared/turtle/upgrades/TurtleAxe.java | 24 + .../turtle/upgrades/TurtleCraftingTable.java | 119 + .../shared/turtle/upgrades/TurtleHoe.java | 60 + .../upgrades/TurtleInventoryCrafting.java | 304 + .../shared/turtle/upgrades/TurtleModem.java | 227 + .../shared/turtle/upgrades/TurtleShovel.java | 43 + .../shared/turtle/upgrades/TurtleSword.java | 43 + .../shared/turtle/upgrades/TurtleTool.java | 306 + .../computercraft/shared/util/Colour.java | 84 + .../shared/util/CreativeTabMain.java | 31 + .../shared/util/CreativeTabTreasure.java | 31 + .../shared/util/DirectionUtil.java | 122 + .../computercraft/shared/util/Holiday.java | 16 + .../shared/util/HolidayUtil.java | 40 + .../computercraft/shared/util/IDAssigner.java | 114 + .../shared/util/IEntityDropConsumer.java | 14 + .../shared/util/ImpostorRecipe.java | 31 + .../shared/util/ImpostorShapelessRecipe.java | 35 + .../shared/util/InventoryUtil.java | 353 + .../computercraft/shared/util/NBTUtil.java | 141 + .../shared/util/PeripheralUtil.java | 20 + .../shared/util/RedstoneUtil.java | 94 + .../shared/util/ReflectionUtil.java | 227 + .../computercraft/shared/util/WorldUtil.java | 167 + .../computercraft/blockstates/CC-Cable.json | 192 + .../blockstates/CC-Computer.json | 34 + .../blockstates/CC-Peripheral.json | 450 + .../computercraft/blockstates/CC-Turtle.json | 72 + .../blockstates/CC-TurtleAdvanced.json | 72 + .../blockstates/CC-TurtleExpanded.json | 72 + .../blockstates/advanced_modem.json | 17 + .../blockstates/command_computer.json | 18 + .../assets/computercraft/lang/en_US.lang | 41 + .../assets/computercraft/lua/bios.lua | 883 ++ .../assets/computercraft/lua/rom/apis/colors | 37 + .../assets/computercraft/lua/rom/apis/colours | 11 + .../lua/rom/apis/command/commands | 46 + .../assets/computercraft/lua/rom/apis/disk | 84 + .../assets/computercraft/lua/rom/apis/gps | 162 + .../assets/computercraft/lua/rom/apis/help | 66 + .../assets/computercraft/lua/rom/apis/io | 182 + .../assets/computercraft/lua/rom/apis/keys | 59 + .../computercraft/lua/rom/apis/paintutils | 200 + .../computercraft/lua/rom/apis/parallel | 61 + .../computercraft/lua/rom/apis/peripheral | 118 + .../assets/computercraft/lua/rom/apis/rednet | 266 + .../computercraft/lua/rom/apis/settings | 100 + .../assets/computercraft/lua/rom/apis/term | 56 + .../computercraft/lua/rom/apis/textutils | 393 + .../computercraft/lua/rom/apis/turtle/turtle | 34 + .../assets/computercraft/lua/rom/apis/vector | 85 + .../assets/computercraft/lua/rom/apis/window | 422 + .../computercraft/lua/rom/autorun/.ignoreme | 4 + .../computercraft/lua/rom/help/adventure | 1 + .../assets/computercraft/lua/rom/help/alias | 6 + .../assets/computercraft/lua/rom/help/apis | 4 + .../assets/computercraft/lua/rom/help/bg | 5 + .../assets/computercraft/lua/rom/help/bit | 7 + .../assets/computercraft/lua/rom/help/bundled | 15 + .../assets/computercraft/lua/rom/help/cd | 6 + .../computercraft/lua/rom/help/changelog | 332 + .../assets/computercraft/lua/rom/help/chat | 5 + .../assets/computercraft/lua/rom/help/clear | 1 + .../assets/computercraft/lua/rom/help/colors | 8 + .../assets/computercraft/lua/rom/help/colours | 8 + .../computercraft/lua/rom/help/commands | 2 + .../computercraft/lua/rom/help/commandsapi | 15 + .../assets/computercraft/lua/rom/help/copy | 6 + .../computercraft/lua/rom/help/coroutine | 2 + .../assets/computercraft/lua/rom/help/craft | 5 + .../assets/computercraft/lua/rom/help/credits | 10 + .../assets/computercraft/lua/rom/help/dance | 1 + .../assets/computercraft/lua/rom/help/delete | 5 + .../assets/computercraft/lua/rom/help/disk | 17 + .../assets/computercraft/lua/rom/help/dj | 6 + .../assets/computercraft/lua/rom/help/drive | 5 + .../assets/computercraft/lua/rom/help/drives | 19 + .../assets/computercraft/lua/rom/help/earth | 1 + .../assets/computercraft/lua/rom/help/edit | 4 + .../assets/computercraft/lua/rom/help/eject | 4 + .../assets/computercraft/lua/rom/help/equip | 4 + .../assets/computercraft/lua/rom/help/events | 15 + .../computercraft/lua/rom/help/excavate | 4 + .../assets/computercraft/lua/rom/help/exec | 7 + .../assets/computercraft/lua/rom/help/exit | 1 + .../assets/computercraft/lua/rom/help/falling | 1 + .../assets/computercraft/lua/rom/help/fg | 5 + .../assets/computercraft/lua/rom/help/fs | 39 + .../assets/computercraft/lua/rom/help/go | 6 + .../assets/computercraft/lua/rom/help/gps | 10 + .../assets/computercraft/lua/rom/help/gpsapi | 4 + .../assets/computercraft/lua/rom/help/hello | 1 + .../assets/computercraft/lua/rom/help/help | 4 + .../assets/computercraft/lua/rom/help/helpapi | 5 + .../assets/computercraft/lua/rom/help/http | 8 + .../assets/computercraft/lua/rom/help/id | 5 + .../assets/computercraft/lua/rom/help/intro | 7 + .../assets/computercraft/lua/rom/help/io | 2 + .../assets/computercraft/lua/rom/help/keys | 9 + .../assets/computercraft/lua/rom/help/label | 9 + .../computercraft/lua/rom/help/licenses/luaj | 19 + .../assets/computercraft/lua/rom/help/list | 1 + .../assets/computercraft/lua/rom/help/lua | 1 + .../assets/computercraft/lua/rom/help/math | 2 + .../assets/computercraft/lua/rom/help/mkdir | 5 + .../assets/computercraft/lua/rom/help/modems | 12 + .../assets/computercraft/lua/rom/help/monitor | 6 + .../computercraft/lua/rom/help/monitors | 21 + .../assets/computercraft/lua/rom/help/move | 6 + .../computercraft/lua/rom/help/multishell | 2 + .../assets/computercraft/lua/rom/help/os | 25 + .../assets/computercraft/lua/rom/help/paint | 4 + .../computercraft/lua/rom/help/paintutils | 7 + .../computercraft/lua/rom/help/parallel | 4 + .../computercraft/lua/rom/help/pastebin | 7 + .../computercraft/lua/rom/help/peripheral | 15 + .../computercraft/lua/rom/help/peripherals | 7 + .../computercraft/lua/rom/help/printers | 12 + .../computercraft/lua/rom/help/programming | 11 + .../computercraft/lua/rom/help/programs | 1 + .../assets/computercraft/lua/rom/help/reboot | 2 + .../computercraft/lua/rom/help/redirection | 2 + .../assets/computercraft/lua/rom/help/rednet | 18 + .../computercraft/lua/rom/help/redstone | 9 + .../computercraft/lua/rom/help/redstoneapi | 19 + .../assets/computercraft/lua/rom/help/refuel | 6 + .../assets/computercraft/lua/rom/help/rename | 4 + .../assets/computercraft/lua/rom/help/repeat | 1 + .../assets/computercraft/lua/rom/help/rs | 19 + .../assets/computercraft/lua/rom/help/set | 6 + .../computercraft/lua/rom/help/settings | 8 + .../assets/computercraft/lua/rom/help/shell | 2 + .../computercraft/lua/rom/help/shellapi | 19 + .../computercraft/lua/rom/help/shutdown | 1 + .../assets/computercraft/lua/rom/help/sleep | 4 + .../assets/computercraft/lua/rom/help/string | 2 + .../assets/computercraft/lua/rom/help/table | 2 + .../assets/computercraft/lua/rom/help/term | 20 + .../computercraft/lua/rom/help/textutils | 10 + .../assets/computercraft/lua/rom/help/time | 1 + .../assets/computercraft/lua/rom/help/tunnel | 4 + .../assets/computercraft/lua/rom/help/turn | 6 + .../assets/computercraft/lua/rom/help/turtle | 48 + .../assets/computercraft/lua/rom/help/type | 1 + .../assets/computercraft/lua/rom/help/unequip | 4 + .../assets/computercraft/lua/rom/help/vector | 17 + .../assets/computercraft/lua/rom/help/wget | 5 + .../computercraft/lua/rom/help/whatsnew | 6 + .../assets/computercraft/lua/rom/help/window | 23 + .../computercraft/lua/rom/help/workbench | 4 + .../assets/computercraft/lua/rom/help/worm | 1 + .../lua/rom/programs/advanced/bg | 12 + .../lua/rom/programs/advanced/fg | 18 + .../lua/rom/programs/advanced/multishell | 306 + .../computercraft/lua/rom/programs/alias | 27 + .../computercraft/lua/rom/programs/apis | 11 + .../assets/computercraft/lua/rom/programs/cd | 14 + .../computercraft/lua/rom/programs/clear | 2 + .../lua/rom/programs/command/commands | 16 + .../lua/rom/programs/command/exec | 40 + .../computercraft/lua/rom/programs/copy | 24 + .../computercraft/lua/rom/programs/delete | 16 + .../computercraft/lua/rom/programs/drive | 21 + .../computercraft/lua/rom/programs/edit | 753 ++ .../computercraft/lua/rom/programs/eject | 18 + .../computercraft/lua/rom/programs/exit | 1 + .../lua/rom/programs/fun/advanced/levels/0 | 8 + .../lua/rom/programs/fun/advanced/levels/1 | 7 + .../lua/rom/programs/fun/advanced/levels/10 | 11 + .../lua/rom/programs/fun/advanced/levels/11 | 10 + .../lua/rom/programs/fun/advanced/levels/12 | 12 + .../lua/rom/programs/fun/advanced/levels/2 | 10 + .../lua/rom/programs/fun/advanced/levels/3 | 10 + .../lua/rom/programs/fun/advanced/levels/4 | 10 + .../lua/rom/programs/fun/advanced/levels/5 | 10 + .../lua/rom/programs/fun/advanced/levels/6 | 11 + .../lua/rom/programs/fun/advanced/levels/7 | 10 + .../lua/rom/programs/fun/advanced/levels/8 | 10 + .../lua/rom/programs/fun/advanced/levels/9 | 12 + .../lua/rom/programs/fun/advanced/paint | 394 + .../lua/rom/programs/fun/advanced/redirection | 705 ++ .../lua/rom/programs/fun/adventure | 1343 +++ .../computercraft/lua/rom/programs/fun/dj | 50 + .../computercraft/lua/rom/programs/fun/hello | 5 + .../computercraft/lua/rom/programs/fun/worm | 291 + .../assets/computercraft/lua/rom/programs/gps | 104 + .../computercraft/lua/rom/programs/help | 29 + .../lua/rom/programs/http/pastebin | 124 + .../computercraft/lua/rom/programs/http/wget | 61 + .../assets/computercraft/lua/rom/programs/id | 30 + .../computercraft/lua/rom/programs/label | 100 + .../computercraft/lua/rom/programs/list | 33 + .../assets/computercraft/lua/rom/programs/lua | 94 + .../computercraft/lua/rom/programs/mkdir | 9 + .../computercraft/lua/rom/programs/monitor | 67 + .../computercraft/lua/rom/programs/move | 24 + .../lua/rom/programs/peripherals | 10 + .../lua/rom/programs/pocket/falling | 651 ++ .../computercraft/lua/rom/programs/programs | 9 + .../computercraft/lua/rom/programs/reboot | 8 + .../lua/rom/programs/rednet/chat | 435 + .../lua/rom/programs/rednet/repeat | 91 + .../computercraft/lua/rom/programs/redstone | 118 + .../computercraft/lua/rom/programs/rename | 9 + .../assets/computercraft/lua/rom/programs/set | 42 + .../computercraft/lua/rom/programs/shell | 349 + .../computercraft/lua/rom/programs/shutdown | 8 + .../computercraft/lua/rom/programs/time | 3 + .../lua/rom/programs/turtle/craft | 33 + .../lua/rom/programs/turtle/dance | 112 + .../lua/rom/programs/turtle/equip | 38 + .../lua/rom/programs/turtle/excavate | 353 + .../computercraft/lua/rom/programs/turtle/go | 53 + .../lua/rom/programs/turtle/refuel | 33 + .../lua/rom/programs/turtle/tunnel | 184 + .../lua/rom/programs/turtle/turn | 38 + .../lua/rom/programs/turtle/unequip | 40 + .../computercraft/lua/rom/programs/type | 18 + .../assets/computercraft/lua/rom/startup | 230 + .../treasure/GopherAtl/battleship/battleship | 875 ++ .../lua/treasure/GravityScore/LuaIDE/luaide | 2212 +++++ .../lua/treasure/JTK/maze3d/maze2d | 327 + .../lua/treasure/JTK/maze3d/maze3d | 614 ++ .../lua/treasure/Lyqyd/nsh/framebuffer | 159 + .../computercraft/lua/treasure/Lyqyd/nsh/get | 26 + .../computercraft/lua/treasure/Lyqyd/nsh/nsh | 721 ++ .../computercraft/lua/treasure/Lyqyd/nsh/put | 35 + .../TheOriginalBIT/tictactoe/tictactoe | 444 + .../treasure/dan200/alongtimeago/alongtimeago | 47 + .../treasure/deprecated/GopherAtl/talk/talk | 1 + .../treasure/fredthead/protector/protector | 1311 +++ .../nitrogenfingers/goldrunner/goldrunner | 1314 +++ .../goldrunner/levels/01_welcome | 18 + .../goldrunner/levels/02_coalmine | 18 + .../goldrunner/levels/03_seeker | 18 + .../goldrunner/levels/04_fortress | 18 + .../goldrunner/levels/05_caged | 18 + .../goldrunner/levels/06_flowers | 18 + .../goldrunner/levels/07_pyramid | 18 + .../goldrunner/levels/08_cavein | 18 + .../goldrunner/levels/09_skyislands | 18 + .../goldrunner/levels/10_convert | 16 + .../nitrogenfingers/npaintpro/3dprint | 119 + .../nitrogenfingers/npaintpro/gameutils | 615 ++ .../nitrogenfingers/npaintpro/npaintpro | 2517 +++++ .../lua/treasure/vilsol/gameoflife/gameoflife | 178 + .../block/advanced_computer_blinking.json | 8 + .../models/block/advanced_computer_off.json | 8 + .../models/block/advanced_computer_on.json | 8 + .../models/block/advanced_modem_off.json | 7 + .../models/block/advanced_modem_on.json | 7 + .../models/block/advanced_monitor.json | 9 + .../models/block/advanced_monitor_d.json | 9 + .../models/block/advanced_monitor_item.json | 8 + .../models/block/advanced_monitor_l.json | 9 + .../models/block/advanced_monitor_ld.json | 9 + .../models/block/advanced_monitor_lr.json | 9 + .../models/block/advanced_monitor_lrd.json | 9 + .../models/block/advanced_monitor_lru.json | 9 + .../models/block/advanced_monitor_lrud.json | 9 + .../models/block/advanced_monitor_lu.json | 9 + .../models/block/advanced_monitor_lud.json | 9 + .../models/block/advanced_monitor_r.json | 9 + .../models/block/advanced_monitor_rd.json | 9 + .../models/block/advanced_monitor_ru.json | 9 + .../models/block/advanced_monitor_rud.json | 9 + .../models/block/advanced_monitor_u.json | 9 + .../models/block/advanced_monitor_ud.json | 9 + .../models/block/advanced_turtle.json | 6 + .../block/advanced_turtle_modem_off_left.json | 6 + .../advanced_turtle_modem_off_right.json | 6 + .../block/advanced_turtle_modem_on_left.json | 6 + .../block/advanced_turtle_modem_on_right.json | 6 + .../computercraft/models/block/cable_arm.json | 18 + .../models/block/cable_core.json | 21 + .../models/block/cable_item.json | 21 + .../block/command_computer_blinking.json | 8 + .../models/block/command_computer_off.json | 8 + .../models/block/command_computer_on.json | 8 + .../models/block/computer_blinking.json | 8 + .../models/block/computer_off.json | 8 + .../models/block/computer_on.json | 8 + .../models/block/disk_drive_empty.json | 8 + .../models/block/disk_drive_full.json | 8 + .../models/block/disk_drive_invalid.json | 8 + .../computercraft/models/block/modem.json | 19 + .../computercraft/models/block/monitor.json | 9 + .../models/block/monitor_base.json | 12 + .../computercraft/models/block/monitor_d.json | 9 + .../models/block/monitor_item.json | 8 + .../computercraft/models/block/monitor_l.json | 9 + .../models/block/monitor_ld.json | 9 + .../models/block/monitor_lr.json | 9 + .../models/block/monitor_lrd.json | 9 + .../models/block/monitor_lru.json | 9 + .../models/block/monitor_lrud.json | 9 + .../models/block/monitor_lu.json | 9 + .../models/block/monitor_lud.json | 9 + .../computercraft/models/block/monitor_r.json | 9 + .../models/block/monitor_rd.json | 9 + .../models/block/monitor_ru.json | 9 + .../models/block/monitor_rud.json | 9 + .../computercraft/models/block/monitor_u.json | 9 + .../models/block/monitor_ud.json | 9 + .../models/block/printer_both_full.json | 8 + .../models/block/printer_bottom_full.json | 8 + .../models/block/printer_empty.json | 8 + .../models/block/printer_top_full.json | 8 + .../computercraft/models/block/turtle.json | 6 + .../models/block/turtle_base.json | 30 + .../models/block/turtle_black.json | 6 + .../models/block/turtle_blue.json | 6 + .../models/block/turtle_brown.json | 6 + .../block/turtle_crafting_table_left.json | 6 + .../block/turtle_crafting_table_right.json | 6 + .../models/block/turtle_cyan.json | 6 + .../models/block/turtle_elf_overlay.json | 6 + .../models/block/turtle_green.json | 6 + .../models/block/turtle_grey.json | 6 + .../models/block/turtle_lightBlue.json | 6 + .../models/block/turtle_lightGrey.json | 6 + .../models/block/turtle_lime.json | 6 + .../models/block/turtle_magenta.json | 6 + .../models/block/turtle_modem_off_left.json | 6 + .../models/block/turtle_modem_off_right.json | 6 + .../models/block/turtle_modem_on_left.json | 6 + .../models/block/turtle_modem_on_right.json | 6 + .../models/block/turtle_orange.json | 6 + .../models/block/turtle_overlay.json | 42 + .../models/block/turtle_pink.json | 6 + .../models/block/turtle_purple.json | 6 + .../models/block/turtle_red.json | 6 + .../block/turtle_upgrade_base_left.json | 18 + .../block/turtle_upgrade_base_right.json | 18 + .../models/block/turtle_white.json | 6 + .../models/block/turtle_yellow.json | 6 + .../models/block/wired_modem_off.json | 7 + .../block/wired_modem_off_peripheral.json | 7 + .../models/block/wired_modem_on.json | 7 + .../block/wired_modem_on_peripheral.json | 7 + .../models/block/wireless_modem_off.json | 7 + .../models/block/wireless_modem_on.json | 7 + .../computercraft/models/item/CC-Cable.json | 14 + .../models/item/CC-Computer.json | 13 + .../models/item/CC-Peripheral.json | 13 + .../computercraft/models/item/CC-Turtle.json | 14 + .../models/item/CC-TurtleAdvanced.json | 14 + .../models/item/CC-TurtleExpanded.json | 14 + .../models/item/advanced_computer.json | 13 + .../models/item/advanced_modem.json | 20 + .../models/item/advanced_monitor.json | 13 + .../advanced_pocket_computer_blinking.json | 18 + ...ced_pocket_computer_blinking_modem_on.json | 19 + .../item/advanced_pocket_computer_off.json | 18 + .../item/advanced_pocket_computer_on.json | 18 + .../advanced_pocket_computer_on_modem_on.json | 19 + .../computercraft/models/item/book.json | 18 + .../models/item/command_computer.json | 13 + .../computercraft/models/item/disk.json | 19 + .../models/item/diskExpanded.json | 19 + .../computercraft/models/item/monitor.json | 13 + .../computercraft/models/item/pages.json | 18 + .../models/item/pocketComputer.json | 18 + .../models/item/pocket_computer_blinking.json | 18 + .../pocket_computer_blinking_modem_on.json | 19 + .../models/item/pocket_computer_on.json | 18 + .../item/pocket_computer_on_modem_on.json | 19 + .../computercraft/models/item/printer.json | 13 + .../computercraft/models/item/printout.json | 18 + .../models/item/treasureDisk.json | 19 + .../models/item/turtle_black.json | 14 + .../models/item/turtle_blue.json | 14 + .../models/item/turtle_brown.json | 14 + .../models/item/turtle_cyan.json | 14 + .../models/item/turtle_elf_overlay.json | 14 + .../models/item/turtle_green.json | 14 + .../models/item/turtle_grey.json | 14 + .../models/item/turtle_lightBlue.json | 14 + .../models/item/turtle_lightGrey.json | 14 + .../models/item/turtle_lime.json | 14 + .../models/item/turtle_magenta.json | 14 + .../models/item/turtle_orange.json | 14 + .../models/item/turtle_pink.json | 14 + .../models/item/turtle_purple.json | 14 + .../computercraft/models/item/turtle_red.json | 14 + .../models/item/turtle_white.json | 14 + .../models/item/turtle_yellow.json | 14 + .../models/item/wired_modem.json | 20 + .../models/item/wireless_modem.json | 20 + .../textures/blocks/advModemFace.png | Bin 0 -> 620 bytes .../textures/blocks/advModemFaceOn.png | Bin 0 -> 580 bytes .../textures/blocks/advMonitor0.png | Bin 0 -> 546 bytes .../textures/blocks/advMonitor1.png | Bin 0 -> 548 bytes .../textures/blocks/advMonitor15.png | Bin 0 -> 414 bytes .../textures/blocks/advMonitor16.png | Bin 0 -> 418 bytes .../textures/blocks/advMonitor17.png | Bin 0 -> 342 bytes .../textures/blocks/advMonitor18.png | Bin 0 -> 263 bytes .../textures/blocks/advMonitor19.png | Bin 0 -> 353 bytes .../textures/blocks/advMonitor2.png | Bin 0 -> 508 bytes .../textures/blocks/advMonitor20.png | Bin 0 -> 365 bytes .../textures/blocks/advMonitor21.png | Bin 0 -> 306 bytes .../textures/blocks/advMonitor22.png | Bin 0 -> 357 bytes .../textures/blocks/advMonitor23.png | Bin 0 -> 282 bytes .../textures/blocks/advMonitor24.png | Bin 0 -> 194 bytes .../textures/blocks/advMonitor25.png | Bin 0 -> 285 bytes .../textures/blocks/advMonitor26.png | Bin 0 -> 234 bytes .../textures/blocks/advMonitor27.png | Bin 0 -> 75 bytes .../textures/blocks/advMonitor28.png | Bin 0 -> 227 bytes .../textures/blocks/advMonitor29.png | Bin 0 -> 294 bytes .../textures/blocks/advMonitor3.png | Bin 0 -> 518 bytes .../textures/blocks/advMonitor30.png | Bin 0 -> 210 bytes .../textures/blocks/advMonitor31.png | Bin 0 -> 292 bytes .../textures/blocks/advMonitor32.png | Bin 0 -> 580 bytes .../textures/blocks/advMonitor33.png | Bin 0 -> 553 bytes .../textures/blocks/advMonitor34.png | Bin 0 -> 542 bytes .../textures/blocks/advMonitor35.png | Bin 0 -> 571 bytes .../textures/blocks/advMonitor36.png | Bin 0 -> 569 bytes .../textures/blocks/advMonitor37.png | Bin 0 -> 545 bytes .../textures/blocks/advMonitor38.png | Bin 0 -> 566 bytes .../textures/blocks/advMonitor39.png | Bin 0 -> 535 bytes .../textures/blocks/advMonitor4.png | Bin 0 -> 580 bytes .../textures/blocks/advMonitor40.png | Bin 0 -> 522 bytes .../textures/blocks/advMonitor41.png | Bin 0 -> 545 bytes .../textures/blocks/advMonitor42.png | Bin 0 -> 556 bytes .../textures/blocks/advMonitor43.png | Bin 0 -> 503 bytes .../textures/blocks/advMonitor44.png | Bin 0 -> 527 bytes .../textures/blocks/advMonitor45.png | Bin 0 -> 563 bytes .../textures/blocks/advMonitor46.png | Bin 0 -> 524 bytes .../textures/blocks/advMonitor47.png | Bin 0 -> 540 bytes .../textures/blocks/advMonitor5.png | Bin 0 -> 566 bytes .../textures/blocks/advMonitor6.png | Bin 0 -> 545 bytes .../textures/blocks/advMonitor7.png | Bin 0 -> 569 bytes .../textures/blocks/cableCore.png | Bin 0 -> 230 bytes .../textures/blocks/cableSide.png | Bin 0 -> 222 bytes .../textures/blocks/commandComputerFront.png | Bin 0 -> 484 bytes .../blocks/commandComputerFrontBlink.png | Bin 0 -> 615 bytes .../commandComputerFrontBlink.png.mcmeta | 6 + .../blocks/commandComputerFrontOn.png | Bin 0 -> 507 bytes .../textures/blocks/commandComputerSide.png | Bin 0 -> 643 bytes .../textures/blocks/commandComputerTop.png | Bin 0 -> 635 bytes .../textures/blocks/computerFront.png | Bin 0 -> 297 bytes .../textures/blocks/computerFrontAdvanced.png | Bin 0 -> 455 bytes .../textures/blocks/computerFrontBlink.png | Bin 0 -> 467 bytes .../blocks/computerFrontBlink.png.mcmeta | 6 + .../blocks/computerFrontBlinkAdvanced.png | Bin 0 -> 534 bytes .../computerFrontBlinkAdvanced.png.mcmeta | 6 + .../textures/blocks/computerFrontOn.png | Bin 0 -> 304 bytes .../blocks/computerFrontOnAdvanced.png | Bin 0 -> 477 bytes .../textures/blocks/computerSide.png | Bin 0 -> 327 bytes .../textures/blocks/computerSideAdvanced.png | Bin 0 -> 584 bytes .../textures/blocks/computerTop.png | Bin 0 -> 290 bytes .../textures/blocks/computerTopAdvanced.png | Bin 0 -> 575 bytes .../textures/blocks/craftyUpgrade.png | Bin 0 -> 312 bytes .../textures/blocks/diskDriveFront.png | Bin 0 -> 327 bytes .../blocks/diskDriveFrontAccepted.png | Bin 0 -> 332 bytes .../blocks/diskDriveFrontRejected.png | Bin 0 -> 333 bytes .../textures/blocks/diskDriveSide.png | Bin 0 -> 327 bytes .../textures/blocks/diskDriveTop.png | Bin 0 -> 290 bytes .../textures/blocks/modemBack.png | Bin 0 -> 273 bytes .../textures/blocks/monitor0.png | Bin 0 -> 290 bytes .../textures/blocks/monitor1.png | Bin 0 -> 278 bytes .../textures/blocks/monitor15.png | Bin 0 -> 278 bytes .../textures/blocks/monitor16.png | Bin 0 -> 273 bytes .../textures/blocks/monitor17.png | Bin 0 -> 238 bytes .../textures/blocks/monitor18.png | Bin 0 -> 178 bytes .../textures/blocks/monitor19.png | Bin 0 -> 233 bytes .../textures/blocks/monitor2.png | Bin 0 -> 259 bytes .../textures/blocks/monitor20.png | Bin 0 -> 250 bytes .../textures/blocks/monitor21.png | Bin 0 -> 208 bytes .../textures/blocks/monitor22.png | Bin 0 -> 242 bytes .../textures/blocks/monitor23.png | Bin 0 -> 191 bytes .../textures/blocks/monitor24.png | Bin 0 -> 117 bytes .../textures/blocks/monitor25.png | Bin 0 -> 191 bytes .../textures/blocks/monitor26.png | Bin 0 -> 155 bytes .../textures/blocks/monitor27.png | Bin 0 -> 75 bytes .../textures/blocks/monitor28.png | Bin 0 -> 155 bytes .../textures/blocks/monitor29.png | Bin 0 -> 204 bytes .../textures/blocks/monitor3.png | Bin 0 -> 279 bytes .../textures/blocks/monitor30.png | Bin 0 -> 145 bytes .../textures/blocks/monitor31.png | Bin 0 -> 198 bytes .../textures/blocks/monitor32.png | Bin 0 -> 327 bytes .../textures/blocks/monitor33.png | Bin 0 -> 314 bytes .../textures/blocks/monitor34.png | Bin 0 -> 290 bytes .../textures/blocks/monitor35.png | Bin 0 -> 312 bytes .../textures/blocks/monitor36.png | Bin 0 -> 306 bytes .../textures/blocks/monitor37.png | Bin 0 -> 286 bytes .../textures/blocks/monitor38.png | Bin 0 -> 310 bytes .../textures/blocks/monitor39.png | Bin 0 -> 287 bytes .../textures/blocks/monitor4.png | Bin 0 -> 327 bytes .../textures/blocks/monitor40.png | Bin 0 -> 258 bytes .../textures/blocks/monitor41.png | Bin 0 -> 288 bytes .../textures/blocks/monitor42.png | Bin 0 -> 263 bytes .../textures/blocks/monitor43.png | Bin 0 -> 222 bytes .../textures/blocks/monitor44.png | Bin 0 -> 266 bytes .../textures/blocks/monitor45.png | Bin 0 -> 290 bytes .../textures/blocks/monitor46.png | Bin 0 -> 261 bytes .../textures/blocks/monitor47.png | Bin 0 -> 287 bytes .../textures/blocks/monitor5.png | Bin 0 -> 310 bytes .../textures/blocks/monitor6.png | Bin 0 -> 286 bytes .../textures/blocks/monitor7.png | Bin 0 -> 306 bytes .../textures/blocks/printerFrontBothTrays.png | Bin 0 -> 327 bytes .../blocks/printerFrontBottomTray.png | Bin 0 -> 337 bytes .../textures/blocks/printerFrontEmpty.png | Bin 0 -> 325 bytes .../textures/blocks/printerFrontTopTray.png | Bin 0 -> 330 bytes .../textures/blocks/printerSide.png | Bin 0 -> 327 bytes .../textures/blocks/printerTop.png | Bin 0 -> 290 bytes .../computercraft/textures/blocks/turtle.png | Bin 0 -> 1869 bytes .../textures/blocks/turtleAdvanced.png | Bin 0 -> 2324 bytes .../textures/blocks/turtle_black.png | Bin 0 -> 1416 bytes .../textures/blocks/turtle_blue.png | Bin 0 -> 2064 bytes .../textures/blocks/turtle_brown.png | Bin 0 -> 1911 bytes .../textures/blocks/turtle_cyan.png | Bin 0 -> 2027 bytes .../textures/blocks/turtle_elf_overlay.png | Bin 0 -> 1941 bytes .../textures/blocks/turtle_green.png | Bin 0 -> 1980 bytes .../textures/blocks/turtle_grey.png | Bin 0 -> 1541 bytes .../textures/blocks/turtle_lightBlue.png | Bin 0 -> 2038 bytes .../textures/blocks/turtle_lightGrey.png | Bin 0 -> 1680 bytes .../textures/blocks/turtle_lime.png | Bin 0 -> 1971 bytes .../textures/blocks/turtle_magenta.png | Bin 0 -> 2057 bytes .../textures/blocks/turtle_orange.png | Bin 0 -> 2114 bytes .../textures/blocks/turtle_pink.png | Bin 0 -> 2073 bytes .../textures/blocks/turtle_purple.png | Bin 0 -> 2047 bytes .../textures/blocks/turtle_red.png | Bin 0 -> 1882 bytes .../textures/blocks/turtle_white.png | Bin 0 -> 1793 bytes .../textures/blocks/turtle_yellow.png | Bin 0 -> 1930 bytes .../textures/blocks/wiredModemFace.png | Bin 0 -> 316 bytes .../textures/blocks/wiredModemFaceOn.png | Bin 0 -> 254 bytes .../blocks/wiredModemFacePeripheral.png | Bin 0 -> 316 bytes .../blocks/wiredModemFacePeripheralOn.png | Bin 0 -> 253 bytes .../textures/blocks/wirelessModemFace.png | Bin 0 -> 324 bytes .../textures/blocks/wirelessModemFaceOn.png | Bin 0 -> 259 bytes .../computercraft/textures/gui/corners.png | Bin 0 -> 974 bytes .../computercraft/textures/gui/corners2.png | Bin 0 -> 989 bytes .../textures/gui/cornersCommand.png | Bin 0 -> 992 bytes .../computercraft/textures/gui/diskdrive.png | Bin 0 -> 2047 bytes .../computercraft/textures/gui/printer.png | Bin 0 -> 1267 bytes .../computercraft/textures/gui/printout.png | Bin 0 -> 3078 bytes .../textures/gui/termBackground.png | Bin 0 -> 123 bytes .../computercraft/textures/gui/termFont.png | Bin 0 -> 2910 bytes .../computercraft/textures/gui/turtle.png | Bin 0 -> 2526 bytes .../computercraft/textures/gui/turtle2.png | Bin 0 -> 1808 bytes .../computercraft/textures/items/book.png | Bin 0 -> 241 bytes .../textures/items/diskColour.png | Bin 0 -> 95 bytes .../textures/items/diskFrame.png | Bin 0 -> 148 bytes .../computercraft/textures/items/page.png | Bin 0 -> 158 bytes .../textures/items/pageBundle.png | Bin 0 -> 206 bytes .../textures/items/pocketComputer.png | Bin 0 -> 216 bytes .../textures/items/pocketComputerAdvanced.png | Bin 0 -> 219 bytes .../textures/items/pocketComputerBlink.png | Bin 0 -> 264 bytes .../items/pocketComputerBlink.png.mcmeta | 6 + .../items/pocketComputerBlinkAdvanced.png | Bin 0 -> 266 bytes .../pocketComputerBlinkAdvanced.png.mcmeta | 6 + .../items/pocketComputerModemLight.png | Bin 0 -> 242 bytes .../textures/items/pocketComputerOn.png | Bin 0 -> 240 bytes .../items/pocketComputerOnAdvanced.png | Bin 0 -> 242 bytes src/main/resources/mcmod.info | 20 + src/main/resources/pack.mcmeta | 6 + src/main/resources/pack.png | Bin 0 -> 499 bytes 1123 files changed, 191332 insertions(+), 3 deletions(-) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 LICENSE-luaj create mode 100644 build.gradle create mode 100755 build_luaj.sh create mode 100755 deploy.sh create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 libs/luaj-jse-2.0.3.jar create mode 100644 luaj-2.0.3/.classpath create mode 100644 luaj-2.0.3/.project create mode 100644 luaj-2.0.3/LICENSE.txt create mode 100644 luaj-2.0.3/README.html create mode 100644 luaj-2.0.3/build-coverage.xml create mode 100644 luaj-2.0.3/build-libs.xml create mode 100644 luaj-2.0.3/build.xml create mode 100644 luaj-2.0.3/docs/api/allclasses-frame.html create mode 100644 luaj-2.0.3/docs/api/allclasses-noframe.html create mode 100644 luaj-2.0.3/docs/api/constant-values.html create mode 100644 luaj-2.0.3/docs/api/deprecated-list.html create mode 100644 luaj-2.0.3/docs/api/help-doc.html create mode 100644 luaj-2.0.3/docs/api/index-all.html create mode 100644 luaj-2.0.3/docs/api/index.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/Buffer.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/LoadState.LuaCompiler.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/LoadState.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/LocVars.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/Lua.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/LuaBoolean.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/LuaClosure.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/LuaDouble.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/LuaError.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/LuaFunction.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/LuaInteger.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/LuaNil.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/LuaNumber.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/LuaString.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/LuaTable.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/LuaThread.CallStack.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/LuaThread.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/LuaUserdata.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/LuaValue.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/OrphanedThread.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/Print.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/Prototype.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/TailcallVarargs.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/UpValue.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/Varargs.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/WeakTable.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/Buffer.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LoadState.LuaCompiler.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LoadState.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LocVars.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/Lua.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaBoolean.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaClosure.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaDouble.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaError.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaFunction.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaInteger.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaNil.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaNumber.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaString.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaTable.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaThread.CallStack.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaThread.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaUserdata.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaValue.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/OrphanedThread.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/Print.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/Prototype.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/TailcallVarargs.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/UpValue.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/Varargs.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/class-use/WeakTable.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/compiler/LuaC.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/compiler/class-use/LuaC.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/compiler/package-frame.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/compiler/package-summary.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/compiler/package-tree.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/compiler/package-use.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/BaseLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/CoroutineLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/DebugLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/IoLib.File.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/IoLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/LibFunction.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/MathLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/OneArgFunction.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/OsLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/PackageLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/ResourceFinder.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/StringLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/TableLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/ThreeArgFunction.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/TwoArgFunction.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/VarArgFunction.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/ZeroArgFunction.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/BaseLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/CoroutineLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/DebugLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/IoLib.File.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/IoLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/LibFunction.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/MathLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/OneArgFunction.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/OsLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/PackageLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/ResourceFinder.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/StringLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/TableLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/ThreeArgFunction.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/TwoArgFunction.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/VarArgFunction.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/ZeroArgFunction.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/JmeIoLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/JmePlatform.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/class-use/JmeIoLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/class-use/JmePlatform.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/package-frame.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/package-summary.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/package-tree.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/package-use.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/CoerceJavaToLua.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/CoerceLuaToJava.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseBaseLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseIoLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseMathLib.JseMathLib1.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseMathLib.JseMathLib2.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseMathLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseOsLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JsePlatform.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseProcess.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/LuajavaLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/CoerceJavaToLua.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/CoerceLuaToJava.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseBaseLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseIoLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseMathLib.JseMathLib1.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseMathLib.JseMathLib2.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseMathLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseOsLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JsePlatform.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseProcess.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/LuajavaLib.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/package-frame.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/package-summary.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/package-tree.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/package-use.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/package-frame.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/package-summary.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/package-tree.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/lib/package-use.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/luajc/LuaJC.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/luajc/class-use/LuaJC.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/luajc/package-frame.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/luajc/package-summary.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/luajc/package-tree.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/luajc/package-use.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/package-frame.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/package-summary.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/package-tree.html create mode 100644 luaj-2.0.3/docs/api/org/luaj/vm2/package-use.html create mode 100644 luaj-2.0.3/docs/api/overview-frame.html create mode 100644 luaj-2.0.3/docs/api/overview-summary.html create mode 100644 luaj-2.0.3/docs/api/overview-tree.html create mode 100644 luaj-2.0.3/docs/api/package-list create mode 100644 luaj-2.0.3/docs/api/resources/inherit.gif create mode 100644 luaj-2.0.3/docs/api/serialized-form.html create mode 100644 luaj-2.0.3/docs/api/stylesheet.css create mode 100644 luaj-2.0.3/examples/jme/SampleMIDlet.java create mode 100644 luaj-2.0.3/examples/jse/SampleJseMain.java create mode 100644 luaj-2.0.3/examples/jse/SampleParser.java create mode 100644 luaj-2.0.3/examples/jse/ScriptEngineSample.java create mode 100644 luaj-2.0.3/examples/jse/hyperbolic.java create mode 100644 luaj-2.0.3/examples/lua/hello.lua create mode 100644 luaj-2.0.3/examples/lua/hyperbolicapp.lua create mode 100644 luaj-2.0.3/examples/lua/logo.gif create mode 100644 luaj-2.0.3/examples/lua/swingapp.lua create mode 100644 luaj-2.0.3/names.csv create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/Buffer.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/LoadState.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/LocVars.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/Lua.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/LuaBoolean.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/LuaClosure.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/LuaDouble.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/LuaError.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/LuaFunction.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/LuaInteger.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/LuaNil.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/LuaNumber.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/LuaString.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/LuaTable.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/LuaThread.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/LuaUserdata.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/LuaValue.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/OrphanedThread.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/Print.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/Prototype.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/TailcallVarargs.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/UpValue.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/Varargs.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/WeakTable.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/compiler/DumpState.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/compiler/FuncState.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/compiler/InstructionPtr.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/compiler/IntPtr.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/compiler/LexState.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/compiler/LuaC.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/lib/BaseLib.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/lib/CoroutineLib.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/lib/DebugLib.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/lib/IoLib.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/lib/LibFunction.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/lib/MathLib.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/lib/OneArgFunction.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/lib/OsLib.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/lib/PackageLib.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/lib/ResourceFinder.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/lib/StringLib.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/lib/TableLib.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/lib/ThreeArgFunction.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/lib/TwoArgFunction.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/lib/VarArgFunction.java create mode 100644 luaj-2.0.3/src/core/org/luaj/vm2/lib/ZeroArgFunction.java create mode 100644 luaj-2.0.3/src/jme/org/luaj/vm2/lib/jme/JmeIoLib.java create mode 100644 luaj-2.0.3/src/jme/org/luaj/vm2/lib/jme/JmePlatform.java create mode 100644 luaj-2.0.3/src/jse/META-INF/services/javax.script.ScriptEngineFactory create mode 100644 luaj-2.0.3/src/jse/lua.java create mode 100644 luaj-2.0.3/src/jse/lua2java.java create mode 100644 luaj-2.0.3/src/jse/luac.java create mode 100644 luaj-2.0.3/src/jse/luajc.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/ast/Block.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/ast/Chunk.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/ast/Exp.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/ast/FuncArgs.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/ast/FuncBody.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/ast/FuncName.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/ast/Name.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/ast/NameResolver.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/ast/NameScope.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/ast/ParList.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/ast/Stat.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/ast/Str.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/ast/TableConstructor.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/ast/TableField.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/ast/Variable.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/ast/Visitor.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/CoerceJavaToLua.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/CoerceLuaToJava.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JavaArray.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JavaClass.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JavaConstructor.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JavaInstance.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JavaMember.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JavaMethod.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JseBaseLib.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JseIoLib.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JseMathLib.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JseOsLib.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JsePlatform.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JseProcess.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/LuajavaLib.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/lua2java/JavaCodeGen.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/lua2java/JavaScope.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/lua2java/Lua2Java.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/luajc/BasicBlock.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/luajc/JavaBuilder.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/luajc/JavaGen.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/luajc/JavaLoader.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/luajc/LuaJC.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/luajc/ProtoInfo.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/luajc/UpvalInfo.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/luajc/VarInfo.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/parser/LuaParser.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/parser/LuaParserConstants.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/parser/LuaParserTokenManager.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/parser/ParseException.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/parser/SimpleCharStream.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/parser/Token.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/parser/TokenMgrError.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/script/LuaScriptEngine.java create mode 100644 luaj-2.0.3/src/jse/org/luaj/vm2/script/LuaScriptEngineFactory.java create mode 100644 luaj-2.0.3/test/java/org/luaj/luajc/TestLuaJ.java create mode 100644 luaj-2.0.3/test/java/org/luaj/luajc/TestLuaJC.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/AllTests.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/CompatibiltyTest.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/ErrorsTest.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/FragmentsTest.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/LuaOperationsTest.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/MathLibTest.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/MetatableTest.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/OrphanedThreadTest.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/RequireClassTest.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/ScriptDrivenTest.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/StringTest.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/TableArrayTest.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/TableHashTest.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/TableTest.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/TypeTest.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/UnaryBinaryOperatorsTest.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/WeakTableTest.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/compiler/AbstractUnitTests.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/compiler/CompilerUnitTests.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/compiler/RegressionTests.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/compiler/SimpleTests.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/lib/jse/LuaJavaCoercionTest.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/lib/jse/LuajavaAccessibleMembersTest.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/lib/jse/LuajavaClassMembersTest.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/lib/jse/TestClass.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/lib/jse/TestInterface.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/require/RequireSampleClassCastExcep.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/require/RequireSampleLoadLuaError.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/require/RequireSampleLoadRuntimeExcep.java create mode 100644 luaj-2.0.3/test/junit/org/luaj/vm2/require/RequireSampleSuccess.java create mode 100644 luaj-2.0.3/test/lua/baselib.lua create mode 100644 luaj-2.0.3/test/lua/coroutinelib.lua create mode 100644 luaj-2.0.3/test/lua/debuglib.lua create mode 100644 luaj-2.0.3/test/lua/errors.lua create mode 100644 luaj-2.0.3/test/lua/errors/args.lua create mode 100644 luaj-2.0.3/test/lua/errors/baselibargs.lua create mode 100644 luaj-2.0.3/test/lua/errors/coroutinelibargs.lua create mode 100644 luaj-2.0.3/test/lua/errors/iolibargs.lua create mode 100644 luaj-2.0.3/test/lua/errors/mathlibargs.lua create mode 100644 luaj-2.0.3/test/lua/errors/modulelibargs.lua create mode 100644 luaj-2.0.3/test/lua/errors/operators.lua create mode 100644 luaj-2.0.3/test/lua/errors/stringlibargs.lua create mode 100644 luaj-2.0.3/test/lua/errors/tablelibargs.lua create mode 100644 luaj-2.0.3/test/lua/foo.log create mode 100644 luaj-2.0.3/test/lua/functions.lua create mode 100644 luaj-2.0.3/test/lua/iolib.lua create mode 100644 luaj-2.0.3/test/lua/luaj2.0-tests.zip create mode 100644 luaj-2.0.3/test/lua/manyupvals.lua create mode 100644 luaj-2.0.3/test/lua/mathlib.lua create mode 100644 luaj-2.0.3/test/lua/metatags.lua create mode 100644 luaj-2.0.3/test/lua/oslib.lua create mode 100644 luaj-2.0.3/test/lua/perf/binarytrees.lua create mode 100644 luaj-2.0.3/test/lua/perf/fannkuch.lua create mode 100644 luaj-2.0.3/test/lua/perf/nbody.lua create mode 100644 luaj-2.0.3/test/lua/perf/nsieve.lua create mode 100644 luaj-2.0.3/test/lua/repack.sh create mode 100644 luaj-2.0.3/test/lua/stringlib.lua create mode 100644 luaj-2.0.3/test/lua/tablelib.lua create mode 100644 luaj-2.0.3/test/lua/tailcalls.lua create mode 100644 luaj-2.0.3/test/lua/upvalues.lua create mode 100644 luaj-2.0.3/test/lua/vm.lua create mode 100644 luaj-2.0.3/version.properties create mode 100644 luaj-2.0.3/wtk.xml create mode 100755 setup.sh create mode 100644 src/main/java/dan200/computercraft/ComputerCraft.java create mode 100644 src/main/java/dan200/computercraft/api/ComputerCraftAPI.java create mode 100644 src/main/java/dan200/computercraft/api/filesystem/IMount.java create mode 100644 src/main/java/dan200/computercraft/api/filesystem/IWritableMount.java create mode 100644 src/main/java/dan200/computercraft/api/filesystem/package-info.java create mode 100644 src/main/java/dan200/computercraft/api/lua/ILuaContext.java create mode 100644 src/main/java/dan200/computercraft/api/lua/ILuaObject.java create mode 100644 src/main/java/dan200/computercraft/api/lua/ILuaTask.java create mode 100644 src/main/java/dan200/computercraft/api/lua/LuaException.java create mode 100644 src/main/java/dan200/computercraft/api/lua/package-info.java create mode 100644 src/main/java/dan200/computercraft/api/media/IMedia.java create mode 100644 src/main/java/dan200/computercraft/api/media/IMediaProvider.java create mode 100644 src/main/java/dan200/computercraft/api/media/package-info.java create mode 100644 src/main/java/dan200/computercraft/api/package-info.java create mode 100644 src/main/java/dan200/computercraft/api/peripheral/IComputerAccess.java create mode 100644 src/main/java/dan200/computercraft/api/peripheral/IPeripheral.java create mode 100644 src/main/java/dan200/computercraft/api/peripheral/IPeripheralProvider.java create mode 100644 src/main/java/dan200/computercraft/api/peripheral/package-info.java create mode 100644 src/main/java/dan200/computercraft/api/permissions/ITurtlePermissionProvider.java create mode 100755 src/main/java/dan200/computercraft/api/permissions/package-info.java create mode 100644 src/main/java/dan200/computercraft/api/redstone/IBundledRedstoneProvider.java create mode 100644 src/main/java/dan200/computercraft/api/redstone/package-info.java create mode 100644 src/main/java/dan200/computercraft/api/turtle/ITurtleAccess.java create mode 100644 src/main/java/dan200/computercraft/api/turtle/ITurtleCommand.java create mode 100644 src/main/java/dan200/computercraft/api/turtle/ITurtleUpgrade.java create mode 100644 src/main/java/dan200/computercraft/api/turtle/TurtleAnimation.java create mode 100644 src/main/java/dan200/computercraft/api/turtle/TurtleCommandResult.java create mode 100644 src/main/java/dan200/computercraft/api/turtle/TurtleSide.java create mode 100644 src/main/java/dan200/computercraft/api/turtle/TurtleUpgradeType.java create mode 100644 src/main/java/dan200/computercraft/api/turtle/TurtleVerb.java create mode 100644 src/main/java/dan200/computercraft/api/turtle/package-info.java create mode 100644 src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java create mode 100644 src/main/java/dan200/computercraft/client/gui/GuiComputer.java create mode 100644 src/main/java/dan200/computercraft/client/gui/GuiDiskDrive.java create mode 100644 src/main/java/dan200/computercraft/client/gui/GuiPocketComputer.java create mode 100644 src/main/java/dan200/computercraft/client/gui/GuiPrinter.java create mode 100644 src/main/java/dan200/computercraft/client/gui/GuiPrintout.java create mode 100644 src/main/java/dan200/computercraft/client/gui/GuiTurtle.java create mode 100644 src/main/java/dan200/computercraft/client/gui/widgets/MousePos.java create mode 100644 src/main/java/dan200/computercraft/client/gui/widgets/Widget.java create mode 100644 src/main/java/dan200/computercraft/client/gui/widgets/WidgetContainer.java create mode 100644 src/main/java/dan200/computercraft/client/gui/widgets/WidgetTerminal.java create mode 100644 src/main/java/dan200/computercraft/client/proxy/CCTurtleProxyClient.java create mode 100644 src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java create mode 100644 src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java create mode 100644 src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java create mode 100644 src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java create mode 100644 src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java create mode 100644 src/main/java/dan200/computercraft/core/apis/BitAPI.java create mode 100644 src/main/java/dan200/computercraft/core/apis/BufferAPI.java create mode 100644 src/main/java/dan200/computercraft/core/apis/FSAPI.java create mode 100644 src/main/java/dan200/computercraft/core/apis/HTTPAPI.java create mode 100644 src/main/java/dan200/computercraft/core/apis/HTTPRequest.java create mode 100644 src/main/java/dan200/computercraft/core/apis/IAPIEnvironment.java create mode 100644 src/main/java/dan200/computercraft/core/apis/ILuaAPI.java create mode 100644 src/main/java/dan200/computercraft/core/apis/OSAPI.java create mode 100644 src/main/java/dan200/computercraft/core/apis/PeripheralAPI.java create mode 100644 src/main/java/dan200/computercraft/core/apis/RedstoneAPI.java create mode 100644 src/main/java/dan200/computercraft/core/apis/TermAPI.java create mode 100644 src/main/java/dan200/computercraft/core/computer/Computer.java create mode 100644 src/main/java/dan200/computercraft/core/computer/ComputerThread.java create mode 100644 src/main/java/dan200/computercraft/core/computer/IComputerEnvironment.java create mode 100644 src/main/java/dan200/computercraft/core/computer/ITask.java create mode 100644 src/main/java/dan200/computercraft/core/computer/MainThread.java create mode 100644 src/main/java/dan200/computercraft/core/filesystem/ComboMount.java create mode 100644 src/main/java/dan200/computercraft/core/filesystem/EmptyMount.java create mode 100644 src/main/java/dan200/computercraft/core/filesystem/FileMount.java create mode 100644 src/main/java/dan200/computercraft/core/filesystem/FileSystem.java create mode 100644 src/main/java/dan200/computercraft/core/filesystem/FileSystemException.java create mode 100644 src/main/java/dan200/computercraft/core/filesystem/IMountedFile.java create mode 100644 src/main/java/dan200/computercraft/core/filesystem/IMountedFileBinary.java create mode 100644 src/main/java/dan200/computercraft/core/filesystem/IMountedFileNormal.java create mode 100644 src/main/java/dan200/computercraft/core/filesystem/JarMount.java create mode 100644 src/main/java/dan200/computercraft/core/filesystem/SubMount.java create mode 100644 src/main/java/dan200/computercraft/core/lua/ILuaMachine.java create mode 100644 src/main/java/dan200/computercraft/core/lua/LuaJLuaMachine.java create mode 100644 src/main/java/dan200/computercraft/core/terminal/Terminal.java create mode 100644 src/main/java/dan200/computercraft/core/terminal/TextBuffer.java create mode 100644 src/main/java/dan200/computercraft/server/proxy/CCTurtleProxyServer.java create mode 100644 src/main/java/dan200/computercraft/server/proxy/ComputerCraftProxyServer.java create mode 100644 src/main/java/dan200/computercraft/shared/common/BlockDirectional.java create mode 100644 src/main/java/dan200/computercraft/shared/common/BlockGeneric.java create mode 100644 src/main/java/dan200/computercraft/shared/common/ClientTerminal.java create mode 100644 src/main/java/dan200/computercraft/shared/common/DefaultBundledRedstoneProvider.java create mode 100644 src/main/java/dan200/computercraft/shared/common/IDirectionalTile.java create mode 100644 src/main/java/dan200/computercraft/shared/common/ITerminal.java create mode 100644 src/main/java/dan200/computercraft/shared/common/ITerminalTile.java create mode 100644 src/main/java/dan200/computercraft/shared/common/ServerTerminal.java create mode 100644 src/main/java/dan200/computercraft/shared/common/TileGeneric.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/blocks/BlockCommandComputer.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputer.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/blocks/ComputerPeripheral.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/blocks/ComputerState.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/blocks/IComputerTile.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/blocks/TileCommandComputer.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/blocks/TileComputer.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/core/ClientComputer.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/core/ClientComputerRegistry.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/core/ComputerFamily.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/core/ComputerRegistry.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/core/IComputer.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/core/IComputerContainer.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/core/ServerComputerRegistry.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputer.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/items/ComputerItemFactory.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/items/IComputerItem.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/items/ItemCommandComputer.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/items/ItemComputer.java create mode 100644 src/main/java/dan200/computercraft/shared/computer/items/ItemComputerBase.java create mode 100644 src/main/java/dan200/computercraft/shared/media/common/DefaultMediaProvider.java create mode 100644 src/main/java/dan200/computercraft/shared/media/inventory/ContainerHeldItem.java create mode 100644 src/main/java/dan200/computercraft/shared/media/items/ItemDiskExpanded.java create mode 100644 src/main/java/dan200/computercraft/shared/media/items/ItemDiskLegacy.java create mode 100644 src/main/java/dan200/computercraft/shared/media/items/ItemPrintout.java create mode 100644 src/main/java/dan200/computercraft/shared/media/items/ItemTreasureDisk.java create mode 100644 src/main/java/dan200/computercraft/shared/media/items/RecordMedia.java create mode 100644 src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java create mode 100644 src/main/java/dan200/computercraft/shared/media/recipes/PrintoutRecipe.java create mode 100644 src/main/java/dan200/computercraft/shared/network/ComputerCraftPacket.java create mode 100644 src/main/java/dan200/computercraft/shared/network/INetworkedThing.java create mode 100644 src/main/java/dan200/computercraft/shared/network/PacketHandler.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/PeripheralType.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheral.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheralProvider.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/common/BlockCable.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/common/BlockCableModemVariant.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/common/BlockPeripheral.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/common/BlockPeripheralBase.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/common/BlockPeripheralVariant.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/common/DefaultPeripheralProvider.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/common/IPeripheralItem.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/common/IPeripheralTile.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/common/ItemAdvancedModem.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/common/ItemCable.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/common/ItemPeripheral.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/common/ItemPeripheralBase.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/common/PeripheralItemFactory.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/common/TilePeripheralBase.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/diskdrive/ContainerDiskDrive.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDrivePeripheral.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/modem/BlockAdvancedModem.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/modem/INetwork.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/modem/IReceiver.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/modem/ModemPeripheral.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/modem/TileAdvancedModem.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/modem/TileCable.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/modem/TileModemBase.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/modem/TileWirelessModem.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/modem/WirelessModemPeripheral.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/modem/WirelessNetwork.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorPeripheral.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/printer/ContainerPrinter.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterPeripheral.java create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java create mode 100644 src/main/java/dan200/computercraft/shared/pocket/apis/PocketAPI.java create mode 100644 src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java create mode 100644 src/main/java/dan200/computercraft/shared/pocket/items/PocketComputerItemFactory.java create mode 100644 src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketModemPeripheral.java create mode 100644 src/main/java/dan200/computercraft/shared/pocket/recipes/PocketComputerUpgradeRecipe.java create mode 100644 src/main/java/dan200/computercraft/shared/proxy/CCTurtleProxyCommon.java create mode 100644 src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java create mode 100644 src/main/java/dan200/computercraft/shared/proxy/ICCTurtleProxy.java create mode 100644 src/main/java/dan200/computercraft/shared/proxy/IComputerCraftProxy.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/blocks/BlockTurtle.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/blocks/BlockTurtleDyeVariant.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/blocks/ITurtleTile.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtleAdvanced.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtleExpanded.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/InteractDirection.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/MoveDirection.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurnDirection.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtleAttackCommand.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtleCheckRedstoneCommand.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtleCommandQueueEntry.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareCommand.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareToCommand.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtleCraftCommand.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtleDetectCommand.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtleDigCommand.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtleInspectCommand.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtleMoveCommand.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtleRefuelCommand.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtleSelectCommand.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtleSetRedstoneCommand.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtleSuckCommand.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtleToolCommand.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtleTransferToCommand.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/core/TurtleTurnCommand.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/entity/TurtleVisionCamera.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/items/ITurtleItem.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtleAdvanced.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtleBase.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtleLegacy.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtleNormal.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/items/TurtleItemFactory.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleRecipe.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/upgrades/CraftingTablePeripheral.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleAxe.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleCraftingTable.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleHoe.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleModem.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleShovel.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSword.java create mode 100644 src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java create mode 100644 src/main/java/dan200/computercraft/shared/util/Colour.java create mode 100644 src/main/java/dan200/computercraft/shared/util/CreativeTabMain.java create mode 100644 src/main/java/dan200/computercraft/shared/util/CreativeTabTreasure.java create mode 100644 src/main/java/dan200/computercraft/shared/util/DirectionUtil.java create mode 100644 src/main/java/dan200/computercraft/shared/util/Holiday.java create mode 100644 src/main/java/dan200/computercraft/shared/util/HolidayUtil.java create mode 100644 src/main/java/dan200/computercraft/shared/util/IDAssigner.java create mode 100644 src/main/java/dan200/computercraft/shared/util/IEntityDropConsumer.java create mode 100644 src/main/java/dan200/computercraft/shared/util/ImpostorRecipe.java create mode 100644 src/main/java/dan200/computercraft/shared/util/ImpostorShapelessRecipe.java create mode 100644 src/main/java/dan200/computercraft/shared/util/InventoryUtil.java create mode 100644 src/main/java/dan200/computercraft/shared/util/NBTUtil.java create mode 100644 src/main/java/dan200/computercraft/shared/util/PeripheralUtil.java create mode 100644 src/main/java/dan200/computercraft/shared/util/RedstoneUtil.java create mode 100644 src/main/java/dan200/computercraft/shared/util/ReflectionUtil.java create mode 100644 src/main/java/dan200/computercraft/shared/util/WorldUtil.java create mode 100644 src/main/resources/assets/computercraft/blockstates/CC-Cable.json create mode 100644 src/main/resources/assets/computercraft/blockstates/CC-Computer.json create mode 100644 src/main/resources/assets/computercraft/blockstates/CC-Peripheral.json create mode 100644 src/main/resources/assets/computercraft/blockstates/CC-Turtle.json create mode 100644 src/main/resources/assets/computercraft/blockstates/CC-TurtleAdvanced.json create mode 100644 src/main/resources/assets/computercraft/blockstates/CC-TurtleExpanded.json create mode 100644 src/main/resources/assets/computercraft/blockstates/advanced_modem.json create mode 100644 src/main/resources/assets/computercraft/blockstates/command_computer.json create mode 100644 src/main/resources/assets/computercraft/lang/en_US.lang create mode 100644 src/main/resources/assets/computercraft/lua/bios.lua create mode 100644 src/main/resources/assets/computercraft/lua/rom/apis/colors create mode 100644 src/main/resources/assets/computercraft/lua/rom/apis/colours create mode 100644 src/main/resources/assets/computercraft/lua/rom/apis/command/commands create mode 100644 src/main/resources/assets/computercraft/lua/rom/apis/disk create mode 100644 src/main/resources/assets/computercraft/lua/rom/apis/gps create mode 100644 src/main/resources/assets/computercraft/lua/rom/apis/help create mode 100644 src/main/resources/assets/computercraft/lua/rom/apis/io create mode 100644 src/main/resources/assets/computercraft/lua/rom/apis/keys create mode 100644 src/main/resources/assets/computercraft/lua/rom/apis/paintutils create mode 100644 src/main/resources/assets/computercraft/lua/rom/apis/parallel create mode 100644 src/main/resources/assets/computercraft/lua/rom/apis/peripheral create mode 100644 src/main/resources/assets/computercraft/lua/rom/apis/rednet create mode 100644 src/main/resources/assets/computercraft/lua/rom/apis/settings create mode 100644 src/main/resources/assets/computercraft/lua/rom/apis/term create mode 100644 src/main/resources/assets/computercraft/lua/rom/apis/textutils create mode 100644 src/main/resources/assets/computercraft/lua/rom/apis/turtle/turtle create mode 100644 src/main/resources/assets/computercraft/lua/rom/apis/vector create mode 100644 src/main/resources/assets/computercraft/lua/rom/apis/window create mode 100644 src/main/resources/assets/computercraft/lua/rom/autorun/.ignoreme create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/adventure create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/alias create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/apis create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/bg create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/bit create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/bundled create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/cd create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/changelog create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/chat create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/clear create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/colors create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/colours create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/commands create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/commandsapi create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/copy create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/coroutine create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/craft create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/credits create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/dance create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/delete create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/disk create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/dj create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/drive create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/drives create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/earth create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/edit create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/eject create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/equip create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/events create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/excavate create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/exec create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/exit create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/falling create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/fg create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/fs create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/go create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/gps create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/gpsapi create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/hello create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/help create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/helpapi create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/http create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/id create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/intro create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/io create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/keys create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/label create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/licenses/luaj create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/list create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/lua create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/math create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/mkdir create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/modems create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/monitor create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/monitors create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/move create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/multishell create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/os create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/paint create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/paintutils create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/parallel create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/pastebin create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/peripheral create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/peripherals create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/printers create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/programming create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/programs create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/reboot create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/redirection create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/rednet create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/redstone create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/redstoneapi create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/refuel create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/rename create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/repeat create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/rs create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/set create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/settings create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/shell create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/shellapi create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/shutdown create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/sleep create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/string create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/table create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/term create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/textutils create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/time create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/tunnel create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/turn create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/turtle create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/type create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/unequip create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/vector create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/wget create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/whatsnew create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/window create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/workbench create mode 100644 src/main/resources/assets/computercraft/lua/rom/help/worm create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/advanced/bg create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/advanced/fg create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/advanced/multishell create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/alias create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/apis create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/cd create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/clear create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/command/commands create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/command/exec create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/copy create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/delete create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/drive create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/edit create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/eject create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/exit create mode 100755 src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/0 create mode 100755 src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/1 create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/10 create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/11 create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/12 create mode 100755 src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/2 create mode 100755 src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/3 create mode 100755 src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/4 create mode 100755 src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/5 create mode 100755 src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/6 create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/7 create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/8 create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/9 create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/paint create mode 100755 src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/redirection create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/fun/adventure create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/fun/dj create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/fun/hello create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/fun/worm create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/gps create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/help create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/http/pastebin create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/http/wget create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/id create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/label create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/list create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/lua create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/mkdir create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/monitor create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/move create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/peripherals create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/pocket/falling create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/programs create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/reboot create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/rednet/chat create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/rednet/repeat create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/redstone create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/rename create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/set create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/shell create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/shutdown create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/time create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/turtle/craft create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/turtle/dance create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/turtle/equip create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/turtle/excavate create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/turtle/go create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/turtle/refuel create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/turtle/tunnel create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/turtle/turn create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/turtle/unequip create mode 100644 src/main/resources/assets/computercraft/lua/rom/programs/type create mode 100644 src/main/resources/assets/computercraft/lua/rom/startup create mode 100755 src/main/resources/assets/computercraft/lua/treasure/GopherAtl/battleship/battleship create mode 100644 src/main/resources/assets/computercraft/lua/treasure/GravityScore/LuaIDE/luaide create mode 100644 src/main/resources/assets/computercraft/lua/treasure/JTK/maze3d/maze2d create mode 100644 src/main/resources/assets/computercraft/lua/treasure/JTK/maze3d/maze3d create mode 100755 src/main/resources/assets/computercraft/lua/treasure/Lyqyd/nsh/framebuffer create mode 100755 src/main/resources/assets/computercraft/lua/treasure/Lyqyd/nsh/get create mode 100755 src/main/resources/assets/computercraft/lua/treasure/Lyqyd/nsh/nsh create mode 100755 src/main/resources/assets/computercraft/lua/treasure/Lyqyd/nsh/put create mode 100644 src/main/resources/assets/computercraft/lua/treasure/TheOriginalBIT/tictactoe/tictactoe create mode 100644 src/main/resources/assets/computercraft/lua/treasure/dan200/alongtimeago/alongtimeago create mode 100755 src/main/resources/assets/computercraft/lua/treasure/deprecated/GopherAtl/talk/talk create mode 100755 src/main/resources/assets/computercraft/lua/treasure/fredthead/protector/protector create mode 100644 src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/goldrunner create mode 100644 src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/01_welcome create mode 100644 src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/02_coalmine create mode 100644 src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/03_seeker create mode 100644 src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/04_fortress create mode 100644 src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/05_caged create mode 100644 src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/06_flowers create mode 100644 src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/07_pyramid create mode 100644 src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/08_cavein create mode 100644 src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/09_skyislands create mode 100644 src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/10_convert create mode 100644 src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/npaintpro/3dprint create mode 100644 src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/npaintpro/gameutils create mode 100644 src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/npaintpro/npaintpro create mode 100755 src/main/resources/assets/computercraft/lua/treasure/vilsol/gameoflife/gameoflife create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_computer_blinking.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_computer_off.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_computer_on.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_modem_off.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_modem_on.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_monitor.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_monitor_d.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_monitor_item.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_monitor_l.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_monitor_ld.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_monitor_lr.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_monitor_lrd.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_monitor_lru.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_monitor_lrud.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_monitor_lu.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_monitor_lud.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_monitor_r.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_monitor_rd.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_monitor_ru.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_monitor_rud.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_monitor_u.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_monitor_ud.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_turtle.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_turtle_modem_off_left.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_turtle_modem_off_right.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_turtle_modem_on_left.json create mode 100644 src/main/resources/assets/computercraft/models/block/advanced_turtle_modem_on_right.json create mode 100644 src/main/resources/assets/computercraft/models/block/cable_arm.json create mode 100644 src/main/resources/assets/computercraft/models/block/cable_core.json create mode 100644 src/main/resources/assets/computercraft/models/block/cable_item.json create mode 100644 src/main/resources/assets/computercraft/models/block/command_computer_blinking.json create mode 100644 src/main/resources/assets/computercraft/models/block/command_computer_off.json create mode 100644 src/main/resources/assets/computercraft/models/block/command_computer_on.json create mode 100644 src/main/resources/assets/computercraft/models/block/computer_blinking.json create mode 100644 src/main/resources/assets/computercraft/models/block/computer_off.json create mode 100644 src/main/resources/assets/computercraft/models/block/computer_on.json create mode 100644 src/main/resources/assets/computercraft/models/block/disk_drive_empty.json create mode 100644 src/main/resources/assets/computercraft/models/block/disk_drive_full.json create mode 100644 src/main/resources/assets/computercraft/models/block/disk_drive_invalid.json create mode 100644 src/main/resources/assets/computercraft/models/block/modem.json create mode 100644 src/main/resources/assets/computercraft/models/block/monitor.json create mode 100644 src/main/resources/assets/computercraft/models/block/monitor_base.json create mode 100644 src/main/resources/assets/computercraft/models/block/monitor_d.json create mode 100644 src/main/resources/assets/computercraft/models/block/monitor_item.json create mode 100644 src/main/resources/assets/computercraft/models/block/monitor_l.json create mode 100644 src/main/resources/assets/computercraft/models/block/monitor_ld.json create mode 100644 src/main/resources/assets/computercraft/models/block/monitor_lr.json create mode 100644 src/main/resources/assets/computercraft/models/block/monitor_lrd.json create mode 100644 src/main/resources/assets/computercraft/models/block/monitor_lru.json create mode 100644 src/main/resources/assets/computercraft/models/block/monitor_lrud.json create mode 100644 src/main/resources/assets/computercraft/models/block/monitor_lu.json create mode 100644 src/main/resources/assets/computercraft/models/block/monitor_lud.json create mode 100644 src/main/resources/assets/computercraft/models/block/monitor_r.json create mode 100644 src/main/resources/assets/computercraft/models/block/monitor_rd.json create mode 100644 src/main/resources/assets/computercraft/models/block/monitor_ru.json create mode 100644 src/main/resources/assets/computercraft/models/block/monitor_rud.json create mode 100644 src/main/resources/assets/computercraft/models/block/monitor_u.json create mode 100644 src/main/resources/assets/computercraft/models/block/monitor_ud.json create mode 100644 src/main/resources/assets/computercraft/models/block/printer_both_full.json create mode 100644 src/main/resources/assets/computercraft/models/block/printer_bottom_full.json create mode 100644 src/main/resources/assets/computercraft/models/block/printer_empty.json create mode 100644 src/main/resources/assets/computercraft/models/block/printer_top_full.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_base.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_black.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_blue.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_brown.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_crafting_table_left.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_crafting_table_right.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_cyan.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_elf_overlay.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_green.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_grey.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_lightBlue.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_lightGrey.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_lime.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_magenta.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_modem_off_left.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_modem_off_right.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_modem_on_left.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_modem_on_right.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_orange.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_overlay.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_pink.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_purple.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_red.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_upgrade_base_left.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_upgrade_base_right.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_white.json create mode 100644 src/main/resources/assets/computercraft/models/block/turtle_yellow.json create mode 100644 src/main/resources/assets/computercraft/models/block/wired_modem_off.json create mode 100644 src/main/resources/assets/computercraft/models/block/wired_modem_off_peripheral.json create mode 100644 src/main/resources/assets/computercraft/models/block/wired_modem_on.json create mode 100644 src/main/resources/assets/computercraft/models/block/wired_modem_on_peripheral.json create mode 100644 src/main/resources/assets/computercraft/models/block/wireless_modem_off.json create mode 100644 src/main/resources/assets/computercraft/models/block/wireless_modem_on.json create mode 100644 src/main/resources/assets/computercraft/models/item/CC-Cable.json create mode 100644 src/main/resources/assets/computercraft/models/item/CC-Computer.json create mode 100644 src/main/resources/assets/computercraft/models/item/CC-Peripheral.json create mode 100644 src/main/resources/assets/computercraft/models/item/CC-Turtle.json create mode 100644 src/main/resources/assets/computercraft/models/item/CC-TurtleAdvanced.json create mode 100644 src/main/resources/assets/computercraft/models/item/CC-TurtleExpanded.json create mode 100644 src/main/resources/assets/computercraft/models/item/advanced_computer.json create mode 100644 src/main/resources/assets/computercraft/models/item/advanced_modem.json create mode 100644 src/main/resources/assets/computercraft/models/item/advanced_monitor.json create mode 100644 src/main/resources/assets/computercraft/models/item/advanced_pocket_computer_blinking.json create mode 100644 src/main/resources/assets/computercraft/models/item/advanced_pocket_computer_blinking_modem_on.json create mode 100644 src/main/resources/assets/computercraft/models/item/advanced_pocket_computer_off.json create mode 100644 src/main/resources/assets/computercraft/models/item/advanced_pocket_computer_on.json create mode 100644 src/main/resources/assets/computercraft/models/item/advanced_pocket_computer_on_modem_on.json create mode 100644 src/main/resources/assets/computercraft/models/item/book.json create mode 100644 src/main/resources/assets/computercraft/models/item/command_computer.json create mode 100644 src/main/resources/assets/computercraft/models/item/disk.json create mode 100644 src/main/resources/assets/computercraft/models/item/diskExpanded.json create mode 100644 src/main/resources/assets/computercraft/models/item/monitor.json create mode 100644 src/main/resources/assets/computercraft/models/item/pages.json create mode 100644 src/main/resources/assets/computercraft/models/item/pocketComputer.json create mode 100644 src/main/resources/assets/computercraft/models/item/pocket_computer_blinking.json create mode 100644 src/main/resources/assets/computercraft/models/item/pocket_computer_blinking_modem_on.json create mode 100644 src/main/resources/assets/computercraft/models/item/pocket_computer_on.json create mode 100644 src/main/resources/assets/computercraft/models/item/pocket_computer_on_modem_on.json create mode 100644 src/main/resources/assets/computercraft/models/item/printer.json create mode 100644 src/main/resources/assets/computercraft/models/item/printout.json create mode 100644 src/main/resources/assets/computercraft/models/item/treasureDisk.json create mode 100644 src/main/resources/assets/computercraft/models/item/turtle_black.json create mode 100644 src/main/resources/assets/computercraft/models/item/turtle_blue.json create mode 100644 src/main/resources/assets/computercraft/models/item/turtle_brown.json create mode 100644 src/main/resources/assets/computercraft/models/item/turtle_cyan.json create mode 100644 src/main/resources/assets/computercraft/models/item/turtle_elf_overlay.json create mode 100644 src/main/resources/assets/computercraft/models/item/turtle_green.json create mode 100644 src/main/resources/assets/computercraft/models/item/turtle_grey.json create mode 100644 src/main/resources/assets/computercraft/models/item/turtle_lightBlue.json create mode 100644 src/main/resources/assets/computercraft/models/item/turtle_lightGrey.json create mode 100644 src/main/resources/assets/computercraft/models/item/turtle_lime.json create mode 100644 src/main/resources/assets/computercraft/models/item/turtle_magenta.json create mode 100644 src/main/resources/assets/computercraft/models/item/turtle_orange.json create mode 100644 src/main/resources/assets/computercraft/models/item/turtle_pink.json create mode 100644 src/main/resources/assets/computercraft/models/item/turtle_purple.json create mode 100644 src/main/resources/assets/computercraft/models/item/turtle_red.json create mode 100644 src/main/resources/assets/computercraft/models/item/turtle_white.json create mode 100644 src/main/resources/assets/computercraft/models/item/turtle_yellow.json create mode 100644 src/main/resources/assets/computercraft/models/item/wired_modem.json create mode 100644 src/main/resources/assets/computercraft/models/item/wireless_modem.json create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advModemFace.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advModemFaceOn.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor0.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor1.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor15.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor16.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor17.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor18.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor19.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor2.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor20.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor21.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor22.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor23.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor24.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor25.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor26.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor27.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor28.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor29.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor3.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor30.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor31.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor32.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor33.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor34.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor35.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor36.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor37.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor38.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor39.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor4.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor40.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor41.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor42.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor43.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor44.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor45.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor46.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor47.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor5.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor6.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/advMonitor7.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/cableCore.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/cableSide.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/commandComputerFront.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/commandComputerFrontBlink.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/commandComputerFrontBlink.png.mcmeta create mode 100644 src/main/resources/assets/computercraft/textures/blocks/commandComputerFrontOn.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/commandComputerSide.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/commandComputerTop.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/computerFront.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/computerFrontAdvanced.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/computerFrontBlink.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/computerFrontBlink.png.mcmeta create mode 100644 src/main/resources/assets/computercraft/textures/blocks/computerFrontBlinkAdvanced.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/computerFrontBlinkAdvanced.png.mcmeta create mode 100644 src/main/resources/assets/computercraft/textures/blocks/computerFrontOn.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/computerFrontOnAdvanced.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/computerSide.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/computerSideAdvanced.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/computerTop.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/computerTopAdvanced.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/craftyUpgrade.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/diskDriveFront.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/diskDriveFrontAccepted.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/diskDriveFrontRejected.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/diskDriveSide.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/diskDriveTop.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/modemBack.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor0.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor1.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor15.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor16.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor17.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor18.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor19.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor2.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor20.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor21.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor22.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor23.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor24.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor25.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor26.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor27.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor28.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor29.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor3.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor30.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor31.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor32.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor33.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor34.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor35.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor36.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor37.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor38.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor39.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor4.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor40.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor41.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor42.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor43.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor44.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor45.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor46.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor47.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor5.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor6.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/monitor7.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/printerFrontBothTrays.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/printerFrontBottomTray.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/printerFrontEmpty.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/printerFrontTopTray.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/printerSide.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/printerTop.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/turtle.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/turtleAdvanced.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/turtle_black.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/turtle_blue.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/turtle_brown.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/turtle_cyan.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/turtle_elf_overlay.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/turtle_green.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/turtle_grey.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/turtle_lightBlue.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/turtle_lightGrey.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/turtle_lime.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/turtle_magenta.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/turtle_orange.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/turtle_pink.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/turtle_purple.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/turtle_red.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/turtle_white.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/turtle_yellow.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/wiredModemFace.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/wiredModemFaceOn.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/wiredModemFacePeripheral.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/wiredModemFacePeripheralOn.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/wirelessModemFace.png create mode 100644 src/main/resources/assets/computercraft/textures/blocks/wirelessModemFaceOn.png create mode 100644 src/main/resources/assets/computercraft/textures/gui/corners.png create mode 100644 src/main/resources/assets/computercraft/textures/gui/corners2.png create mode 100644 src/main/resources/assets/computercraft/textures/gui/cornersCommand.png create mode 100644 src/main/resources/assets/computercraft/textures/gui/diskdrive.png create mode 100644 src/main/resources/assets/computercraft/textures/gui/printer.png create mode 100644 src/main/resources/assets/computercraft/textures/gui/printout.png create mode 100644 src/main/resources/assets/computercraft/textures/gui/termBackground.png create mode 100644 src/main/resources/assets/computercraft/textures/gui/termFont.png create mode 100644 src/main/resources/assets/computercraft/textures/gui/turtle.png create mode 100644 src/main/resources/assets/computercraft/textures/gui/turtle2.png create mode 100644 src/main/resources/assets/computercraft/textures/items/book.png create mode 100644 src/main/resources/assets/computercraft/textures/items/diskColour.png create mode 100644 src/main/resources/assets/computercraft/textures/items/diskFrame.png create mode 100644 src/main/resources/assets/computercraft/textures/items/page.png create mode 100644 src/main/resources/assets/computercraft/textures/items/pageBundle.png create mode 100644 src/main/resources/assets/computercraft/textures/items/pocketComputer.png create mode 100644 src/main/resources/assets/computercraft/textures/items/pocketComputerAdvanced.png create mode 100644 src/main/resources/assets/computercraft/textures/items/pocketComputerBlink.png create mode 100644 src/main/resources/assets/computercraft/textures/items/pocketComputerBlink.png.mcmeta create mode 100644 src/main/resources/assets/computercraft/textures/items/pocketComputerBlinkAdvanced.png create mode 100644 src/main/resources/assets/computercraft/textures/items/pocketComputerBlinkAdvanced.png.mcmeta create mode 100644 src/main/resources/assets/computercraft/textures/items/pocketComputerModemLight.png create mode 100644 src/main/resources/assets/computercraft/textures/items/pocketComputerOn.png create mode 100644 src/main/resources/assets/computercraft/textures/items/pocketComputerOnAdvanced.png create mode 100644 src/main/resources/mcmod.info create mode 100755 src/main/resources/pack.mcmeta create mode 100644 src/main/resources/pack.png diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..d56dcf1a7c --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +build +out +run +deploy +*.ipr +*.iws +*.iml +.gradle diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..f5314a6d9e --- /dev/null +++ b/LICENSE @@ -0,0 +1,98 @@ +ComputerCraft Public License +============================ + +Version 1.0.0 (Based on Minecraft Mod Public License 1.0.1) + +0. Definitions +-------------- + +Minecraft: Denotes a copy of the PC Java version of the game “Minecraft” licensed by Mojang AB + +User: Anybody that interacts with the software in one of the following ways: + - play + - decompile + - recompile or compile + - modify + - distribute + +Mod: The mod code designated by the present license, in source form, binary +form, as obtained standalone, as part of a wider distribution or resulting from +the compilation of the original or modified sources. + +Dependency: Code required for the mod to work properly. This includes +dependencies required to compile the code as well as any file or modification +that is explicitly or implicitly required for the mod to be working. + +1. Scope +-------- + +The present license is granted to any user of the mod. As a prerequisite, +a user must own a legally acquired copy of Minecraft + +2. Liability +------------ + +This mod is provided 'as is' with no warranties, implied or otherwise. The owner +of this mod takes no responsibility for any damages incurred from the use of +this mod. This mod alters fundamental parts of the Minecraft game, parts of +Minecraft may not work with this mod installed. All damages caused from the use +or misuse of this mad fall on the user. + +3. Play rights +-------------- + +The user is allowed to install this mod on a Minecraft client or server and to play +without restriction. + +4. Modification rights +---------------------- + +The user has the right to decompile the source code, look at either the +decompiled version or the original source code, and to modify it. + +5. Distribution of original or modified copy rights +--------------------------------------------------- + +Is subject to distribution rights this entire mod in its various forms. This +include: + - original binary or source forms of this mod files + - modified versions of these binaries or source files, as well as binaries + resulting from source modifications + - patch to its source or binary files + - any copy of a portion of its binary source files + +The user is allowed to redistribute this mod partially, in totality, or +included in a distribution. + +When distributing binary files, the user must provide means to obtain its +entire set of sources or modified sources at no cost. + +All distributions of this mod must remain licensed under the CCPL. + +All dependencies that this mod have on other mods or classes must be licensed +under conditions comparable to this version of CCPL, with the exception of the +Minecraft code and the mod loading framework (e.g. Forge). + +Modified version of binaries and sources, as well as files containing sections +copied from this mod, should be distributed under the terms of the present +license. + +7. Use of mod code and assets in other projects +----------------------------------------------- + +It is permitted to use the code and assets contained in this mod (and modified +versions thereof) in other Minecraft Mods, provided they are non-commercial. +However: the code and assets may not be used in commercial mods, mods for other +games, other games, other non-game projects, or any commercial projects. + +When using code covered by this license in other projects, the source code used +must be made available at no cost and remain licensed under the CCPL. + +8. Contributing +--------------- + +If you choose to contribute code or assets to be included in this mod, you +agree that, if added to to the main repository at +https://github.com/dan200/ComputerCraft, your contributions will be covered by +this license, and that Daniel Ratcliffe will retain the right to re-license the +mod, including your contributions, in part or in whole, under other licenses. diff --git a/LICENSE-luaj b/LICENSE-luaj new file mode 100644 index 0000000000..2cc1808644 --- /dev/null +++ b/LICENSE-luaj @@ -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. \ No newline at end of file diff --git a/README.md b/README.md index 7e0787c380..af193bcc14 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,25 @@ ComputerCraft ============= -Issue tracker for ComputerCraft and ComputerCraftEdu -* http://www.computercraft.info -* http://www.computercraftedu.com +ComputerCraft is a Minecraft modification which adds programmable Robots and Computers to the world of Minecraft. +If you're not familiar with ComputerCraft, visit the [Website](http://www.computercraft.info/download) or the [Wiki](http://www.computercraft.info/wiki) to find out more. + +About this Repository +===================== + +ComputerCraft was originally released in late 2011 by [Daniel Ratcliffe](https://twitter.com/DanTwoHundred). In early 2017, after working on the mod solo for five years, it was decided to release the source code publicly to allow Dan to devote time to other projects. This repository marks the first public release of this source code. + +The code in this repository will always represent the "bleeding edge" of the ComputerCraft codebase, but stable builds back to 1.79 will be marked on the [Releases](https://github.com/dan200/ComputerCraft/releases) page. + +Contributing +============ + +While ComputerCraft will no longer be actively developed by Daniel Ratcliffe, you may still contribute pull requests which will be reviewed and incorporated into releases periodically. A pull requests is more likely to be accepted if it meets the following criteria: + +* It does not add any new dependencies for compiling, running or using the mod. +* It does not break compatibility with world saves or programs created with previous versions of the mod. +* It does not add unneccessary complexity for users of the mod, and maintains the accessibility for which the mod is known. +* It does not add unneccessary complexity or stylistic changes to the code, especially where functionality is not being changed. +* It does not create bugs! + +The pull requests most likely to be accepted are those which fix bugs, simplify code, or make the mod compatible with newer versions of Minecraft. diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000000..54599037f2 --- /dev/null +++ b/build.gradle @@ -0,0 +1,85 @@ + +// For those who want the bleeding edge +buildscript { + repositories { + jcenter() + maven { + name = "forge" + url = "http://files.minecraftforge.net/maven" + } + } + dependencies { + classpath 'net.minecraftforge.gradle:ForgeGradle:2.1-SNAPSHOT' + } +} +apply plugin: 'net.minecraftforge.gradle.forge' + +/* +// for people who want stable - not yet functional for MC 1.8.8 - we require the forgegradle 2.1 snapshot +plugins { + id "net.minecraftforge.gradle.forge" version "2.0.2" +} +*/ + +version = "1.79" +group = "dan200.computercraft" +archivesBaseName = "ComputerCraft" + +minecraft { + version = "1.8.9-11.15.0.1715" + runDir = "run" + replace '${version}', project.version + + // the mappings can be changed at any time, and must be in the following format. + // snapshot_YYYYMMDD snapshot are built nightly. + // stable_# stables are built at the discretion of the MCP team. + // Use non-default mappings at your own risk. they may not allways work. + // simply re-run your setup task after changing the mappings to update your workspace. + mappings = "snapshot_20151224" + // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. +} + +dependencies { + // you may put jars on which you depend on in ./libs + // or you may define them like so.. + //compile "some.group:artifact:version:classifier" + //compile "some.group:artifact:version" + + // real examples + //compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env + //compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env + + // the 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime. + //provided 'com.mod-buildcraft:buildcraft:6.0.8:dev' + + // the deobf configurations: 'deobfCompile' and 'deobfProvided' are the same as the normal compile and provided, + // except that these dependencies get remapped to your current MCP mappings + //deobfCompile 'com.mod-buildcraft:buildcraft:6.0.8:dev' + //deobfProvided 'com.mod-buildcraft:buildcraft:6.0.8:dev' + + // for more info... + // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html + // http://www.gradle.org/docs/current/userguide/dependency_management.html + +} + +processResources +{ + // this will ensure that this task is redone when the versions change. + inputs.property "version", project.version + inputs.property "mcversion", project.minecraft.version + + // replace stuff in mcmod.info, nothing else + from(sourceSets.main.resources.srcDirs) { + include 'mcmod.info' + + // replace version and mcversion + expand 'version':project.version, 'mcversion':project.minecraft.version + } + + // copy everything else, thats not the mcmod.info + from(sourceSets.main.resources.srcDirs) { + exclude 'mcmod.info' + } +} + diff --git a/build_luaj.sh b/build_luaj.sh new file mode 100755 index 0000000000..b3aaf0871d --- /dev/null +++ b/build_luaj.sh @@ -0,0 +1,12 @@ +#!/bin/sh +cd luaj-2.0.3 +echo "Building LuaJ..." +ant clean +ant + +echo "Copying output to libs..." +rm ../libs/luaj-jse-2.0.3.jar +cp luaj-jse-2.0.3.jar ../libs + +echo "Done." +cd .. diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000000..0ce941a6ff --- /dev/null +++ b/deploy.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +echo "Building with gradle..." +rm -rf build/libs +rm -rf build/resources +rm -rf build/classes +chmod -R +rw src/main/resources +chmod +x gradlew +./gradlew build + +echo "Deleting old deployment..." +rm -rf deploy +mkdir deploy + +echo "Making new deployment..." +INPUTJAR=`ls -1 build/libs | grep -v sources` +OUTPUTJAR=`ls -1 build/libs | grep -v sources | sed s/\-//g` +FRIENDLYNAME=`ls -1 build/libs | grep -v sources | sed s/\-/\ /g | sed s/\.jar//g` +cp build/libs/$INPUTJAR deploy/$OUTPUTJAR + +echo "Creating API..." +mkdir -p deploy/api/src/dan200/computercraft +cp -r build/sources/main/java/dan200/computercraft/api deploy/api/src/dan200/computercraft/api + +echo "Creating API Javadocs..." +mkdir -p deploy/api/doc +cd src/main/java/dan200/computercraft/api +find . -type f -name "*.java" | xargs javadoc -d ../../../../../../deploy/api/doc -windowtitle "$FRIENDLYNAME" +cd ../../../../../.. + +echo "Adding API and Javadocs to deployment..." +cd deploy +zip -r $OUTPUTJAR api/doc > /dev/null +zip -r $OUTPUTJAR api/src/dan200/computercraft > /dev/null +cd .. +rm -rf deploy/api + +echo "Adding LuaJ to deployment..." +mkdir deploy/luaj +cd deploy/luaj +jar xf ../../libs/luaj-jse-2.0.3.jar +zip -r ../$OUTPUTJAR org > /dev/null +cd ../.. +rm -rf deploy/luaj + +echo "Done." diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..30d399d8d2bf522ff5de94bf434a7cc43a9a74b5 GIT binary patch literal 52271 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 p \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/libs/luaj-jse-2.0.3.jar b/libs/luaj-jse-2.0.3.jar new file mode 100644 index 0000000000000000000000000000000000000000..b05ee77450bdb45a27bca9e8e03e235d837aa4b1 GIT binary patch literal 290203 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 =)b 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%0A)U_8ckQ^>P(F&-z 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

lmwEI?i8Pb*sXq#!W094D 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%0D^A_kj>KJVVa*INbEM3O89nBZokQMq5j=aJ zxM^JuEGw)jtEK@JEc=l7u^>s#_!l_uJm@oD+_Yo?4kLHw^1&hqox(ta;>#TEng|_+ z@umr4PZmAEgaCwbd5xN&G5Bk2GQHs#%Bj+*+_(pX(yPyxbwuX#opWx%|k0vJ%QTmZFm zYiR~9@LFI5cettWV!a_uXapJ**4 zn4fHIF!)QZ{u-)Xv|f_!g-WJQwLUl44SMCeFrm?2tDmR~Y?FS?lwf1{#dH1e3YsoY zY^mq1S+Twx%m;@sA24DG?t@_XVtUV~Z~{(e@DyCydt}boq^aar2lMg^V1Rn%_PW!D z@)z|A9QyshkVs%@FEC-!?-Wz1Ovv6nqz8-gsUGMa`~3n)ibvct(X-7djlAN1@|$$(*w96 zeqmX@Gke%}CuGF$dDZ)S8Uj9`cXmYug}L(g{@#s2Lfv5c5(yxn_%f}42O}c;R_uiZ zV?qna-R%cMf)NtGAqOX*b!**`CdtjoYB)U+cZ=Pr04Bi@VGM2x^Bcs2HK7csJ=6Az z!3g8*W$U3xXidQgVQ+#6>EF1jM_~no?@Z_Lfr3o=Ke-HQ?xP4gf9Jx2=aape0m`8S z(6d{i{k!)T=ZcBg^%~uLc`#Vn1XK^3sIWavD(Klrab(C8tfR;V>19cyq*!)Dq69cG zVB5y>oPtqAqAbw^DJ~ADjb$XJ656Wq(Cy)CaF$ztz+SP#JIYe_$iZ?YWeX0l|hF5$tD1-%>vSxT$}LprNVz@pSx z9%L&>@#NI^*!}ZLcE=Us$teA=e-Oos_tUj6vj(40c-GOR(Gtqc%owX@BRNAAp+lk*3lFsE`Z%s$S|Z83XdulLi*`-WujmW1Eneo0cOb=CJ~hLI+iU%x`j^}FGmK+ zfjg1P;&GM36&JBEW2eo9ja1lK01c`nJoe&0?5#Q|6S^_cxde_{g8VpjhSzWmU1aS9 z@$6(LBN*W+HS`SzK^dUeP=Oppt^<#U_ZBkYT!D--;mIf)_9*yC;FW7Xg3l(9oxEk; z;A!V>TkUVro|H_ApD5Hd%s~|82?EDPpA=brWlsbuG%ym-*OlU+qOROx zubDR+62sNbvR=!)ja=*_UI2m6HXVH;UuA0x(?PM0`v%hzVe4jFYAh(_Xr{1h%~-oO z7v82J;+S6#b`1%R(%NUDC(8lvstf92+QM>x9=#Zx=}ZGd@~sDE5I3v#u-%(S@MNly zs$j^nzsotN-$(jwLzGQp)(7^?(MFL4w+o(3N6!i+aZnt~p*JyoZ-H9S&eqg7HSYC< z*cMh)(PRz1_w#m^B$1Z$MQHVmikiaGLMvJ*`ZK$hnf8uITX?G7veCnNC#aIM;WnLf zP<8>#5#j87U;%_<;^_fx6?Z0TCT4z=7*0^cRJ&crQX1_BksNt8has^&r0m?8v9SmD>M(Sb-CnKL1d8Fe*Y*v?W@+*lA5 zrQWsrm)^z;m}s?lexgE1ixNGkNogKCSo$i=h7jp3@qW%V^LBC-LEJ_0@-sSSRiP0x z;uYgoFqpIyH!bg($JIBJ{&29%e$lePqeO88C!;V8sh1ghy)Cr(>1c|99wd2SYy)TG zc5XZwhA3gSGjj8KVQDtX{$VVrQd%qP8bzA27S$}0`MW7k#!59Llr2(K;d<#v+`s&w z=rbxJ1yraMTxUReJ%#V@P9Q3W^ND!*UP#yu4Ug#n>QvtKYVI8@yt;d*5#ChS5j;1# z_|82h3Acwu9>3_DMQh&eqDB5E=Uj?2om`H^Cf5xqW98HGC+3<`@@9gxqD2arzkdJJ zR&$h!pkH`+^u;wV*`kMWa2Bm|L@3ype$AcN#3g2)`$9*o-wP2HJgUAWxc0`1k_o7v zmfxe}2iPVV{Y6i_! z1*GsCWd|mEa@}$MDZ11;P9|_>+i{M~cF1DK1;D%xRUE+Nmv9 z>;|LiJ5R!+g=;>|E)?2o5PFUz+lL8sbr_>kdfM5j0)$*rd>D96r~S!56%pAV3+oLu03G@#DOQ$8d60 zINnJJ5z5QYRLZ3>Z!o6JtmF}XYzC+tscI1c&xlk|x7=~j!_}L!2lCjrV}?`t_ZYX* zob9A6$CrQ2M+E{o|`u<*J z7T(;s-;=>!3(UqyYB~Vz?hjf9C{(TpXk9KWw)Qik8`ZF>le&Jq4|4*{okm7G&I0=uq?QQ^p_teF&bX563)!wMV=>+o>Visk(*+Ss|FO4zMgw zOJ!`1>h`VbU!&l$IO^(;A2DAyIy|C?-y>33ErvF?Z@(wBXzp?WlNb$))`m=FKY%t) zLGO{f#i7D7_7uUIH5U^o%fT7Rpx40D6XF1RyJYcuAb4a!%d^HWG7d|zMgi}SNV&&C zm#aT$pYkE+d3UZOH{LZ~+(yS=C#u-Rzx1CPxw|8dkR9=Xf_LXM^tIX5k2QE#l>yr7 zEC!Z#jIxtu7^~`+p9oh-_FS^RGZYAgHp`Fi>OupMd|l+J*4YU0Tt$ER+EeE(wuD=Z z01m^eaBxWMvFU9O;JK`pC&<(sDh4daUn}kj*mup-RMA6p%6ZR7`$g4zwtl7ac#(c! zpktC$Oz5gp9vWL~W0Oo`@7Y{$;^^YX)Wv~ckTeK&ci=?C4X3PuA4Zsth|+a8Hp`uQ zJlL`$@O0yTee-vVmMhLty7@EmpsyZ;$yxxXG?h;q{$Lhg??2o+Gj2dtStOYhc|pgY zr;Xu$BN}n_1_@R?M!fOBks)4wT0Tj~Ij;Uixbg`VKrp~cOh&5nrn}Z-GEqfk`hL)c zHI5*+Iay)Q2BUzP1eS>tj23k@X~2US6A|jr$GMg8s%68#*flT19+`+EAEagewHBwq zg*jMwyruV6_Bi@R5GNQPtVjA2arhgki-jv!0rbNlt4pEGp85~(K(7Y-H>vUyF0GkM zFr-Aex2h{!uQ$El2*-eo0+3~2T!q_xV2QluhEPAHW4YUGed}gk@5|Y~n`iQc^I5>K zwFw-eHdUfj?wHKmhajue22`SR8m?%By1^UjQL}cD<;(j@ZbMckm{k7;?i5+k8C-Hb zDXp(Ap}6A-o0OdjYV0Oq|5Y4f{s8W?q9Kqw(*DMC!Whs$^3N5VHJtk!bEXSP1oyiT zOul(Vn*IEfJaxcX`)G z?uAoOxnbk5`uj7ofS~h!N1|bHfyM5p-{^a1+eoYhpm>_5-Q-F*R*8Agiz-ebj)iTP zn(Dh~wTAYtsp-U$I?im36v<$bZO9~y_#&sbMzq;biFONScl;1NGxo8#lSYK7yWurxd#h=ZBgOm6CP5^u#Eid{0e}H7M9WG? zm{4L{*osy|lST?PT)0!4$Vtz3>H;k6!uwaZZ{Xl(Iff$(%{=+@Pf_ZC$@rpr+T`w+ zTVoy1uM~_RW1(K@3mN#IJQ7pDJMULkvS~ntc#x5Io?5m(Kk8NNW<<4iw;Qf=zb&|v zGo-+<8_uYEW7c$B83JxoyY{8je21W${~2Gmn-*8~>#sgL;{kuT-{z3XJUcvh)aonv zNncAeu#sP>K(Ryc^-sb=k)cB~Y!5dJ>ga8X_a1U-ejYJ;{(63->3Roc zGe*lWjG2&GALzPY)49p=9>r1O>e(*LDZrb6m^8EbfL+6mJB$^kxbUXp$YRHcGXu8+ zoz)?Cx-)$Eq+}Z1CmK|5C^5|B#AQMb$ z^2Q^Gy}X=LSRVHw+fRdHVf%Cn+KYK%cikSIpD!I;IMaY227O5DtXqU{wb@&47l zPBEX9c{!qNSIa|PNEe;DFuPGTHK6?f5m7&!l%I$lL6}PS)z{a;B9c&+!*M2g1Iv6F z*h2)jjRavFaXcdzZeEwfgq75FIzsZOfK0_^;-6ql&?l%X3Bo3J2}O(ps5zGTR6=ts zG3$x0O?OjUwzZO5asGQVm`yKY9rM}giU6>;M%mHbuL*Y=D9FROqNp|ctB{OZ!W+fg z9$_`v8MP+OcXt*xx|J)Y$o~TU{^0(Ds|ok#jdj$#H<3f~dOITi{5-Lg!582thX}D*)bw3I<^t zxdr*_H(6$$o+s`2KH`B-VU=(Le@E*BHH$gyy$E|t?om4doQ8YK;V~+kye(zYgrAvC zOI81}blEMXXviBA=$l=H8!;~VtPqx=#SP`?9W?iYG6E0adiK7n4FG1IEhrhsJ2|wG z1IqF-_DmF@B)?DM-HU`al`wBO$*a9%Mo+q1wQk|=#u$l1m|tdLvt*uO|~;uPTkq~`sX11YIc zE<^p7OhCN3C{xVhM$}2Nl7oQoqb-ywY+6^YCvsy5&x~e zhOqfC?#?0#XkpGkd-8#{#*kR1QEL@`cy3Ggq)5j!X;fJ=4WOo1x5UFw?lQDWyfVIi z0rOp(U+Io-`Y5nqZYBvG(N7&Pn|duznK&t_XdYSq`#RpaEHT!567xy%9{e{tBY#aw z?N{|nb_r1Q!>a<|LsPWK1v~Nmc!yFwA=}A(tvJT@9g~Ya0{=o))G>16nS!s$iBDMQ z`LEiO?RgY-Ro`{x$WuU8kK95enttxl&zb0j4+p+QhaCI2iGgHxEXo~LPdofRh>3LW zBd$$PZQnXSaM3-O*dtkFD?oJvnxYF%f*;Sa2oh8Jqdf)Uoilwv_a`QTC$T&0oXA$E z!rzo4AJdppLC0Fq87V!F0xkPx+x>di=uegCpUaa$$mf9T1N)zzv18go5yK zj@5*nPPjs6Ge+zMisekS41;C>;R9RF08VnKJR!)VjDto z`ZK;6UUPMSBAh%eP^h#3hnDt%1Qv$K&bma=nmorf`>1uf?h@CfS}Qhv1`S_%E}ku4 z?!1B?FA@5P9a8XgM>@rT#EmuTvlqTu>at%ij3uTkYP=F=)?PO20nVT!BO2x@FeX-8 zG6v=^dWMG(shcN-heHMz$(%;4u zoNYQR*ib0@65lXr!u1)YMh>b>eH!mxvMiuEOX;+kX|fh0>9PtF^biaYz_iXsv~odu z)~rueaMjkBw6VPB`Y@(o{l$r2FvSqIYbEd?y|vr5TW zmj$nt>uIzxxbfYEWbbKR?n(4rc)qQcw^mWFGH_DdU6;SLVay<9}B z3BA(fr>Hx|(0^pr4Sl<0PhB3;n>7t9Q`;vKos#q~2&Jt)%O8Fh+pTX&I9W*lAYkyn zRrmiP*Pn#^vwIVydo%~Z)r2UmAAwI18;DVUEVy5JcVu@rZZouN#(_PaT6o(+J0SY$-S26t-0l6{ zu$9sc;uFqSBeMKs+RGHm2zOn_x`1Hac>fSCH_-5O#y&pj2oAtMkH$mP3|@Jn>YSV9X`PuJ}F72El)+$ zhqLpFaZfUILxN`#taML1+IEG-c0ddpiL9z-n=Oe>f2uCxQO+ErsxM9eNCnu_ckWiS zJW9XhU_{yYNAV}vAmE19jJCt zK1(19Nr+F+Oj_6$dL}`C)yDiAB1aYy#xO-KAo=T`DNdbZ zrQefPqM%hE#-L}w1)1SeiDOAQo)erL^SVazVA&Y-=lX9UBY0NGLLX)D+= znzJU2GU;3T(rCrBuUOc3Ij$dK10l+hGTtdGJU1=L$d3T9P1z{Il+O48XqG;-Y(d-AP5*Rey{cq=4gh(NZ z=&4Iur}oW@ZS`4~;@f9<<9APOt`)|)=mDeevA`L<<*}e?##xanpl>E7);VfH2K<%~ z@sE5i4|l2@t(E4%g(|<1L1kW;F^tlIqcZA5HA4rFtG;7dZ(jaa0e61qG_)pHpcTF= zNFrK<$bwGH+9^--KHgk2!UI+P-rqhG;u^-&yY*j0;B zMJl-=mN}AItcyX=S{*N_Jgy)4nq473wgL`(*`wEfZjjEWi=P)cMnP3X<=J`=zluStCr6gZi`ecNE+An! zXLbCgciR*m<5E)YTYuH#{DL%%!S zGyZ6TN1Je$bZO%7S)bY*lNbl(s`%}e2vm-y)|KY3tCqx0hCA2;ZfTTmf6u}5^|FwK zXPlQNC}R-6>rkVSxH%_32sq3FI4#|687UxMsC}9H;lP5qvZiQMABuo)!Zy}dCx=Dm z<4Zzdc=HLQ!}IzyYR3p%=a2kipK4a`7*};6E}U$kWT~!k)}N&^F^!^uG6rBC;~T5W{y*57M)okaDG+`gc=ct|3gdHA zti3}#30%h(`TC7`=K_~%aE}~tP5XOG-#{Rj=KMmnjVr|Fz%NuEz3+c{{xRXe5i;g?hkYs20>D*z)$*EsD} zY=Z;z@owVeeuZxOQI6af)2PiKWQQCGq9M*nO1mEj(JvrGEZ|E)!*Z|Qt`ikD7rTW_opfDO@TJKnixdHCzAUKhC&GUYe9-8YM8pr z@1`iNVC3J}`_?388W{c=YbgdnhPU`(p{K(0y9eU`VG|djyH1KLcVoQGtUlyF{;NVh zn7DgQ!S_JpifjiAgdiA#Qc25&KWkwv4kD8krZ zyw6=HsyzE^m+Lj(_~qYrhoQK>a9`;^Ai>?kOF{ z56rJN@hPBRlOeRc%rdwIpP1MRqI3x>qJvN^;+^`-ZIzw!%gXAC#3|?GL!tp93S}9> ze&F4P(9g?ChN66CG)rxRA0bMDV7CdtTeEv#$`!nYH^H5_7v+Wi5ErKfJBZJ)N_|kz zlS+Lc&$EU8@OOP-@9-6UA@7)T-^6oY=u3p6U$zy3LGNu!0T9oGKn^%d0m0q`O9A2D z97_RV-uT>^D+4kD?vQhL8#OX*Cg-XbilC;X!I$+?iDk{d(9LB_UR_=ot>DHDPU59T+AqerT zQ)e+VW20-><*dDbW(7Vnn)A9in@v%k_j5kFUUPoUo^F3#kI(i2MH*`ggK46}P>MhrsL%RfM*KfIEWUbL<$~#Wq}`pupHTixy7HV;|Z**2Y3(r?Bj# z-1o*(yK~g+fo>%;4{|iI2&6Jo9=67MVM}9snE8^K7D9lGjg!EY^^y^j6Vn&$hc_4x z{R%&v!k}BFo6?FuK7j>U3boG$S2W=P8Cr6gH$b1`%40M$?I>zM+0?p>!;Z&|VI40B zoa;=|VQ(z6ug(Oy7}Y#G(VD4mYOroITGv*AE?e`{Bd$N^Mk{cZrzJcjPBbtYYozxO z>o+^v{Y=AE@2uiG&q3ZxI9)vYy4p6`VPDisB(h9TYI4`&+BRnxjTwpZYDq;SO=H0? z@2M+~c*x#q-8NrrQK5Oi?~E4sP1EVDJWT#n>50ya&L0VFRVif~T*+e2^LHy;J26o? zX}B>kDBukF?Ahe5Qz9xh)7|G8fn_&66dk>4?2lGR4GCg4k3rs$6>|zR|CbxOhcG$R z`iaHlLaXh}?q97iP|d(O`O-_N4g4LIy_m@iGe}h$nKh+`D0-FNauZx$5Z`g~5ti8X zSahsk*tVv0<5<|q8H)9#2Lw$HU%RQ+7I~D+9nB_XXA@aawvM9D&V@-PemayrWi+Jf zm6@DGm=j0KAXwF|&vtTPQns+wo=-NukHsKIEn&VChrg?%p&heXud8LJpCwVQiV}~f z=AKF&J2HV86E^9#p4}D|d=9m^N6{s_BiQ0kN$&q8+8m?6xDSq@PfOb*Da@;7JFQRW zQ{_jg{lGu{)9dwFC-eRv#?CRivtZ5FVaK*@+qS!7+qRRA{f}*QY^!72wr%_7%*R=s+DzlJCDIGW{Q1LYk?ZWuLB-j<}cBn4O>nISFCb=<9DngjUI zch3_RLdW{`3N{!u!er6;0vJ|Z{L;;zfZt~#ArK1;zJNh=VhAVjg!n~cbD1R~h41{P0KNAulYhe z`b{{&UZfGB*P@Ni%uf;@R)QavVmOszm_wo%PA<*$Cww)`Rl3z%x-;Fq@tTB-RQbljJl%yQhSJH}0*KaA2i!rMSC^hAlQ!y>Ztq3-0)(i z=YJCiDbykNl>P2c4F5J`Z2#A)LM01rC# z#cDyo|Dd6}(CC&4cQnj^74S>;2HMeB>*FkwwZk-ZiEa5@kNjyIg!t_zFv?lK5h7Y+ z&CGH%KF(ow$kYDzHZ`ROq|6)h%@K&;WLLMTYwIb)?Zc*KqAYP7ouG7V87N;vZX%rr zOP1Ag8)`a%3@Z}soqwph>tU>nJaokKb{n=XKR1$OTCd=RPJ%bV(r9k|4 z5DdgPBBcDuJ$6mF22%S-#e`pSPcY3Is?V(GPDv6T$&9R?TpIwxtg1nFE!k^?<-%(G zCoZYB56WVn4AJ2fWL4VkA!ajwB1)sFdo+rI@4J;O{#u#P310>|8_IafL`>fY7#O67 zS&!brb0fI}_(%GR(w4bx&br8jU)A4rYe!D~3FXWzO+vP2D}R|gPoeBim^A(jM5r4C z-(zUr_R|$oJ$T5gmtImT?V=AfO)5x2N%rDQLCOUqu*7YqfC}M?Ug?mgEnd=EKsi6X z5VHOjYvO|l8}%?5NBI`g%CAHcFae=a?-11I0QZn50m2)i1r%Dj8xMjmx!_jkM$e#Q zHHN5w-`ZKEBD4DCK`m0$$QkIZml#s7V#JxK{E;jTlCqUM^i}>}_)oR+O@d93pM51Q zp#Lu1marAa=?@JAgoOG(VOjq76ZSt=<$o?mfSQLs>H*r9&x+jR+Qj~=Un~kF*!uZl zw|yAcG-<$(_*|XH!AN=b1Y?8LmCH%;!KOuYO9U;iHDN6qK4}Cil31|9{EmjkC!Ole zMNKcg$N5eU9)HASqpxS5tBk9Tr;evXy!x1~`|V#qbh~wk{Lvr4-o)RPJF%e(!P|Ys zBA7iLz~1CRK$kH2m^pCzyg@%*odo*)f#5^T`B3}8$kWoHcNxiF&i#dX!$@FrV7BuJ zqjwEV-AVnXLVt$8VRjPUh=nsSy_keZr0p>!e@YW|Mhszf4pMhcLTtr87xgy_Qw}v_ zb@pBBgj@w*`@9qS5rj+!5d>cw@gk9)N-f@#Dk(5MpeiY_JT&yPAPdAjm-bJQ`qJOP zgzHJaOYdrg>&fs^+~9;Ck@?cx1oU5#`ZC-=gbPT&OYKe}|Bibu@82T*q`yH3#~}Np zx?u?aE%Pq1+lBm<;4ZamLPZ!HORNB$gX&9lTSys8OcSLAg(by8?1=)ol(aI9|FmMpEjzM!;TMB?pxN~o< z5{PDs30A4Rl0q?{K~O{CEoqIX`Eii`%I0dNrNhgp+V2>d^0c9{p+IYrePbMxe-x6P z+x28{vg+{?lj?FaFXosIi^8C(AGR0(KPN?!JuRomeRO(WTB;>N$3&4-6O!5^jU`WR zf+P}Wf(d%^8Dv6{r6bjLL+#%Si^ZB>d_RxqfI531Pi%YAzC21;es_%g-BMXJ!~JnA zs^xi4s?*3h`MI!Gn&-(p|K?zkZl=kuqL+;+*quU>)x_Jh;>LeiNfbWG>6Hdl$~sF zhBvFovVk+3mv)dbo$X_3uo=z+;GNe%3{FbtB{w9n+|xnj0DkVo?p${+0eofPahgs_ zgEs9H2_4CVOTX2$wB4fiq!)wC7;P`M4Em`?DZ&ruRa3JqCT{065=2NkO6o*C>r-TO zk}<+Oc5weD{-Mrh9=<-=9o}rE#c-lmlEH0X!v2fd zT{CGL#vErZRCJX_aWSk7X^td=HC9@=fo>C3Ku|)P0lu8EXR+lyNsLhM%eX;@v)i2u zHoMMZ>mVUawlqxRl<1SVsr7@j$`=v^AubCSpZODRIwKs;!9xpNtKG-4s|`oc4FNuC zmg8pp0|L&mNTmW1=%LiJNX^m^&FhKCTfOhh-bk=wvERdc3_Ij*Koibw+tvTQyt>`= zUK4q(DxAGm9_4J{hnzMc{k&-VF=Uv$oHi-DB2-pS&#Q(`rcoOeA^l=MS-wmkj(uPV zhhcLF-?AKlVhs)E+<5&$kiQQ*FQxLSI4cp~Ei7s+IiZHxn|+w2M}jW`Y_43$B!r>J|pA zOu_@gvy=7#+-|-CXjAgD0{UhpxLj{;WO7C+23+fV2~=x&ZDuYn@TKGl?;l20e+`OO zNDP}-ssczy+UZsgNDO{!E3`+cnx<%}XlFb0k+VS8DTUG#K2O7q{cBJq2nBr%DWJ z3GV?dY54_g2hUVT`kaQ4(qqsRR63(J1NXr^x{-CV-Db(|%yvP`cslr8F@?aW$@zV1 zK2-uu5x6I_R4MheyXqeKTAO4Q_qt2E(#i4)1w{)UOVJuwyIki9sBn?)vzm`1VM<)$kHJ)wf(@ysBv)0B8xx!dr>~F;LY9kq(xhq}up(TCZ@bTAv z9cXnRo|9dkV4C4o=&uZ7SSer@g{d+{DEZkpbzB&n#-_!%sWX% z5W`<#?WBnD?wS~@=84vrlUcNHau%Iuc9|sY-7uCEDgBER{7bJiQ?%cw24mpY7U}T* zpiioR4gQUqM16>h#83z2%u;!=7uw56Hao76lHMOv=!uS*BB=(^ba;aou*ri)7Z4hE z9WH;BxC-bIksQ?82$O6NYDY}Nzi*JTb9p zKKi0gCrJHidR`QZuBxtTML{D)FSX4QT}?nCeR`+b$E8j_o`GX))Mzz_8!_SKlD|B< zda}ImZ0>=vY#+b`|3vuL#;sB$vQ(DuCO*nZUQCpalg@;&iv@yUFXyB$FE5edq+#lj-_>0ikjNN5d!0*OOJ*AobD?U0^y+_!s0 zs`%pxx0x^$L`6kmW$cYah4I8&F;Q-m`&lruosLR^OfSy|IES(knW%QbMJ77)-6&kh z64I1hRYF3ZqwA`JTn3h*88j^>ma$Ds4&-stneqzZ)?{j$8fBk=0vT+JntMG}SD>!0 z;2lhc`3WdYLQuJBqs&800Zg)Q)lQwbZ*_%kX?c$8vPh9-aubpOr%PDAPv$By@-@J+ zWCB6LX?9_nxVUIkp6#sUscFc%nTpk#Z1}fS9BIxE3>a%W-c-7#G%^`vBou zcRE(~tTXYfA~tvW!hK?T@(nf&EUm1@adQH#5t1F}a(t9YMJ68EAE*IE!$I9eVlb5z zy44+~2-oKm6?$am#hS@!cl?j71I*RQN*Im4S=WX9iAT9$K_&jNdnDsgGp9QnTy;zG z-MxyfQTNa%W>5Rj2yd5_HV7<1u5hf7^rpKCMWJ*VM*Fr=`if(Xq}PIZ{v@{eOi;FnzA2swod_|!#M;D$B#oI0 zn>LfyCanTT8ZWOhA>6mBlQEbNVFR6H5A>3e-zyH!0z~0ux#ffCN223qn5R<-eK^Ce z7IZm`ohk!w`qbrT5U}!Jo{4Mp_BmV2zY-Rc*2|Ts<^Fhb$90&vS4kMvjwwkM92WjY z-nMUl=?89b&8%V#X;2cf!?0D#a7j2UxRTb)0O>KR5j@63^Y1j`1o2Sz1^tbArG2}* zski-yfY2Tj)>}dhesbzr*)Nt-P_@n0EX@L`W9(f?8r;E8oD1IflL$_j zk^+=VQOcNCUToq3iEB=Cw?kzrh3Wi~II?M|zx4ArEI< zMbE`+gH%|N%G>W%;|CP1y=?gW2#cf=hEE&q0=xco+u18@=DmIgX3LO)fJpz3k&S7rY`Dr2lH<}Z-<^&6J9J| zUMzRVN>2ii`fzuiHE3_V%LppM1R-RiNGQ2d_69*5;#^$aQrf*jxX5v_j6ZZl6?-{# z2g7^9N5aX7$#xm5@ptwqDTYYX_kJKTpkF&eL5GO_4M?fp-xo*X2zO5kQ-g5_1fjL0 zCG3INBHd_0O}OJxRAXHK0Jck<4&ac2+*Jj(OP-EymUO4tRE=J{c176qcZ+aO33B^R z7`QXY+dJ|Qv=`t~-0(wP4N(CXlR5811@Snf1l2$L`5{QF$3OwQMLr{Pob(Z2-fZLY z6C=G)K5ZMV2TB1yNiRp;WomElivtrJk@SIFqQsg41>(-QOdQLV6qTmI8ftUUsl-^q z%K1ncu_j8ELWqP8E#8i<2A&$Q%}XRzDxa7lT3?C=^dMQU3~Zmv4NA^-@K+600_NpO z7cl!S^>gU3zFTBo-AA!&VCC@6CY{NZeON{L9DEwu-Nn<*Q_>|ZHt1kpIg0N~&=gLM z1Dz*kO4uiHiu^1>9BC}P3d)U)N6~tM>l4B~EjHj_6Rh|db3*6^^_ zZjgb$Syw|9QCXOX*HBmp+d?5BnZGj>Nl4Q32B6>fD{>NV5b=|5sJt}?&06-&On3t# zVRiXd`hzp_M`~}}g;~J7;gj&)A)l+pA6=n3d73)K3JE#to6hQ3d8iC8rrU;A|$wxXY@|GJ)UQJ5fxw3bYRi2 z`?;&r?JTh5%#4f?#ml89WAB`|uD|AigDQRVu$>BP7ubOm%+p&7E(>i7RxR@g#_xy% zhLHR755*Plj&Rrxk&*KllPbgAZ11TFIgAyQaKGRc;0Nf^C$WB0Z<{guPNsZdF#Cq< zK|MD{ZEZIR>S(;w`KAU`h|RLhxOI-8=RMF@Avvykqm@n z{l&QwNOrOXR$BL{@u9xFqYV@1*!aLY?1Gb43Is=>Kx8br3>yL)phOuEoMHYZ$zmxD z2Q5oF%^VY@gPEAt|9u+=Hz;x?V&}AOZAEYjHoh`Rc?781%1eA*3(-j<)z>XEM0^0t zG&YzbpHAdw?ADj4WGTRYfLARhtBUquPROu7@!eT(1fz_Lkp_3CTH<0$0%9oOWFl8i zB859TowMs$a4@#Hh`v>C1W3^Gwi#KK>g)XYuZNC>ueBCJ2&>=8-ez7pyS9^59 zi?9%78l=YqM`|+UoGHD|Ql3O1x+#}=NiCK3qV{v!uHG#`OZ zQ#fBp9zF}#vFs&q-$4%__*m*lGS|FGCNcYLttC`4%Js@u|JaL{4x4sH@z)P|MUH;TbjPHzaAuY(e>=&ZWz{YV2aA7K zEp;y3&dqd&-oUhO^ff=smQI`QaqM~M1PSW!AdhsRMBEvoZv_1aI0-8vIBd19_4=st zfNJGrl_uX8j4NAr@jE*&Ouf|dPRs$}Rl8SDn+sUR2_TCu8CNOM(ob?8QkP~lvHOaw znc1_a;Zw$HnyJ2~0P8T?P;N&Dov#nnTu{DM;6!i*HhEeFFn@LrGb{fZ(a^3`vNsOF z>Y7DDflFD)!-Z4kUY)hyg!e$N%4?!(d0Wl2fSjjtHZhM1%p1;vl^QvYH90ip zz>|UIymI)F+E}OHO2d1&&q{9PW>ljBQ!!c2zy!Pe$A!39=M3-sVY@f9T2My>2f!?} z{QO258{y3q2{&DAEOs{ogw9;6#S{HPL^?^aGAzOjx*P)Swo$}^Y0wnWkyyK6K65B( z5<)UGkmk0MNDOpNohR^!Q!q*z?uMET3x0ruG4Lqa;D;I%_C3Y#iTUcDFdlh|4_>6txH#hbM~Zj57x=VhQhxbbCjqfryps z*T&FTwzIYNraOgV<=9+H+uVtp{9Zar3GsH2yimU3m4!A>@g2UuR$fD5LBI0U9q{XNPjOAI)Q7e36Ii&g!hDUI)h4OFi(zy--YhCOlhK)BFmJJ+4<)Vz z3e=lC!z58S;C!AuzW-ZdJLU&%8pAhxWaWF1{SS91OCtth11Ae3VQV`htABbdKCu(u zs)ne+Q*?BNKSggK(4uhA(PYc205IycD!m}8jk5X;@(E3`&+6pZDBtDU2qu4(^!Ea! z4nH&BCdNnJ-+g^RuV<+HdaFQDytwCW&ezNlGffa1O{nJ+^<@WXdHH#r zoJZ?>CEOT$GZCkLxKl$W70Q|{%7CCvLM3xx9`8tZV5|`Tit?mwv$x;Phg=(=vhMZB z9Dg@Q;(ZxQ$@mNTp&L8;?OX3Sy`=*M@cfh}{h*Xoid!{DZd;3~%#6Cfa}X~1JfpKa z*o;3ZNJW}#+66wq(xF z(>%fxpTl*eZW!PBu`Xl-htFtgPhZ&s=P+D5iNbOvbAARnRCM=mw3i5eJ0@W5*m=~zR0SM%?{~_M!LZY$d(D%_tI|h zmKt+V9^Co+k}83g=YU@9;4wLn{rkYH(~XmuvhSRon6hKgs{LE z)Yz9}(gbvY7fkVXqFVlKHmQ0q6OKjzXL8MFij+4TYp|R+-XvNyUHcb&T})Bz`5x8& zQu>%`&FvVke)f2+O_$JW2mdcydd!h5?1_`J#&v5_^`Bxm84;hL|LPVXw@h>eeou1s zchd9!y|n)e9U1&<>>o>;Pf61<4?2Gr)SC#V5&@Q;joyBtzaKmt=By}Lyi8qIE4=ER z93?zF+*a^0klS%6)BOzi3<12jr4XaD{V_gU2`!D)@kN+;g`YnX= zF9u53(ZJTo{9jVmJ_>vaeT=BQ6c!@0iFTv?e*K86J;*GlvGQrLnA{BsI2GH7xK#3Y zU6|CQKfZa)&<|YT{+O|3Z<`x0n_dJtc2_{0lOpcR2-~~eLvb-mA=%6{X)K&$;38kD z77McBfRxBHu0W1*eA2#L6>&BxI_F380oKOd=#G?$wnbw=c+~bDtuTTQ0ZE9I%F$o# z$bjZ44!mJ^;;7O1y3y<^SAVAr#Rb?t0hdHex-$)`sJM`w8pO)&!fCE9Ei`5;%=P6- zhZ{SLtN6tSb06uNKqN<~x8(w!TuZP}c*JPEp1}mTOpM&SP)u)+kPU|2&cd(~f{_=x ztYunHom01SaIJsc7K=j#R2<&{DiYZLN#yb0CiFj@#pr7v;JjoG3E})`&nEZE+DujFDZ^4i3p1~AgV#eJ>X{V zd_O2Cf%%4FMLsl$yU9bkR|%P$%vtI<`Gz$+?%JBjbDD;jwgA>gmXtU@$3d>&FUk=% zf|ITQ`4^T5XP=~Oe@#$J)P>}5iI`%qleNGA`iU@cTUZnlIwt^*CxE*_1k&zfmC15Ckz zS*c1m5Ozu0w&X#W;UM5*!j{mYcHq)^#Qv6U)BT;uv)q$e9((ta=wbSKt702wGAzNa zqTZ)}WeZ(yQu8F5sdmjzPx%al!KuukBPT;!1Q%iiDD4@qL0`&{Al6ijA>UO-&3nw& zFS(H2}yXYu{BE<_{IbB7lk>~Rj%zp`QYtSj6W7X%k~^S z2Z)642#UuHdgEyZ%?kI3X)7{DGoWb?szFyVo*S@IwnRXI>lr!z8nx${=MZ(oUH>9_ zDCxwdeG9T@E**H|O5|Cj{NtTGJ?Dj69%&8gJ~E0Too&sTJR=N>JKsnf_j6?xO^lAj zupuhIb`*VPW@BMvfS19zKH0XQlyk*9Azi&cnKlrd#Q^?x<}iUT@3Ck)&a_VaGL9(x z5j%$9!om=~8j06p)loueTi>Mt^VLL&5f4)%2zTjTmO5Ka4$_KsqZqEvuf%S2=kxP0 zb@0|ExbVFmJGtMy&4aTv2D@5ZI9O9R|CgRiRuQU8cOrY{u;qk|BtITsF&4GDcbuqW z16dWt@owo(g+X$s1p6yLh${BHShp{PoP1XA_5*qGIVttDS@3C+IZ5T{iID}7?s+=+ zk)w*Ujzo`(dKDH3t`#l$H8B)AqJRKIrxW^O?pkI`k-?6a8DU}sORTwyeucT>Gfh)Q zu3}nNEuSyCmN`EtnZ%lyM_i>FVWix?>KL`Lg_N({ePYIQ;*JUMnSW7=6tpUY%`+5gyUKSvDj@`!K=HKgwrvRJ zUh8`A)#j|tkN2hrVcv*>qK6DbBBUJRr-hf-+YE0S0DDZZ09R<8e2g3V)3Zkkpv&Lu zuHl_x`CU~eD;N480n$_1U&tnlUL|$F$9Kk51w6yOw;Z~0Z&|Fk1FYPzMt7C6Uc+WL zwYwC=i@o;%{jV8>rjFviegG+gKHGQi!$JKgqK(b`%h-Bw@ z(;V&+0zG`ovVL+2Dw+Einulm)#!b$-C8e zC$r~xtre1)f&2;u;r=y+Q^M7ToP2VkT(0GJW*sA;A|3x%p*Pwwp4m7;gW~4p zu)(8zYx&p#zBZ8?PTSpe>Ts!{7{k_@;3&0JLSDkuSrlWlE50rPqB=}$;MzpR#b{nS z(aEiWlR{q)dSlAZhClulN48>BX$UWv_#8@(5zqk-A$CXGe;~Dmn#UAbL_E#5u_Qv* zm_e@?Y8vZCY^PYg_sp-amv-t|-J{ypdzZc8c^BjhN9)fE0HfHTn){Osk~^uvx0gBV zy>3N$sxl&lR@vM1pk7dQLnc4~wj_1X9zK?35wz*UJkQm$Ear?!{``eRzsC7B{9Txn z7|u7T`SRPpv{PT;|9b9>XydBG5CH+%|N5V!wBHB$Ke8giE*93tCXWAk@O1Eev+EWX z+|tsXm^}oUi3BA<3=$AQgnpLMS|THdnUW*`0kg@*OJSyt_iLzYmm8ibu5;KAku4VP z29Xj*YGP=gE-ox;YPDOat*tJoemPyXUrq1_eO*1>`8Z8=JkdU_J5BLDt-tkJ zA}aQ5HO(m|7uVcCk2RwVk}pGZ=)1avaA6wF@>i-H9qeG{; z_!CgstBL2B4QO;iRgI|;G5|nk*#9*ZtscD5L_KUss8^?XY@o6RWGUA-E~|&mUr_rH z?09DO{5a=VGdVJtdQo>Sxfcn-K|8EVFpU+aH_ck9h;%8i=U~3y_V%hjKCwoL_e5>d zFoDk;O{P6G@db*;^^ zHb_u*h3b{5ZGnwsSQ{~AM;dCujiga_C7U!X9<5SbQB!_YQ9iO%e#EA&QdxE>`CN*1 z!#H*9$lB<(RbG)R>7Sr(2S0MAVYe0WZ#KGvPud6vY^b0ATG63y$2r(6sPn2l<0tJR z@WTJOqHE0?HXuUnrEU_V?;>atQ+9qPd7C@z3-qsQCtw~z?~ z@rI20-zdJJnn&nG-GNmr>JPA;Gw8SE(aoPL8Lqdq86|bi%CBake=FislS6|5a?eNtG{6_^7pS!{aR#D zew0c2fKJ(4ItC>uJvYL=;|P1FYdgHEdGVtC)HnMLrb@}*v#St>2K@;hsZgJLRjvLG z7umHY#q$P1{8?J}o9G=j@;A-7fa|TZxBI^s0E&QzEZ7h_UYckFq~sM1vBPb^Yw? zMwvhyq6Gh{A1EQp59Es;U`HzfdPFQN3FS=ZHu()i)Lz$(hKQj7d|FMZZo|RaQY)k1c8K zz=HF3ZWbn*ODb-uwieZOR))kg)j{P}IgpVVnY35cHkz8q$t3EFDQT(rz={}YiJn_ABp8aFqLZexVs z%H33o?QEVLF)msD+k|j?m1topv`RO)-nP`bn6$XIw4kcCwy3b6t#kIIqQ_+ovEF_` zSB()eO2fQuwQ2B_jp+fL=^?@B6vpT@QvYX-Jp}yuxw*9^m`<^+WO;?bAtlT*(tK1C z9L=CJR?}3Z>wqkiz$%TJRtgu9ZB#1TM2ti#Ju}y;9il`Wiy~n{DLJ{46kTyqPrti) z5mNr@5xHDSd@pQ;11_hY0j>nIMCJ&b+I*(X#5OM=362eKyV(Or(dLzjj;+#$4iJD= zYFeoG^)2^_x5t^7Xw6x*2Ki%Nj4^5}Rx#r|Bz;k(XmBrG%hK{}(M6eqja!Sx;nb+? zqf>wQ0H)HxqtDh}Ps+fyQF~=Z8zJLwpT-uLtjCRLom&MacyeCh;EE~&Ud5Kk2r3ht z-Ew2Aq1Be~uah!!_-Bz%ZoL=+);}MKvJn)>$Fcll74++g{AvW0Lv5Z^Y1xbPhHq8Q zZ^^`Dl35Aait=qMS5K#~(lO;U`v~W`e|YKC@EE~+b%R|+Zt-}nVgCbc8&9rzH{R_~3?y|6HY#StMX{Y6_xmEQl7`<%!S;iZiaJDY>R;5mTN9RqEet zc~&!%+-COk1bP=m?6!wXKY?h*tZwogFJNcdGm$=a;wFj>}jrcdXcy$(5hr!kKntj_jH~R6hAIbr=5RaFtZiMrvDUzv? z>)U``un~sJjD*|NekM75nbO#zaG?p^g`-V!JPq~A!Dbcabe;@QzYjPhcK}lD{=UAD z{b>9uq^Z#WBom%A<9cbNqEHyF99+5z*|`(A>vnHx7Jfl`@Yp$Y%YY{cY%pkzwFXgF zYmntILE_rTDOAM4B)pJ$^#jD|$1pi6N~=>L<_5eIn^_WuO@E1{e&4SXK=gz>j8rY>AH^Tf&OZ){cWz$FvJyz{Jh>BqC84oouO{)WhR;I>bUzYQ)jS z?M#9lbM;#s>(M`Ic6KJS#E=!OzC5&a`$0LCMkW&d;)8ZFU3}&3LVRv9hT3J-~s#*OF-prd>%iET(*a&Y_ZIjrs!Pe_rvh>E&gDE3m zI9ohsZ^KL6y}<5>_LbW^d-(yl%wH0jWPgpq2G1;?!8r!l*F-ZHE*{I>n*ugLzy%N* z1#;ZXy-D0GocX}=bVUnAux@4xUr_~ExoZ|FBG9XPJ?j8`4zoB)@(7?$_nuoH2H zycElOX4XDw&B!`WHcy%kxq_)Z#fu`Z?R>^lz@M4+;|(m#c-IK=tGp*mZ_vY`6q+_SuIQg2uOP4#U#n=hOXl01K4K^2v0qJV~yUV|?a|ht^{SvnYR$Td+ zYHVTCBh%X0RJW;7Fw>}S>C4h3W)yR)1z;o`Og>5+v@0OUyu>t zvb?8zZ4wt*9@yxt#QtF7{&>6B`H4e(IU)#^CD1d&MauD0Sai|+C*$*ahq|HbNJmZS zb6`GBH1{7EH{lhGN5jk0l?a#L&BOZ5{?g|dNsOGt1iq>&2o@C-Vf=~}PGzF2{VpbY(6bPx3Xmvm84VUn+$o={F-ISoEX z3)8E;!gI|t-?{wh(5k|W_=kEs5Ct!vDR_sjTlE;si+an{1=6=UbUVsmfK!m|_S?%l5B zzW#_xOJ@cnbB7;9PvkoppeyR;n)3UL$TcIwtGhf=Ht`I;tnRgW33<&+8fFj}z6kwR zn5Va`1jU^vETgi}0UBv=6wlwgrQk`V<@!bDo+ATU4RW#sSxsRW56DPe`u$^!?UOoo zF2x?n8hDAl)}Sf3$+hDEZ73%tVqcV$5!*)M%^FQd9NGx2Y5q9j9w#<9Ao-4IB@7Yk6>kAni-J-s&Y17g!W&3Mb_~@ZJ|!Oi zK_zuB0SU+sBo(2OC}U>#!&u(PiENAL$WkV!Q_#o%CX zg!P9i!bJbxo-Tp0KqxK({NA57r4<#gk-IXQz8GC}cv^(U z_Sy%^za~t;f2sCsHg>m&DLuOlRS)zUofRGy>Frf+WPKLJgCZws=hmFJD>8*juZ5r< z^5zwpwJU%uRZV;OzzryrVtLoqr5es%c!ndzf{I`?-`Z(W$x+ur=WwV9#XVCxv&Q`y zBw-}uH43!}*{v5pW~p+E^m-9OBholE&ALj|6L+_9Pi}{kAW)I^vBXpSZDKd*yzrs5 z3F77v?_T>D{Y47K&Y=zVZM{#mO1M z1!7F}bW?>znO5A1j8YQK@ku-Z8e0^?u7z;_#O*J4Ntb)CaJjF?w39daNcZfhX3a55 zf@=BWf?w=^B;cwpZt*B(aDm)ShUC&LFwT^3vnKSVkRIbXr-hPi6>7E!z{U=Mo7I09 z;44oOOix&Cf>Nbr{X$7VOiW{fW>&ZStD&e!xB*RHRm-8BNA#!b@Imd{NO%uNboA28 z5i0CtLG4=(+j$S{(5$Aj`20l~L%l-#+X|)b_&~>CXkwz4f>V6*#c=)xi=!2VRt?jM z*1Ir@!8_DJvV*q92zuU-5N(9-bXSId7wBbB#(-P|?$jN*+i9hUEXDRRezbMmJQ2=2 zmOUK0JUcUcI#l^?&b%1qKxgX^Q>zjoQ7#)zip%4Blb=_|jCp^*OF?(EDt%2Swz+Vl zW1^Ck5FcESq4d|iu(njh*N5Zlk5nluvB9duco3+(0?t0a{7V{`0N^AeZ>9rIpcim> zB|TfMXf&but`$_dTkw0>>5PSd-@PMMKP4_WFWBBJHps@^NcY zZCX?*@PD8+|A6v!=E^IOpRDG3|6=VrY&w3ICk)o|Kbi`fF9$n2feK)7Z(9@QD-M@v zpBP-tW_l%3)bpJ0gs)y(!dV5YT3wof8p?SFO{4a|dAbL?VVl)#%fk-OqPVX-<7}7_ zFhJU}2i@IJ@>f)-E-EIFp%u#djQg!(0^{ECti+aagW=EqaRoHOswt<2C_G7)aHE57 znQ*fg=vPi!k#KDdH5FH*+xr6whs-*@Cans+MohRks1mtJsztoF5xFX%MyL0|IneJ& z+Wp(cbi;E^ibLrjyGk#U8F0A3ERz^i2W61nOSWkA(jj}2ohM9Fb*-21@n#XY>A z>-#*#tJ@qO$fnp8`Zd01b#8miCc`$UbG0ABY$%wwdanc+Z7wLG#HkcP@Z*xvYK+j^ zP3j|x=zy7|xq#SpPQ(;|sj_%aGp=P(U)$=pwiRU+8}1TzxD{TQ6<(ATAIcIp>Jm5Z z5;yW3H;kpkN&QcL2}qx8V-&RQpDU2HNi#(GiFm}8Z;&I{#E<4|JemumhwyPsCQeTY zwIasa8ZU?=R5WV}gBKL7BK>(ww~s&rzPn+uHwb>1Kz_TCblmJ;$A(s&WLs@1^P|z; zWA6h^-fO_j2DS0k`>0zI5kRu7IkE$j;mHtTrc3e#RFK)BX(b0j3G7Vq1M6niwhMn+p1 zdlGKxU_wW%rx)8YjKw5RfNI5tGs&7n{#0aPEZ@>W3~TFC;S(LmpyK8VVv*m4jCkj* z5=vH^PmKU#!G)V4xior%k?G^FQTWyGi!%iRwg^ zli}k`6e7V3pL zFjSI-xjN((h>K?te=N_GfmcwIHW(+5S28oRLJVhzRLdVH)EBoP+_9r(Z@m8>9-W&v*h~ks(tY5Zj1U7fnEP5&h6cVJC=u zGQUmnupAZZ6guKzbp)SqhXh(I*cypiRaVT57F^yFe@NT?{_UkPt1{^6(%8jOx6cF;+_gWkPG_8 z3M9^4^zJAfp$|L2lwkOy7AhjVNH3`S!codNHOL54cci<94Xv;Io^6DY0Q0(9uNdQ! zyv%3~sFu5l19Kcv)|K>{`TdjD!z(<=7JGph~ zjY&($O7s{JF(8)ahh)`p4Np~&l*kZ@W1HPfGue~$b`yv;wRgRF>N#&g1!Ta43Zl+* z;oX5L^`;zo22R8n0F_8Dymp7DXj+1BaT(~6DadyL7244iv!l}UnO965!38Ki6-Q1OAR=c1X=jE^_(naJ`{9(TL z*x-O_o^>Z$W3ZDs2iT!^Ie2lt=t3v`FB_)Bd;~I(Pky8Bt90?xSaC;j0N9|0hH8I8 zB>~>4m0^j_OkP9~v#O7z)%p4PbBds24RUM!AWp`kr+vpr+u21z*@s^zO=+Jag8NUl z_a1+>u%it}#v?dJpq5obB?|k;)?5|(mFlZVR$FGl2xRrcRN4?1Uvv7Qq+F2KgCzFvRhl2~K`e{BAce*SI*GUa zZ6n&$B8Oh4_USZ%bIM$W$IM%qquc`QSTJE?jM3qISNX<+-12@ZLnQt1#S?TUh!(bN z=9?TAi@kqi4>N^fNL3D3+%q^QmeS1jfT$GG-P;njAfp8G2!@3YN5bVn(GM_3Bo+sv z*LL2~X5gJ<1O>ZUK;{)DO3_D3Pc!i0D|mLz-s%$*C*ql1tACqMdemk*X{=I_75xZ_ z%E>6m0%Nvs7&-LZq8k6!Dm=o#a(9jF^HxBfVvy6xDBP-~^p@R*-Z|>dqCK12=2&x3 z>jRp>brZ30TK|R-`HMf1OMN9#ZBP`tNuSj36!$QwEgtpQA^k7H-Z9FyAX(cj+qP}n zwr$(CZM$lhZQHhY**14+SJhYjb)S1j_c`a@G3H!r{#s*YjG37ck#9WlS1x=v^RCKq z3*1=7aSQ&KWDHn=3&(q84L+&?UkZbJ9jkAaqbYK*!`S>!eZp5n0v`hP=Yq;2zf`8Q z4{zAPAxzbMMnaZN-EQ%*=hnSQ2v26zX&dI~n^=~kUwYsv;oCSFXlq{29XdAg;6k zzi3v|AGiv?hmLcpN`)mr|85W>z``a}P2F{OIR@yIs^>S`unaQFxoP}#hGBMr6KKSd z*VHhP9dINFGX|R%h~du=c#u)z`6}X!O+IEZ!>k@UQULncC;1~U6V698G`X}`U@uWW zs1&rHmXJ^RD4~?Hoffc(8oZehu!$VZ%?#+y0>*xb;JG@z`YV~U?9j73BIPrC4omq> z8SLAe&`=U4k3W0KUtjJUm-Dl%H^ATNo!R7Xe|VGaUDrs;M`6N;QcP!L`|^q8$ zOIqfk!-`AV=A|=doYFrjbFRp7uCNMS5js`--avSoW^`jEHxZfD9P;~ zxhj{~LuMTr{84{r=iEW#;AiB#j+h9GdbWXB%Fh6Yux2!2lD5g1qfta!f@;^(D8fuq zs23Qh4XHl8eZqG#V28;eWvk`9!+uK(9f5vHW>@a@9}m1o1bI zf2Zd>V)XpQ3F1E4<|0qzKA9Vm?MyZ>EP1OP!{03hpKv)9@O5qYFbmLu6t-|O`Jv`5 z{KnXbW4eA5J`g_9=APUj@sW%8unourShb5yxQkD)uJJhl;n^m5mp&!kYskYhA2tCW zIwceBnu&k@vfK7#!*#&`^X;V~cL9c}S<8~K15AcuXFS`aN`Q`Vdb)Q4wFOhL@BIAM2NOpf<%$3iwHQio$su%lr{E98vd>lL+ zbyJ1f1r@tI6+1}2Dik!0q?K%5A-^=C9(dxT(~6aBbXEJjf}PVR=r<=;_+@1PxextK zIJHxBX`1p2dUs(U{30p?KUN_>+`4P=a$1}VeDM}sf-WeUj|qD??Q{)JJrGfA`b@Cj z&JHK^^>5lVe(Cm`?PrVGn{FF>#Xj_I<-)~1JpgPYx5=X)!H4mP50RM&!&>B()4#;J ze!A`99SUs1Tt?Zs`zf-F6f%(*_u%-wHn$YtA-p+r;}ZHi9&Ah8zM^n{T?~tZ^c>o+ z-Me?!<*8|GsgQZ0$0hhnxQ~7N8t%xqN5mT^Sdd}7bt68^QDDl8|MA1gB*k6tGa9d+ zHcMiZZ2jfq27}bsA$-J)sh?qlr!1HA><4?TX5(EN{8;qLN7E1tIs5a;#Q6IG zBA49Z(RGU_Fq_-~6|qxbPj1x_8pJNJpEhP*6v#a)PMgFb8sugfLYKxtf6*}-)UKgF z7mO;GPhwRQp!pF(_W*~aDrQv4;_sFPP4MVgqaa`4=&$O=g(I7`vm978Wf^WenNxz2 zdtKT25!g{qF?7s^5m!OW6-4kSMB^B!+&PV8E?B{EWk?|2amDD0YXZ-SECE)DKf~vg zX3ohY#aJX=Fx(o3U~JD2ITQ2c2*c2hC|;FKxYJ%)O}Id!oDL`e3k@c!8@7ciF0yFl z;%81ITI3OKkcGTKXXON5kP&iVh0GhAe(iu%(HNTzi;&G~J$~3OrwhylV`kB}mTe~s zP5Jr@9S;^I$RKpf&+a&YR5aBZYxN2b7N`g`N?;QnylRQxfd4M0AY&=+3ICy`IG_Rm z5d6=w?SF_V#7*t~DWpi%fb_vp#r!7Y_BLZ%pE)_U$W9ZoOqNZXrxLd0v=OS%me#hU zY(?!#o?+W|<8Hb^q_DV;Aol<=5|GM90jH*t=n|w-6;u!uROD3YMnFYWQ4my_eEF5j zyJ%B+b<6(!!%E4$_1@)90@v%ggg|_ja^6mPN)*}jEuM$Nx6MyU*XG_X{umEM425Z4 z#PBOi7iG4aEKCNbzb!SyXH|l7hzzF#-3D!kX-o&+IWBQuvZL1(ybY{+F}m{Q^Wu-~ zzXR`oB@p2|DuQ1U2fzo_fozAmW9%Oz{0rGn4)_bm2g`wV4-2Cmt!56O7T5=k0jeGE zC!YSq(P9Vs17HVq1$qS>12_u!0mu%_2hWOJqYa=BfCJ!z=s>+E9Y7D<3)Bwlz`a)$ zzzqNn7>-~9$Pjpw8&C&$1B3(SgX_S)2eF53_g*Tp;~_O==4xv$R9LFI*%-5_!G}m9NLu3cT)Mw}XOQg2AmYhj5l8dd5iAlJpqPw-n-Q$#~3h`EV0!@v? zMa?BQb2+)AiIl6%xp8kJCXv~xYcaA!`BN76e1jly%l=J&M{}ykl&;dA^~>J*`939a z#vG}tMw9+5hYIz&GBrwot@d1zH+$;nu%o!Z8ELiWE1^_UOP?!lv3rjd>MJQjdB@$e?7s!{2l$J42lFXeU|#TK?j=`ny6_IYS7-1y zR!`wf^u0^yTR`m#(gX62X-_|ZaHDjd8sUq*^BeFl`W@9?xkwaAgK0&aC<%DHBohv) zMHLYz;|Wmvz+L{a=oEN4I0XQIKHxlrGGKF%QZi8}hf;+mQq=OGa++2No2XT~8O5TE zWg3yIKrOJCIq(U9T>hyCzDiP`nSnRa>@lh*t~bu{(HY45;pnUjRigCMA;N+0&Uz^E zX!Z^fD-s+Nv$S)b8sfOC7| ztt9R>qNY`W?FI1UOdZc**Q;*r15g%(U9{U|JfZz0OH~h9BE6_nzwI@fTK#7_rW6qu z=+GYT)*7MJY&6v@3+1F{q@%Sg%oivpo*p&hm+EmKrX6v5ZDz+ws+p6Jtz9RHYUMs~ zp3fqsSFM35@gCFSRU)@Mb*HYF7P~=m4qAR&w5~VD- zlo}xsJz53^dSgn*+V*ApHoMBe*jt6@yci z&}KB+(7`Q7?9V(*G%RIH^HteS%B?5M>Y%9`Gh0}%nXIcS%qdsZ^}un;8J>>c_p)kqNKhOj1t>-;!zChfEsc4IlT+(5W6+ydiaJ?<&*HBam;`rAv50cj=nRqO7_;zuC3p+HWT3<*B-V)@cDQm*?9xl1u)vW_{}B;kRMYH>obA|7?6 zNsI^g-dhM4<4|P0zimXN$Gmf&e6u#8XO zWM6P_Yx0FhdH@c*Vr%Y&_+oFiF}r*Gm-fUj@H|%L*7P05|7H2>)m8cHLZk1->g$iX zZ~XlW)Nh3l3B3XQv3;Iket7@i4xo;kpkBCR=y4GKfpT#W@d{8ZyDr;NrTDp^rI%zU zQ38Qn)PJjJ`~o|vguAGOpFyG2F&ZF{e$!%cEb*r9TNDc&5qDj9~C)kjy;;oY+8 zKFi3VM%~4CL72pB@if*K^B3Mx@u@~dTw>1jgV1Ij4SVWOl+*5;M@|g(lsezC$jCgx zqH3qUr5_|1PiL&UtGuq{Lqzp+fHGp4tRxbIe|AGa^xBR>~l1tf3-g6)jy(@X?x}A~!%-=Tz8Y_Z5FL$Bi(-jd`r( z*R(~FEe|l0)@B(=m>`=yY9gbpR|f)vb}`GvVxdH#gXJPWtLA#`2*eT<*b&!5bhv4A zhG;4(7O7`4&pv9wI*kaxT{7~Pf7C0*T_u!Rjp~_jIa7ENc}37w%gZ({styy802%dg zBm9F)k#18?LN3H8!s$;kJiu?obpkEw+9>nuJVSFL=K6b?>U*m4?@P8@YQf)5nJjKj zV6t7Ll_m37=QnM;)$Iw)HS1K2Y>vLG(`hRHJH!)v!-Wu206dyh%n}4yE1Je=yy#W- zRA?}i%Ux8+*DAMpMp4b*s?vgiKuKyXziBU`Qngl_t6ZR5@LqCMOH0DZGWpa7CZ=pZ z&Zuh*1JzJuQ>M~B_eFe|n+kQ9KCVidOVHD5R6$Q^=)O5B>#j%(d)^3g>sm!NL<7~L(|D8PRbX^36|_aGEHI5%)YvwRA3Nu@tt^3iv?6mC zbKwRK4*$3#4>~=(=1QLOI1e@RCMqI46klg}CaNZOe?`w05tdIR2IahrG$7!S#S3)0=0fplxEHL!*$IPQp;Tr&`-(3dpEbz~jab>+e2AJfM_JJJ2;`yzd+V84>Z zy~2ZtTvZ~FyF`;77`GcGq~w*6x~i6v7Kj6%Uyrw~%{}DU$x|&<+oJi8K&FE3Wa#sm z-pG-9kXZ)}NsG|~Yl{bubSB($X$jp0;cw0)mn54vPLC{KC*f2?n(~Os!va_MqUCZ6m^=a~9=P){X$*lT!LBgqjE(F z7!Lpx0KokxbjACh!`2^6i@$Hcd3_4lEWG+7%KKk&2cC1sbv8 zc?cC6h;kQ6G>uN1#hI|Ep0((n-Mr28*{2cps@(n*O#IEvFWOJ+jl3pE4T6Gcmgz6M z)0|r$@7cH9+x*y?rk09y&uLWxTCBgRFFBo@uEcFcFcR^qE08 zZpPt0EIbO@++)H%A+-={1Hs<>+1i=T#p3+g^YZcXJS$-Axv8mYNa_dEdfd#** zIa4|*?ZW7)D`1>~g;GG5J~NB8KtRew%@M0EuF1Mb{j~Dbh>}>Z1){2|rsNfA-wTNf zAC*=XURNPX8jY!*`a~a#3whBAZLFSZh*(@?gq0T1ENGRMig!BVBDPvA2(tSHCn>eT zNxzKyo}$W?0lAR(EIoQG%o540t(sj>VYcctO_$t-Q~^U}wE~7bsCDn#>{csJsDTZX z17`os>4+z$ZUh8}61C$GGf7PhWt%9?v>Q@a4Cs?dPpmJXlqwLpVK6@|2IoOVpk-)$ z&3?iIvWH0~#014)g2G63bhDk9Kw*eQHc(x*RWErVyo(8Jp8fzA^Y(z3>VADw>gmS7 z~iLp{b}TO#~RbA2>JPYskQWkS~U&?29L$aE!DLnv-xp#3y=ON z^ng|)u&!gL-wsUpOuh9wbDvoSW>?Shj9&4qP<Y*GE)JQ_7k*(uTLm3z!s42?;}& zK6ZWtn6<8Tp~vBO&yip3K$~_hl1Zhf?!MR-mJC_dAE1gtqqemjD%_(0-jQ5QrD;K^ z2IdSX(l)5ytCC3~6B;@xv|53{sgspqCA1cmlBAYuF=h}V6Q`=dToy+HHPt@M6CL5$ z>Tjvp!K&w;5UmU)n$p7sSZv(CRgDu-&xlhBji^vgp;6~o4X9K>(a6uLe4v2jmbT&u zgqq=&`aoUpgb(PXtm!`$t4Jhc+{PqF`%c6W{KSXIE=qsz|A46fz}rURn>(}?Zi_H~ z55scc4?Q>aAhv(1p};LoQ`O#aZD}8%JH&O@dtlH#z>yGPBOK12f$=#0ChI;@j_SfM z@T;7<-3q`#XJ25rM*o!S`=NIqP$_I1fzhR!Avt?r*)eY&>S-z%r{j?H${%C)N=v%b?x&g!)0*Ki4B=l5VC@(?p84 zz5EBMA^(KFG4Q8m_YxZbfarf-I~APlUF;?8%0To(F>oW078jin5!vv%A>Zg!QRLGhgNm-}r5k!doxH zj_=LYR^iNdV$9`w;R3(Lx!WVDETO%=x_j$)>Yek#x$7?XzPIoZ2B0FTjH7Ue3BGzL z#XZ9}HFWCHJ{ec#7#lSAc%TK|8$kbXCC&4}G}k)_p|5(!s;6@*z}P$6-8(SF%d=T! zKuuqJIsyx2=VE|WtKx_}WM6q^=Ft>|7xtmDHF&2@W!I7%(Hym@v3xD#1AgnHJ(5e+ zYfLWazP=D~Te&tD-R0RXKGH+wrTSEH=57EGOx0Vq#|MtqWC(ue3kr_Qfh-KCg>$eD z|9WL+=HC^C-^j?XR3A$EnZb!?7JYMiXb2v+N6y33?+yQORTlHWoX0ynG{nO*$b+YP z=ZxCtV1Vj3vDRk<*LSkd4uz+DubsztL-6Tew)cW`q+ubh5!B@8UCyk63OmxO%36w) zxYkOFbagM{UCG-*EeEl5xrw}4S%_P3t(wdISJj${JSOdGjff!`$*eVI^iZ-YP#1l3 zLvF2=cHz$|G-L}Ay_GEmre%#O$_b4_QKCuI*+GGb1^7bhX^AxysSKc#IfbAFvldx@ zlj|_I@B*W&-dGt~_*2AXUM%PIrqCK_Tm@N5PRyH6%$a z6V^!+WDL9+MU6)DwY*GVKf^z28Lj|qR zkrGrkN|G6>oPv$E^9X_|;c~F}f=ywt77GZYYM}n}cOZGiTUfWQ^LL6iDt9Si{0Ek> z_(No{{)5a|Y>!u(JmQ>;t@5lP^`b+MuT5d`#03SYwpd&mnYQf$L!@UZ46OcUOQ`7d z8Y4Wg^n0R^ppQ6MZUH(}>Mq0D9xtR)ov{N@dA&4(g^zvpVpgJ|9wk&Dy5ez;)KI*v1pId9kQ4Y)rK_2^0-+7Aa;>JIi-yJ7l3A zT{;%{mUWfesZhUvbi=x^xD_7aQ8JL>ZWOOwVeWUeArqM0tR{t?la6oUVg3jDSYI=> z4)qj%Yip%N9Hoh+*({PtP%INf6Ie+Slu4?|Hc5q&RIm{eZn92yjR{ZbEP1H=P_k4f znvmJd&cg$)3l<*Q6dM_ZAUX|AtT^(b8xsYyaciIj8rm#dVvE}66UJ|d6)MSOl5()< zhGk*8?HvBKCQGqI4C+I6I+M-Gq$zRZwrh>NTT-aTR$t~R6z4%5TBCFp$A_z=ow`2C z;%sL(U}HW_r}8?-QJK2F#mqVTYT4fl6NFyyIxV;bxf3c87-Dp0*_RZAzn80PG({OJ zr@vc|mc@!lBs3h1Xf>RS5E-X}Lzqr@PR=RJ#8O6$%_7_K=tf0d2)UT%=3^rDMuLV# zP3U@zv?!!{$C1#6wZ%&$OR1<1x(%yBmUfc;NCrK1>d%uH{h@O8ew|(*hE_3oCwQBR z;!?ygTM2JbeBUrCOQMKcTQ~DcS~ykp(^(X>Pu`1U&^0Tybyk%2-ryWC`nk|r&yrSN zbl<*7RI!NxVi_uPT{QO+i`Y+2qMq7YX*6~3=b(x)5^_>quT<-HRE*Nd%Mxq1pcG3m z4S-VOSRVtWaB9kFt+M8c(;9%elD||If-gNDlQ`z)L6C12qUMIz~!}N(;!Am0*<=pb`U8Vns=iLK;w#c%rc{yBE@u z4TOOfTshPwfEDP({;S@vx-z^beaaT}+Y3x#PjenTdTbMX{qQn)-l;FzO!GovA0j97X9!nVoSHuxtiUv?K-E$o{oesW`#e%dON!LviyUT>q z_ev8!GG`f_JaB?+KZWnCImhaZ((#k|i6&tpNod1sAE1;Kem)+&j?=O8-4V*M6~Q5G zVIH16_L6qWVu>q82u!%Rv1CJcCwN4&(`k@s8gn)i47h4@Hy-M=8WBwwwD?3g&D4%- zCCsbXD$MTNN}t{g{D`KAGvxAeYzt8+zRduj?82$PQXBHE+4r?=tV-K*?lOlw1$xZ| z+c7!RpRO!Zx$Vuhiod))g;*gs)iUQ;$&1k+Llx-HU{m^^9?R*2=OA7Orl<2&yA8dJ zup!OVuoX`)1y&9ksbI6~Q2LNcuicC!(Q@yIE|ksbqeuC~=GRU*51lrj8iUo{gVC2=)x&sKBSqmN94f>( z7ZMz$o}M##`dQDf(t1kv{7}Wk&Dxz&Mt-R-u)>KQ%P^Ul*hSMVNLxk~baS0fJs)6` zLX%BS{#xTsX&>8P`BzEdj$zRbJ~wtWdyt+Ec5ES2YmCjD->)$B34CoPcCgO@VK$^P z?xiUPO@!@U78Ml(OfP~y1})>hy9)4RZ!R4%H^GVbby2>=nJJktuIu>Coz*=Y-WXW{ zgRFqrr1@u2UEsP(3M;nWibOYY2k@1a%a?2&*h@amC?sh7B^ey|+CXmGwVPfFlyWXz z{AWM)4PqVOtZhOijOA|YlE21uE)Y|^TtXAg;S1Ty%`#@)Dq?k^_OH;WSHsB5uA4$- zp0pK2#+|a|I9s<|f@^7DEIQdDoPk8W7H|h`TPGO4JU^NBoS+=gqSc@9~ zYK~PqrlMyqd_1d8Mg^7kr0#Mf+}@DTV396T zY%nJ0&lW^UE-~4V6RL8^EDPA;zs&yJKZD!YG;JRv4DAD~L5&q;&gA2^Zdif+B^lr>!4psL8M@tMGIiS1q5UP?Wed=~7 z#>h)wR6x7wx2)_=zbDAzj)xX}VwKJCt#Q zO#4OhYhnL3kjVMly=>wlSySzqtg30ugmun9HPMuHg*fmN*^Zy1gp{m;M$p6UpGEa~U1+*kd zZ4?JUuq1B`0)ToA?SvQ~;GHgtfqe7et}Q8~Q@w!J z=h=L(<6Zpy;*Ph;mLv#-)-yY&IljB*{^WgMkB>|NT0Rwo5o5gNLeR--WVSLJyl4H$ zST%o`IrjuX2WdFQtH?858ut*Ahh#c4T$=VMTYWcz@o*OAqxp95p7$_ujGb~M`^3EF z9xgah$ysuS1E8dZ1Cr1C3F>~N03C=c3^9o8Vs8|qgN$TlD#NNV(hkK&NL1X(=ZPDy zA*^cLoOV&7#jV`A(_}-D`zFC4q{#ASq!NaZv%|%yvl0oBk`Pbm%-2netp&usS<`XS z4y>a{4K__7vZ^m|XmH>k6b9N(6jTK~X%WNZVTDKaq>RhC( zqq(wwOqLpkBSKnK2WAqLNR32u z=?zX%=`Gw-=`A^enX7i!9>T6>jB4WAKU~mu*Bs*hD574!gH*e#4tcxj3$A82w8+E4 zi!5>R_k?lr_l>gxt=`$nUq!~sUSsImseHN0iy&vX_)gpP4YEP}6DN z#tIR!Bs-!u^``0gl~8Ed8&f}DGS#*ZvNOiFLqJ%4+UrV~x8%NVZOcw%qlhT=0fC87 z3n(QW?ba($G^?qb&-4-#>@*!ASCA3U9G;Nzq@hx{$Y~%qzT$|JH@Mpu_6aIH z!73V+?=`}_S_>?&wQ6K&7ALh(xE$m`t-PrkbA8AQ=}kt$Zf0?(T;fNEkCsXh-cwY# zxHKIsd6hxB9K|HLY-L50DkvevR8Mo;HW28XQoPZSRyk1hv|wavah^z2)VFDSvHdy_ zZ7HVb!m6n3nyfVj(}>nlLmQ=^(!-`x8y8nSz_8Cb;TL~}B=ZR|zlsN-b&sBaSPwuB zifku9{N;|kDcr_DG4vkP2r>yl+h+iZPJs19j3T5Rv6a-1=~{PXJ@6UN zvs;UzGHkxHpedQpbib%w5P$ylad3E@FuG5sx6w@RY0_z@?PiB(tSQ~e8!O$+9vfTc8$AKVUV1E6^AqL)DsELR zcSTBh33t-^fRLG~ZVF1x+Qe-nFnB<1nz7mpYeXb|?Sd8l3;pj01U+ysj-)@Nzqz0L ze@Sww89M!AhxjiRsp}6J^B=&*HqiI_UVwr5cQ?g|h6}VqAvM{p%!KwF3Bm*>+l@hY zOCzbmNc=r~MkQb&XMxY;JW=fW8o+0sVQ*nlb=$gQ*$)$bY@R2D6OLGQq+Fw|L;cTq&r*2(t21RlST#}H&H1VdMis2r7a#T&Ig;T-3e#M%BAZ!U-Qs|ddQWOTw zf7AD)1o{6B8JM7>Y0Gf+q{FD0Fz^7@twQ!giQNqx8#hD1J$%q^ZRd(9ytroncLV&f ze%9dmX@hwEbMQ?4Kc`av>n&5Tu>9BKKXa;~s=DgfrU-sJCdsmcXqzd;AjrkdBMBhH zoKaAqpj2#GKvAHSezb;xB~x~t>%)Gpt^=H306h)pd3ifeqtH)xgn!l!Rq4B*!C&Q< zGq;;X`&rPLA7{C5rypne9#7)?{Cxok;_HacMyU~p@2xVbf1ALF5g11Bo~~oT8HTv) z!SBaHh%urKa(vK_doTy7#a)eph3-WRGyuQtT(iOfZyW9RMILdHnRNTFWxL z^o8re8KpT{djZsb)bSA-MFrFsML(m_{3EqfUSa+A?lr(V`DVH4R9)C%0}BaqS*f^G z2~-hUBxJ7op}6O{y_|~}$b5dn89lP2323>cwFn~Q|c{4&kEwvY=se~=1!OW)VjWJShB2> zn^}nc8*>7KtMO-c@>Kx3Y0^NQcLry;H69UPq8T2y)j^D~+rSNu;zv+1-;imu5RsN9tp zv7ss}_EtBn(L5}1W>s;b!pQzC#CEMlL-MSJ;XNrM%eCC#;8lvD<2CBGu~>zfrm1q{vd;9hT88B7=<-dHDs*3& z)@@(?or*x2#@PzBB%x=?KG)WY&aJL$SeR(G!dd#F1t_!EMIFE&bl9+rj`3%02>&9` zR^x32AK^=u-V}1b0TZoT496bTnCzoB-&qZj-+Vr*vsJchb91z=Q@jIxHhGBNDl8D3 z-`*6ZM)4_Iok?ff*ny8Z^B)f574rGOXHL&-;mJY8Bv>J1q$n-ox{wz04uklK`!FOx zOxy3H1X_H1VV5BV&d6M_54R!yfd?@H1lk+}Fb*U)H{%gE{O*Va*#A=Yupsp_$Fk@n zZ6;jYRVem{hE&20l}u|xob#MDmn4PumUv@0#ZP!|otLCFK5mV1kZ9=Fm8mBuLj?<7 z7n$!luszaAhWDz-b5A#Mj;ERadF zBVoT-))E-&`}ajCf{03H;Rj7T_!ANl{C_S&|5|xew3U|>5WeJY zVF3#iLRz;_SZX9d5mSk@1W2{=iG_0?(4_hq7%P72qkmci`OG7pS(yI?{Gu4+m4u2a zu{C#NH}Cs&o4X9Gvtb!wk*Zuu-^p1bVxzEs#A%s$`nlMJe}S7 zJf?dTVJf3!s8~-mE~(|kIZaW5E0GdRUXz^~M#jtm6&gi@b`_0%#x6CQ6M2&DgNt3aL zpaZ$gUXrH z`LEmZvSNjB=T}h0rBy+ru?2qRsUdPwZkg7?(^0FIq^?)<#p0x!P-iDf85>v{RHrgG zE&`F8>&b*Bq9e(M@d-xhMmxP*q;rikBRx@6Mg-z;dBkC+aoE5Vtab(7e6{Gfhv?z2 z{ZVT~cZO?mv0*SaOd@r2RK^$x;akwl)g8p=c*1SR2U{{mPV498GL+~_L2iuWuHT(b zSR2hx-&oCo?%&KjRxyq8l!N}sYv~dr?u>%;)){;td?0VC6BmcPEl&|8mQ@U9=Z-?o zzC(+G@4Le!yz&c61Ux2yLclcmjw}1`KpN%RH4Jvphn7Zm!cGjrDv{aEYXR)PB1ScE z`LIV`!8pq)bkHue3gP^TyrKk%+@ki>!6lYl1E4{UD3K$PLHLLekoXL{18aS7iTJsM z-OEp7Jme5aK45xgOxzg{9i9?SaOliFc%D|ePhSV+2nWuG-Jd${S~Ul0PUynB__cch zZj5*CVUaPvUD**PyUK|_cNyl3+vS*quJo`L@=e$Gr&s;|LmCo~JUAcpGYu+#?*B&X zb})2uHg%%^(S|7e->3g_{uefB_N!EK@bobh$+(q%!sa#lNbm(egN|~W!+#YIT+S7T`=_~+yB`^jF1*B5n@=@ z`I*L~^VC#EU+3Iq1#cZka|7z{PJ`s6#gh&2!J)`Oq<;@0Y=G8jXuDmY;8XCv$q69||?Sn=KRle>0hky}h-eg{h&5va7MNsq?>V7plN54J?T8 zb>fsBdwN`vO29^07+TdDC0h@nLkMz}K9!`y<8Jyww>Kw6T09PaCmxwBLQR+%=;{0T z^{!U~D3LQ-UVup~qMT1VPr8inl$;(Pva$CNiU4;l0{sL*KtgQXjEy$weGU03Xtk|^ zmYOv+vYG3nK5I?BB*klA^L71MIfX}%QZL>=n8S_&FnCA3(-&zkePm51nRB3`WH|{{TD>qnqr8t+d1*5H4o><+maHlNy0U+xYU}`XpP%&o zsW14;Zug}PFMViVqI7ucaQc$}1@KB-=|8yLCfIYhfBV26>;=E958yBQY#-29*4Xy; zVetX50uT5t@Jy`m4e}RyC0;NW>=|-zxBLq{t@rrk`?+4|Yn9-O@*DpqmrwyC06D!7 zKqUY=Aq0COe=A>UOR6$l^-diEMV@Ma0N!790U&sQ6@&q0PgEO=0C&YOKMYvRBL&8k zWJ4_QA#f5T^;oTuw;F4(BPqEuMr|~JAAMP)pF?E~m<)g{$R4TOnIb_dPdu~w74R(p zXp0s^22dKYyduCzMOq-WGnEP6T48c~k_CRVR>qy0na76QADZ2~v@ur-v|KY_J%AI> zw3Z2e*+&5y0J^{%(SXqa@`etS#+mxGuo{F0yc$3Suo93pK&xM>pQ_)gAFE%hpR3=i zAFN+Y0M`K7fO!u(;1S>yxD}uk2q?fdz)Jv_0AdYp4R8(80^|zl3XBCX3y?NIO#pij zNB{x>Oa$OMfHwdd&>Qdr03EOwq8-Bla!;w>G~hE}3Q!%O7DNZM9m@fBPpdy2;5T3` zxDTcS@E&zQ9gv;M%My|5DR3B4#R*bq;A_@o(pYPS%tUS-6S}!oqnj+A;&2koiOF>o z&)s(M&nZ3KUclsB_guszDo`)nJ-fFD6)n~=wnYc%oos&_k4@c!tpaX85)n1u1w5Z9 zEXZIsWpG@-xdZe@u8=*R+&H8BC>BtK#W)pA2w$Y5!`%3$^6-PT{;5NPUeGO_oqr(Il&`obzz zq-Z2ZAhNYP2JP%&T3*9}xYllLixukTLqHn-+pWPq5kl0-IAD^;x}GVVEXb-;?q_x%1~XkI%Dt&=fn|Eac^BnvptZKFg&!}uMNIZPOCo@*bS@IS zEn-Bu!}ogDU@EDUA(W*g>gLQ>X}ml^j*K269NT?9LMHk!7e>~H)Hnww0j9`DgoFh*WJasi_sDDW*H9ABi1jdjAO@d#H&c=4l{1rIsssOZZ zGx>U1a;JoErzOxfg~9SuROtFSQH{x}P&vNW1|zW~cAykYS2`*GPzGt?2M@o{k|>A((WyHqlt2=(Hh|oMV_&nq#?CXi`CGsMWEqWz?FMSu36O@7fiy)7mz^_u29UCK&6J9QO_zo( zSVhY&f{GC$xEHqlm$RKv)5`6SaJrLN3o*(d}X3FGqtpKAsO z_Ogx%J?|WAE1Ig&C8@iLMw8#E_H6w7(aL~S()c<<({HPd;Q3Lwwz4Bw1M&zsJ*M_N zCPi;&hv==%*ixE>+dp>oTN9YL&A0;+vJUnpHF_oLNz}F(b7DK0OpGVC zZQIVowr$(CZQHgdwyn*(wfkeg-L0>yPj_`y*ZI?3=jyxf3o6sYSzA)m^R;-DF!!~Q;$a;{Z$mJ?MIRhhf9YvvMlDQnEe z&&O++x_w(;oVx`Tx8=4M6LqP2=3HrX%Wjpy#%+>Xn7Si#DsDNt@lJeH6~8JwODKH&*nO10if`?^wf2iV+lMjk zNw9PJsF)6~$KSDYhEvSPA;&iwnIk(E<`WT;a{i9<>RpJAkEGjcyvB&wu>7fy`?dcQ zMp68s%3e?=rOd1|Wx=#m)XvN-EbUZ*FO64dj{Ob7E2{`uA;{F7T(hv4SDw;<#F8aI zuruV+y2KX6qDKY*I?h?1b7|Vq$KNE}R%>Y~cwCEbM?jr8$_u~0R z0Ji{j!?hyap!Gib0)VT5f6x}hmR*l`m!Y@FSMmpupZ=p_{*MwF& zg{YEy{lz|4nd*WOElo{}Q2WF9bv^p(x&A4`{tB!(HAy8AxVrMN_?g-l?9NGR85FCJ?%a^+l{R%cz`x zGZr7}Uzx*+c@CVbr!^etK?8asy!2|NY*$34kK=%iV~ig*&G(+jv4ry(7m z(6~RW%|tdui!vM*2CE=W^^H!ejLT-Dr%PDx5L@uiyq+sO8AbRh$me}n} zt|h9)CJW6M4vpOZ$*B}9Ae&!z#?@=C6&9x?^#g4y~`!R9jP@Qj8ib(fn@$NIVtItVTVjE7S6fRC+M1%}D_Cjx&DW0~s zzWxx%BS7vrW#9UP%%}ewcGTYUB5JoNf7^Zh>;Y-Od33#J@t`&oV0!3flvXnO35z+` zvhv2K$XP_&R2+}KE0!T=hl5h6bCu3URbR2(_AlGBW4T(VB@o2wyrs6Oi2@UmU_Y6* zR6~$U@T9DR29u%b6=fPsjlHn}Ce$zE5zDY@LL9cSvH8Nn+6uuY27f4J*bR5sgZ4E3 zLX-U#O>Y+bvMO#Dn>`iW^m*9&45*fRRWtTY8cyv<3A&ByWG?Z_$yeJ(edy=f^j>pu-9ZF zeD&ZHV`!USGo(M=bP)-saP{8|q?w0GP6BmMR{Z&pZEvr|rlNETc)vo1blh5RiKv}h zxYpDgE+;x&FKe@)&fT?W`nno7wclJ!ls)xj*S9eRuDHqeY7Qx)kZ^~8Z1x40WgavM_`I0oSWU|>Lps%z)t)`(@ys2(vQ_2G90*r^<% z)4V@A-5iWFV@@cGSmTb#_m-_kTDqm5r1XoIF20(jGNZ11&QYEnS=vGEyKSu1Gj(&O zOu2C;*hXx2xu^qXCl)Y2Lr{=V*+@{0gUQiw_rvGO&eQ5A<1g3prACMVN%)x$p$w|Y zhQevlinx8eezK^Cf7Y&Xv&qg9+H@0N{dN1=qRC;6y~0a%#}wRRaCxG3m9R_uBJic??1@P%?BBz&0)7l&y{~ zDg-n@b@*~Z$tTX?l_PB$FI=)6U)i#{&-H`&`<1wc;!*{7JUVfMR1ibTo&_gWBka1v zkJwliBAf>pPqmo?LebS? zPb37vx;k6*KK86Q3w_o%9%N9~HqdBjW!~2y5zRpm+I!*0n`~GML2Aj%_~H!F*4kNH z_PS^E$(kn)ukoWnbs_uYt0W_C{*Uv|%ercE}1YI~%qBCQ+lO`$qE)n*ZkqH*Y zHCj|2aBJi}6n#4rs0*&M41$@fyNHXr4E1fuBvG6T#{>Bm%qrR0sX;2d#!6C` zCt$_~DU5nH6dc~;y~N4X;`&)$Ho-aO+)R9MQS6Jn6V1GBs`K)S6X1}VT@SPtkAtXk z3Ome#q?!PCL36!ag=G5P7%}JU2%7Qo$xI z#v0PPB0Ew0cwDi{R;jclhR?$03pT16mPjn>M2t*>fYa$le3q_+Hkb>Czx2Almvp7Z z6G|-;?%Uf5b#o@{E-r}ukm%BKuTycGhZop%XTp%&^#u%O zl~h!WlUZ?F(pH_5h)7gCd8GK$p6K5{P^2f1qSC~yGx|01?~uo{^uWmGf#XTtFAO{C zD<7vJ{8&!*RT%Ba9)7$LMgwN%i^gylK=JAy#uyZn)$21UCScSJz;KKYIE|=hyCbVV z9ce_j^!Yqie}~U8Oho_Fs;kM%?0B)gfSUg#L8G06RdhMkU-KPj;Lbe_18YoQ86EsY zLh<46-8m(*;~jtaiINB=SOz7Q$f0I5P9vE}tFMeD0jU!~0P0yug_~B-j%oPwDiva( z#j9$PGrxYd$jS(u-LQ2&6Ycs5`CIa4pVG==k|x~6aO`we`|@KB32?VKg)a;>L=_p--<}}^@(z0{E9fNG;|#+$n0&{s)n`U6}O`lcu9L@B}1{| zluP+2G2~b9&m%9BtGw8^0*_Lpr$w9b{KQkeG4pPb>HwDpk(Y0~>=J0vxI33NZmErRy zX7{Q^sdI}Vt%1scCxNj_gNgucu#R|OX8FHbOA3FlRpepD|b%z(Vo<@ z5Ze)qc(W@sqGaR?PeBY;x?~GaRt#3We-@rV(wbLZx)_aF%2BMXew$JnXs{?wjHV_7 zx5VYAy3d=GEMf28 z?fYX+XV*rOJ}YYJ-pBGFH2HTQZNC8rvy)p2L3rrHdWi#=gdkdWVqdN38NuTzZ^1EsfM5a>qC9k;D(xT4eR#dXO}qx z&su$WJzn+Lr`DR6ghhwq&IOq3v@-yS^X-Wsl)6urxHAI3RNJzJUT4j|yb93+>AjJI z_pNXTkn?~vkaa*$J$_{rtQB*5O8-za4ndu5(`zc@8*}aJt zPRrQLi^t3&q&?G(Q*>xtPL~UMLDt=x&J-OT9}+980;1voLMl33!eO5vB?a__cIWyb zirClJa=j}hjm?~okN@Xlg~T4NA%<|5Ds;!^Ym=a8+p#HT8P2#ElzhshBSV%msg$*P zK3-t^85eh++j(6Q$MmtPDbtAIbopVF3EY#mmjP>t6V@$NgYeRR#rX7&3vi!UX00@n z;+;wtQ$^Btr5J>0Os|G>1V34qR_)l)48nA867;rd%7s8tCN3osT7oerm!|?x5?Q3= zcMH>?DMb>hLRuuxUxpbMUF6`OA~x^JJwk5cmm>~aCog3eI)pN3k$?41cM^-dT@@l# zo5eI(cRE9{bjgHfi8(FVdch0<;G)9V!AMzTCgDt%Bp`Y7!x5Lu$PG9-{FLpu;659D zt#l=E>$cnUBRNY${ocGR*%|F>g%M2&{@g7LEfooECqy;#-4Fd2f=ktH9BB@v{Y8pA zE8@uU)5Ej-9yR2Wg9V#_aby)z2~UB|wA^*CVvUrtWi;h;?9}yPuq7R%a%qMoQsE_1 zIH}8OuqE#~r3}k*>F9E4{M7X==<=>rrE`|0_5$-QP{obJ+;vH*CW_+q#M1RdzcQ=n za;tdrW6tufMWyp5p*4%(wGFaqHwDJ+q`SWq`P2oXUTKS){hCE41l&lqg^&@#Zt9Sd z_IL^i;>|2%&E_~8;PTB3uO_jg@IvKcyI=6h`!i&+q1~MUEST}#zf}ZA#pRQwfa`>JB$nX&nu4%nUcq2a^pAH;xBY^bI>k!>kITE+b?t8Lcca zMAxtn*sPg`Z^z+PtRlCR@htuLb+`D#wC7hGYsVnGs*E>#jIf^14VZQQ8LdKO=%;Yh zRkhS<9}PB74>#|GSye?{+LJXivoup>uBvRTR!7!H{UNP|%eU1cm~c!=s8nWASLGak zv!`BQmZ?`+H_|>QKMz(b2C$EnH;uJVhgHoFJ9nXIMnzptL??TZB%cP8D^?p}%Sh>> zNeOLYPJAW}-mR%-tx8x~vU1cZudQ~Y8+(XUm*X2MdsPK+8&yVTaI9)Wd_KZENAT}# z_Ej^U*f`co{(4J>clP7=X$Sy^d(*_LoX+jBQg6abR`#ecUfMQMZ`!G=T;HInc#2kw zv9`DO?3}u-;jBYjTeWsJ$gnhg7fHM{z#3*DjQgiHIjtsX9j2i`NHexX)0cs&&MkEv(o)95<7Rw$_1l?W5?`bd&(~d*8UiFoyb19}n!=IzaDahuGu?G&r2{B5rpPc6#WzKKq|;Mf7)I1iG}IqFl6l_)nrwseEV0 zyrm?ARPE1eMQVNI?HR}}4yhJK08VJ#9ma$iIKrxpkawLE0&c+2*zI@2u-XawxMKsl z#%`wJt~)7gXU>Cs@4_ML^K#q;>vFjUA)X-DyIjxsI#VJzUe&! zXXnf;dv1^`+b9fBeL%<-d?a|jq@LsUcVgmr;1_&`M>oGbx2L?V86G5p2^d?T1_~NI zz4t`_w68+-tbDS0ltpx1sCKMU`Ko?)S=!)*y%=M7OaXY^9P3s-B{1HTb~b#iZRFlF zoL<3cRaxJiFy5uf?w23xTh3r&8g`r-c5(_gd`b(9-!rVAMrfbN%Dbf%wominaK*78 zn6b__aj#zj-fYGl64xt~w%v}r%nRQpWO0pN=D+M^03Kl+-5nyEUhhyeYr>Yynj_v+ zo*t8PulpA>!S^x3Sv~P2(8rqkXuo);w;R;GBBhEpM%HwBWFsi1>WJq5p?uhx$ze#M zLzX}LSQq&9y->l42=wJ7;5m_GXvqgsIn-BG8;NSmJE}&eV$)v4=V;Dg&k1g9Vt=a7e+S@$f1@XGb@S57ViEM-8fZV#KRq9xsF!_f z?OzvGCmiGk-?C3{?<|sNI1z&_K&nHk^~wqbTTo$vpDC}X{PS4auw~UG|7Rxih)lmE zd1H}wyo#A~j`@yw{0^yJJ~Py@$~$`}A5?Kac|FMBio^l`4x7sW+s8ZoWybsIL+Nhf zEFvFyl-aq@43I}If3_@(q?tB{usw7DLNEffSi(|303WA z6?(x<@E5E}aL<-`sCAWUiU18%ed_`FZUg5O2l6FCt)CJ8r!Oiu#M zEqk;_9RBQ{>rIb91J{AuzN#gxeN_wUO<9#FtemUBphfO6wJn6h<6u1!)K=+;_JK5mO~tPGS+2=FNIk--OaWbO9rq4e z7BTe%*iN$DtgNO~>E0%0=`o~85hX&%tr-7U@r+(y*NR@Gu91lXMa`Y9DjocF4~7;J z>1SS)m2(zqa(Zb$?4Hb;@ZGw+V~sIFHKw7b(Xezs?Vd=xH}y?WaStU}Rin~g15QLN z=<&e!|dd+ z>|SrSuaPJf@BTFgJ$)-}-(5`e%9>R6LMvgjM47?l+JJ1}T-E+JF0KAAa)E-{63N zsQ){HilB|PgQLE+GiWsG2rT&uaOv3TF~!&3h;fd<}gjwOZ#4i5@swnP*#K2ZF6*}nI>x@vpwdWLU3 z-sZekk#KvgmGnwlToLoiT4WXTN?2?W^U7Fs5%Wq}d=~S{Sws-~j9rWo`%GPw75hwF zoDuuXTm*=H#xK^0eWowkhj?=#Z{AS@wLY}qMVw{pNrLyZ3(!8nvrfvxD%gB z7qTX73%FCAvdnLY*^qSwJjl#y`^)2&jh z#*l@E#Fw>7;UQ+ggBvA6%BE-j5}(Np+oy2D2cU}yC&(y!?yWN>?1eu3GE`!sBe{h# z7gkgx6R7_ofeXZ?D!TF-QF9@ov+HfUo2&;yBFO}sNV!4*!f$*E;0w|lriP>cE+J}g(iA9fr6g4@HBcz({uy~c14&ku zQfu^R0E1Cdy-LHB_?R(;ar;opdn|(-&Eb`#ljrp)#o<*8`dW2s!DGGCP9L~H^NJTe zr#}S8e7KF%_QHHqH6@eunn}1sT}bix$<@RZsa1;3{CB)qzdKoCs@Gj8UeHi9Y}<#x z$W82yQruXRwW)bl2iM%;SI+|cC{xTx;&T#jXyMUO;r!-FrcydiQm-*c*z)T|L=43g z&w241LF?kEeh)?J7(gtmVaW2xzw=dqUuBfG#^}&XI#x4rso}6M0;{B9xl4_1V`*1M zYicIN9^4exm?^#Umk#ZuX|k~`kE%87bo7LlJw`*(l0i4F&bWz0z4xgW%Qe{0QYEU! zR7#=mgx6NvX8qXG>*V2mM$PpmS0HVU7H8N2%j;ppjFe;qRd92kYMVL3%G#em>F#&h zvx~}vIm$NBkz?@ckwQy zucqZ=?*@mu2k8rHf&khl@h~Qscld6k-=_Yu3+x4j#s~RhESVSFyWy~<*QV)% zLWo1M(#? zp$qQQbXeopvwXMGr)%?yvuo4%A$`ND`Gx*+ncRcs9dc+B(6e>t(z|2!+Od1x{2}w= zapkhTWAUne(?R1y@bQ`K1N6l|!3*|Xdr08tvv?QN$7}scw)?F1CH_)E{mt~jnCyf8 z#XiA{FtU~6BOvZ2?uB)!Iy+ZmKIv1ed`Y9aRpi*7UV(gyT`f~+(MB3qy}vHBKI9a} zR7VwOU1kWPt%ZQh>if6}#bS%HIy$9?QUjXd#@!mN+56ZDY^e{yYD+cRiDY>wy(_Z) z%laS9uE{oxb=-E<{03>)MxhI5iyx;ePHRF-K!+>j>NIB`{5JU2k@M^no*vmX#B(jq z#Xp(ajAvhuHrR_j>)MoOf3Ho@CkFsquUBr!dmleOP}c=;h$|wl34pC%aF+)k;`tuR z)%V#C(v8X4~+kly^~Nd#1O)i+&{N6A!q{3` z-&)`Fe+R%{YI%4n4L#|&4qQ% zazgg|&CB~O?K+M9crq=G(G>sr3J&1;Ft`vHtKi%d(>(Vr;0m{w0#)My^;Lo#4_3rD z`lgKh$^025vcorRgS0L5qzPr31p2e3df$2s*eEAT6EM1NBXFRgb(HC!E)rW-sVm~1o@9o7JUBfNUM9=puTL{AXeBiGx`0)Dq zdw75R&rOD=Ufsmi$ws7`N})FFP9V=ygQ)s%c0oW|eO%qe$Z z4{;|zl&l=H{)#Kkj$=QSo17v2Vp1xNorWPXG*Z>XF^wW2ZQ-}!xj^vPujj(88J|$Q zlgui~S1$HwAAu&fdTfU?PHPVG4Y?sYu3$vG1CiO`9z-5QIIPZe%EY5F{$tK!V=rar z9l~hgmiNLZLXA&3h;gnf)Kh*+)cdrB=+V{T+B4D8lgSldI-xo+#iCz`Wn<(Zpg{r~ zFw_w~{Mfydz}a&U5IpTL@gd>EbL-wx3>vq z9iZ6$(Yu0T0%9UJ#D%VdzwEb^0-4mBC;7x=^EuUeN2HSdhNPm5N#a<2L4%N>h>_}% zMD(X{1GNqbX`2EJKHRWzsv79k00en_riO9RlE1I(Z#go6I-oK_>7XxB4XUB~1juC! z64p=&_@D(S1h53yC8%os%G5H0NlOa+Bv2<2@72aS=uq-t^04*M`z-_6p_ri@kdBBZ zMb&)eB9731Qwy*m=+m<}^GKZ6eoMx>_@#oU^2cG#s&!2#pIN3&`*UbkH=uE7mNh_R zRn4!NXI0IuX=MFWECtic=avD}w2NyZS=xmS(i|I=4WwCCbLtJ#8jk4mYbse*3v13< zO=p$Trksw;)eTu3=dG|mILwRBH$!n&CSuX_;S`TAuYdtU(3$B|*72HZ4U1b|s#HlA& z7pH&yX#eP6=iLU&r6N~VRiQ!hjg1m*>CQGdS(M^XdIU*1q?@k7jkF&;)BFyR6Hg48dy1 zXSP$J>R@s=5X0`vSj}Otj#_YP3T)=V?M+v|>RZn$s;R1iea={0Xs)+$8X>4o9`{#C z8)xYKOX>&1J}k{cr{zzQAHbpj924{J)mKS(vUOUo)%M>B^~2CUpwfyjCY6OzOYQgT zbIT|7LJmw&B99i6#wJ;%r{#9-8KXfP8E2UMsfDhObGH1IYz5Nd3VUuj^Cn+X#@RV} zgs`!AQ-23m50hv{7v^j@z+vqQyYMpsS*$W?>=d7RGUrWG)!yY354n~hAm4~}5XG&S zOQeCz&%`*=#294i6uOhUv+}o}r8&r2BUpXC^aApOv8%c;$lBt6t`t!kSvxC1jCZ%z zi{VlCBTw1l5M9spWlUR~8-p##DJVZ?;L$hrtG?x0;FG$j1f6EVsL44S6mTVKH~f`s zS_{#hUX`<2+w8qg&fKalFaHHjQc;I*pkoa1AMT*T00I^?N+ECPg6@C5?905o9a@_j zKsB)OdODh+=Zr3&}Cp-Z{GUi*MKu;e)^XipRWJ&-paoHk@^w5fhNl3m^` zoSzW!cA@V{xF_Xo3)ws^$j(hLIcMc~WqSeBBHxi$z|yWS;GXq+zn@~9!g;&H_A{$J z18p6a)`(z~GUVWRhhw?Q3Uy|6bw!F=ZBbceScpSXNH&^O+J^(+2;wJ3dN z>Su(~72R$~eTV38seQ4U)RyY_Xhhj_djpNqzBbhrBD*Z+@Ci)Ip)89EJtriUsln)UOJB+ z+*>GkJ9X!5^>zo^5)Ueg^W?03WJe!e&Nj(OhUIJx>T%6900zK!W~}pA-`1*tn4~;D zF6c&ARbyRny5tR8-q-LhLUSGkO4hQVM3Jrp*oM1zOL+4EuWPDnTi)n>bDr4X&w5wh zOlvVWB!M=+GeumH_v`{Y{&TB;FXydsAot0hB%R5Vfi(e82gZ6XU?E3u=K6lY+Ods( z^{|#9<7WJD4aC9~a??lC)+%`2r7vqdqR@$|G_ZAinRHsEIp5*2YM1brc4+`dC7ONq z)3izFEG1qQE~h@RUg_l}e2_;wr)x3QBA6v}CtgY|_SF?|Ms{{Ioyx6NeOD9SI4U}4 z7N{9RA+p#~EDRAE|2mKvaVmge%S*FeDa-q)z@Yk(+@O-?C4(sVamtPiO?q7wfB`YaLX$Ab3R$kQz@cPENP2sak9geWib2LZWb2UqVvO zZq)vOFc#RB;{P=oGK;=mb7iB3va+}=wYl^~lt>y{pMJ{DdUm`nvL+jmpPJB0 z;_6#|9Aixm%Z>bOBLhJH ziRjH;YyGxs*PNAP^Z9cnl6i&Zn3J1gU;fVyipjSGs00!$$csSNes6h(;vy>3J6Q22 z0sCwI++2s$mCn{ZDmMq^L4&_$-;p-*;Qj&Dcg2t@@OI^|PDN|Xtmq3BL~uz>YzzoR zH?35Y{X0~H{aa{!fi(~9gPtk6J4tR(&GfKF4DzG*yRlleYgRLoLU0m4*QXF?^?182 z3Zj!La#9bVvM#sYJN)G>6q{(<_{?r)HIQ8M2(#9y*JZ!z&yYeCAFnvimEU(8S6X5G zAM5W4nH>h99mk0q%FjW7hiwEdiC2!R7|bkdBKE}Wn^?F;nZQPwgbZD*%4r=o0ZDMX zn->8+h*_6V!<#sV^Hi!!B3Ei)TNh(zsgD@msFLK>{!>j$R`1TT6f(4%a_lnS`Vh_J zDalkaOg6O8sQZ|@UvuqT;^UdgNfdHqEV}}mRqQNmzb6GQy;!NA+?dk6J7hZX0sEo^ z8Dva6?Y5cW)mN(bMm9Y1`w(R@u0c;h_3jythq!q0$SAuADHeMY{@TTG-qe{)!^m$V z_Lcc(Wp~D|U>Dt@WH8i><;$;M7oyhj8$}0w+P}TQtgox2WC<^!pw-gwBSoPkz)epO z3*;z@>J*rns1Qggi;C)sQ(Wz1L`N1ym6x`)LQ&q3y`r*_?Cj6khicbk8MZKaE(UK5 zQcWZG%AgI@*3$#%Eu;2^>w_U^wakL%An3xcay03VdV^p+S@B8nWhZ?@Ribd$1Z0#z zfh&Aj>Hf81;M^o2)h1s;Sj#T@x`=^p55h%qRl`~D!k73(^ir($BDVlriGikX^uCb0 zK+bln9i`L5q_n|*Bbc9$vPy!3+y{hIe|{ zI%ayQ`!wq0d>I|#*c#?2*$8bd(F7te9$I^Bzl40-$MwFNC0O6u@1`JqLQtOp)(rsj z;OqiX&`nO~C%qBr6j{Fg_{DGvywYJb{VXiT3U}?9A5b87CP`BLJ+b@eaO*mTYA#6S^az+Ec?@Og@S2Py3 zMAM`pT>Mqz2-Xll;afu{M0bcBC0nVl&i<-y&THnop~kCDGH~UMReurrxk2xNRWR8d zS9=W<*&yhT-#GDLo^i(&yg(D{PP7GjsxKD9-+$vawDj&0_Jus35&H#oD!BXleczs= zHjcFDuY@#I6Rbpa_ZX`p*#2YFNJF_pa-t)qDs;EhgyJy z!7z*FPmBD(#h(JL0XPAXi7LWGuC4d{G-5`zs5_Y;v~ZQD_ZRTU%e}wQfD^FF(zfU( zk8X;n5Vq^m*0N-!A0xBO23XP@GX-ec+))IA;d>eZz@IB(^`f)7$YLEWu% zVY2`;tsGFNVk^L#=D3phTfb?IZ12%_V}?j7xmVPT*nk(kZLD=|GMn+Y@Hqig%X4Kc1*C1h2LY4F1RJ3a(RrfGb3+F!rRnMvo89AfZ4{z@q<~`uITsC|k=r~}m zH;^7uBQy1EP>ktW+7aSOgro*8HBM6VNb{T`bR#oNmg!GF9g2L20^^#{WQ)tcM75^z zCSoOoO?>Xl(b#v@*p0_exly(zy4yLxFa#Y*E8AW${}nj zp1t7qWvUpP(Y*k6A9Mi4D~2ycj>)kG-W?Tgc@8^c4R|n}IBeHCyHRK|5Jyq+j|0}9 zRGDwW)mKIG?R}*mQ`TLYu3f@%Hl3Q+u~fVlt4&(3R`ShPv2Gp;FIva_`;8<=Z$zfm zfIx1bbEZ@a1QCS+jpuBs+dye#hfbYIyM`{}*b1R9clwc*aP}`h?vVp! zkLWQh51BFD%eFrR|K!}?$K-MEwGEbc%l{;oc_p+%uu<6K_k@pc*5#`R>5$zW!jTGy zr$NIqK07?p=jtFc$0?ixXYcV~{W}dg^p;c&D6#9wy4LC@0vmbx z_p)N>X7w$?eTZ}hdIOD6gN(mT&gI#5bHUu-Kt_1!`%rju6Y*3|?JI@Lc4vJ{CrH2ybL~G_0fx**h zv8^*nY!kufBR1e6+IP~zC3O3v+xmiZ{CZS*X>ezs7|}J*s@9-gDcY90Ntz8jJJb*q zfw4A%sZOQUAqZxnR#-vv-pTG4z%~Y1w>b}|-Fl}#T?Q=U$61*x=i>_t%g45MJ22JH z+D^-8d8 zFz`d?b*q)JSd0t@_d1PxBT2cadnSI7V9YP1a}lN5eGgvBkI0!Uez!@BVX!?^VsC0L ziFY9alRid#pO};GpeVBq)vAA*>Qu5kaB_5U;vz7DB?l4H2Y~*2&`qm&zyL;;!_1*@ z$@9Fvj-xy4`mKn$US`W0v|B9|%A2;B=_P}=zj%UQbOXxq6e8=5wsYEjcPOh#oKF-Y z_!+sIvw9i=^h1&)VIPfFo8k=t$^%ZUw_s>FpFhhYr5Jx)2)FRhg2$n$%1uiCpcu5J z8B~IXka>eY`=}JgwfLxIdG2QI?+EyVnQ*Myt05!#6ym&&N{i z%YnJLju9T!xEd7i^314Jhh?|0tiglknWozBjMwqpo<1Xs5gq+Ioi+~}hw~o1H0!UW zv|RCJSv&emWYH#^wf`*P-(|hKfc+KTo3nbCI84od&RfJmS%N#X6*xi&OGyD8e#(cM z7EbBLfA&aFI28W4y#`pk3=iC>9e;0>v8*d)ev2B|Xn^M#(KEw1FEiHc#TIH@D zzLeRl$AO5cAjH&9X}i1XyQ?GIIT;U`{AP=tu{%Vwu1L_b{_**RIWF$dsxdD7xBa3P z_$5h=_lD8tc(V5EuCYo?*CCZR*&WcURuMC2gSkYf@|IX&+fOe`9MGYG965`l^{O0j zSVVa3e7FHIF~Qe8p9FBmb{dh@{{SXVaM-$C(25MUoR*Hsb}JuT6WNYhChQ3hi#in{ z`9?bJkdca8NTyG?{{2b+cokJ=z|>VaZ#He{J55b*8!5R*ZCmU2*|GR|q|)6_30=B9)DZabI9cu_C)qBL~) z9r^DPv(O>P^?ZqHd}iII6ZiGK?u}Y`_BPfeoK?cs#rQuvX{O=MSQ=L9N8tNrhcJ*7D+reua01XG2qpkg+oR(fnl`4fccl22*llq z2i8Hxl?EFQ3PJPm1lGYu{_=e?{rKo9*-qGO3FGL!zsLNV%?WpB2*%SqadMnRt$lC8y@M=$;OqzJ~jyobqe9JhdwIq~h${SWw!UMeH zXbTs*C56n#+aM@)j&Q4ODQg4LcjnU^t*t#`w08wBbn zKk`S~B#s23Va;JRL)>fo=82$*8COG)<2&$gKQtmy-lOXw45as&n433UFtf(omuFts zu+M_gekq&c+m83*APWx0W8h8N4rylb)yb9zL>bvF)r* zRjrx#terHeTh0U%GYQ_;Y|ok3)Xts;r>D;>n!xvWcCQj31hCth>%b3<&7C<@TV7Jz z84_DE(j9*$o&Zl>DP_ilY12VSvC8Xk5MG`hmxH zv6{z(wnv1e2XiSR5o7DvpLdi%#}6=~txqr_;}bF{{9}~B2dGMn*TaGMy&g|;WK*aw zR*4rwCCh8e0D#bF5&@$KhEP)y&H8vWG}l$;3r~y3?PyQL02qOQ=ZhleFLm&Yfuk@w zPtR5a6YoF!H(}r3dPhF@eNyNm7R%ph2qxKFB{@U7XJmj5-U!~u+iqweLtd;m>E0Ed zHUMp|pK7o-)Xf9gbKftfo3q&&>g?A+o>aFnH=H!~Nl3<$8MC+L$Ap~rh3Cf@RxiB^ zQ^At!HCgMoT)!NItZo}m1A@s)hwVnwU-x~JtTSUBJtt%}ZQGyABlonJ?}u{N-tQ>y zdPf-32+Ss%2qq$Xx+0;?=6N(9@6T8T7t=C-?rOI48puY^+lthmW`2UlDkw)}V;R|t zz@JJ`&g_PspoV(v5g}51S?vO<{0a_Km!a>@c?4(-uN1|-4p@`x2+YbK|F{*@<$N^9 zbcPMMH^g)rQ+ORv_iwy-ReXgSK6mtALEU;;)GKcyuwHH|9=Ir+ddTbt(P3M1t<?QDz^W*KX8akb& zxEo1@?-KJNPdo~RPddi@DiE4zi;DD#@7y3CCU{w(xI4~NJOKE82TxMmsj|_0KmF=v z=CR07xUHcLEbHh+{2Bn(4c4J(xeYk4It~TgY|lgWIULfI_AJ83_Y9cH8=CIeR6hLk zYu*KWg|t-@Zc47=hV1Jr`i?}DZ6>uCqx?{TO7pp`05Rez9c)OH_Kx&a)6HBF<)NHb zdLQMZ&s0i8HFbX{r}0*c{2ZwtFz3GAlNB}RsZt$eRZhIUnJQPYD^GI@r<5eac$Rm% z8;~LF6-!iH1cgD>44Vpy4_Dgiap}*&v~=)efXo}mWxk7 zmb&nQl<9*pHj~@#RfE(sC;Vu!+XOXN;aA-ZVz$Z+zF(3UYk5SJ{&=8$gnOPIL|dpiR%vAlNL`^$fD(O((gbG6SLtCbTrIEzRa&sFo&B18W%j;y^+&nSmYJ*G8SSELhCI`I z83{S~hm}-TuJfY~**UOKy&g!?;ckHJWb~zpH7j@RmIS4B>)&xGPaBWGyesHX!pifU z{NwV0A`|5AnS8!25nfmN_PJ5Wl0EcsRj|mvjFnM)?T~Y3oD^rhFT1zqPNV5hv*tAl zWzftYhk~ko%t#8#RTW7Z+3px~px44L_vBY-OFHjkKkw>535@lhlwrpPEo1*xH;^Wqb_J@eGoQaT0qAz*E zH?sYMDyfj7s8{7LrTzJUd3zh5p*7!<2%p%Z(Cb4I-(jTfi4#dLnOI4A%tTV1B3?97 z>W`JbzVOvf{zr$2V0)#xZC#)?cWH@rg(vxNZ{n;r*@k32@M2@W^r2%7@E)?b)&R7It=qnuJBTaW?h!rQz z0x6s=B;gB}(tsIcFvE&9NJs`vvz&(^RFvXC6AKeB0j6L+btE(gMype937KT!j1yv=H^1g~y=k`tuxwRMPEWVgcd+ zp!)H`M?RGdM~YZxQf&yMD)9imJ< zLgC^oe3hw=G$Ik=EBc+OjY!19h3E7pQtiM6!-W_Io2ib51LE#+b@&)K0ZkBNpkuJ& z0fmfOCiq&$I$B29)$~~adVsD0wypt(t^rT?VEhZRn~7q3h%Jy9Po-p&*eGq5eiCQiB?TNL@mNbkO!|1-471+2qlS>Oaz9MOkByQ z7B=f!3!~56j~&=Gh#-P=ONSsJA}A#(jf8|qe6wETzqpHj-?#Vf1NT0>zd3WxnKLtI=AC)` zinHF>@jdyah$8Y+QbMR_a3h=vwn{@}h-c2GyN;`O&fjyGCms^edEZgD$;~oXmRD(` zvwTn6E{JM3lGCy|VDe;#kjW!_lE!(FA*PueTxUUd`*gnR+!TZCGfZXN&xm3!sklhA z6OxlykTo!e2#6VZl-J=oW|ngp$73|Ejn_M_KTOO`(&Tr4@5-#1=yvjC)vMGpHGent zXCYOg#&XtCRBb8`!ud{dGVZwr?;clm!j~&KA(3(Vl~Sf+kMF^Fw*FMI`BN9wzEE?8 zPbN363}8!~+j()lk!{h~BVFf(cqtnr%G(l(%EF)!cb@7{>~n5LPXeymzAM1(wrMl1 zDjrlQTm3Aw#naMq_wl%pUhLEjSxMdpnVodAkI#`7gt#?2`P0e7o{xHxwvVBlj<2=>uZu3kt%TD!>Wi9HOItT#Yo}KO zJAMegQdtj;^!wsqq4?{oi2>cK{sHW(#QfxEModLfzzfLvgZ$?vP9zZIkHUHvJ(!6Rjv~vLvT08Z^_sqWX}J z&&O3%o@@EJbaUNlpuuSB<_`!E9zL8;tRw$u@WVplB+#i|pN?wU(% zMp)Emn;KB<(B$#P=%sn;54L^j^c|6q(m6f*iu?}u$;|Mx*>jyZ9+eiy#~bDemp0s+CZ_5z3%`mglH$g%mp`zp{(7aC~{V+(d zm*QDcvvtkFc;SP1Y25#$aPL=JS_A2~vYu`g_6tG^F`~3?Tk=PUrU$A7+Iwf# zP3sP^_>;$7+`C#-qL5o(_k8&aOaHK$+*=~2HHLG<~h0q55ieQ6awVCENJJHSK< z4-hlO49Dh)=3#sL{@NsSIQ}`lEXSdqfmi45w?qc)KkL3>F}vWioRpToRdF$(wtj}~ zoY$)vJ+Y6o&XWNtn-yvXsjcpkgu+zA#5Eq+-;x5~;EK9PJa%s5aZV*YtuAEXW_Ghb z`vNpcqF?IkP(V0aeg>ND&i?u0H(0`++b7_+Csj+t2}YbmK@lKCL19J`Q`M~O9Bd(C zmc~wME=~|*yZ=s6i_`q(Om>}kzhB4dg6GmJ86w?y{lR-YT{`hr(tQL~R%EUA7>YQh zgav5LHcNw1v~r@6eO77Jy=ymx(K0>p@L0k5TkSY(a~z#@IE^?5sJGCC3A-x1udj(Y zby&JA*Ub3LICcwdE$+46I&e8%$8qz_HF6Ak3Hl54U}MXqXG$JtMZ**ZJ-hXGaX>dZ zev_O?@nliwuHL=28P83Bs@kAjd4v8HSv>F63-LD++pm+ZXwVy)uDQ~GG+I-LzZu$I z=0_CSvwbS&v-P$C-s#D2@;B=qp6B|CA9J3&B5RyM1ZV8YIRo4VBMmfR)3v04g>&|d zCrRYYnUa&*?ss6tdSXzRR+~U(U z0t|I<+*s4`I}%kq3v7M9Q&Hco<^HiGp}XO|yITX3Cf<*vg) z&0O?hQb>I4FWtiOM52x9Sx-eZBz{q5aOHm0H(yTU5MFb~;#j)1Wm%c<8;?qv$e4OF zk}c^{T(~5QR-a9q_;vM0x%P@~yJuE*I84<_aJxQz_@v!Z-~n5*dciFtZ`Bx?s8|QW zW9wVXW84FLb`0&QchUkbf4E$QADGBl)X~@^W063?cg~(Ui1&JwW7BAjNWfMpSBvQ6 z$e@XXl5@f3Qj0}Zr+0c;VasHf3)PYpWAM1uY3435i!xt$uDIb6(M@Hmb8*^aQhoR_ z4JiiLkl5-9Zll056`*W%#4U5#B`{>iMb~gf_{)ywmQyJqoH%+Lws+~E{TROC2 z`|F9cvfq2NDzmF9btg}LA}r#`N^w9)gyFa=1=Q$ONsD(%&h<;V3UeN(y5}zkT2VZ< z9g`8vnZ!&IcoA4YrS-?ah@#haVGdNeDBmm3LNE8sj5BSBcrZmvayQA^ z?aD!{C91&k7@xq+(6Bpx6%A_+S+>t{3=MVL=cLR^QTmHHt4TiSMd7L|A( z|L*tA>5SPc*VdgDhrJfEAC|i-o067u#1qxLdhlv0#4Wk8thaNxawnHF%TBOppHbdh z@P$BNP-Ml692A>Q^10R zd-bIC85aQ`#RK0nyYIL8>e0S@uJ%pvFj^wJ+`iv7X7`0OAaM71+a=wsAc2ebr$6ML zyktf!2=TD?NWIgVNxZ>}%N37xiX-p>iFS>@n;7w!+WP+VMJUg|$UkJ9QNN3~qNTfbT68D>w{$93P1Fle9Ro=6WTPmltKj)K+m&qP;jnV18^u=k-`#u?` z`YUC=U>ahF_DzFE>iA7bF_DNE-j8A@Dsjnf_|>F5xpjM=;>!%1ku>GO=>l^oMq_V- zF~jjt)3LLL!eSAgp<=mxHurLwxGv;IoEcH;lF;0?p^Y(7^IZA#Nt*Hou4Cyr$Tt;+ z>Gb(z>(%uDpS5kD)@54^bo=PH=XU1TRA_a?4k9|4i}NF8XTDjfTjErTv`~C$HM{Su z5T!#nB}g5oZ^vBTL-g3L-lsZ~q9o$0xZD-oPUj6pFLnBD{3vZU3x*;U$L_Cg75V|< zSGR7@a_a@RQ{zJtK|I- z#p1Ano%jS@;&72=xvp90HgD!<`?Y7i@9l9mH{AUTBDQ$0g+91ucS>5L?2hV&{uE|Y zRe{@a$&EEWm%9~q9?SYq1Z$i#6vgJJZ*+``A21rumn!hfmkdkcp1yP~Z}SDFcqF5C zpd;$nrkb!liexem4|@lS6U;r$Jf#s^n}P2N%2LqEmhFroGL`cQA7;7quy16PUa0Em zHNHE{S=>k(hA%m_WyC#nMmOa{TEM&F;z2RZuSKab8m?y^Uu5mxR;Kkmu&|%^99d-E zI92h%$%NHirIGfveA%D`ZXlVYEV%yiVtpr%YpxD+ZMv$nCpKJ|M>>x2`gSFF8A_P|07Y zB-IY-B+Lv9T30y(jbW5yc~>Y+^JL>hVuyn~{*_NVoo|X7S3fY2nYJl!?=btg$0@MV zM=G@^Oc=kS5Yizk%}KE}d-5a&f1iUj8(h{YT4TR17JgqeURek;pJ9BRjz_8CvkZE} zXn_~@Oa;?ck>pLb@zC}894W`MI=jasIN29N75%?*PMo$`#o*kT&}{hJxzph5|Fl3D zzkFVUdCSn9#qgfjbz+D$cc&axeB|N;|IK9Psx*U&10}woS9>o>y9B#NR3t?ydS%Y- z9~#xzXFpLH0_W+vprN3gM>4AUzSsJ{q09|c1?byrcsJfQIX+CfnQ@^9eNa`$VVH*Y zIThPD0a36RH9@OFQ6aBuzs3Ynli>s^fd;AyoI6D zDEO4`#!T{$pExaOK$&#G;SFz8PjhW3TEi=K#aQVbCoYYrH{ae6Nlmy*maMMComNyU zZQd)gikIf|?8`mpN^~fdX{NWVT!TsN=ZtpSXPD3X8flhSmucp+Uj*@MehzPX8bpvb zIm_{YkwO@v&-&5gt|ohOlL{B%<5`zoIstsb%`-KMk(r<9Zh6r}zPGzcuWqWnP5bP` zlCZiVuH+gccTTcPo9%RBFSEBIBgWEIDZl5wl0ADv!PGh0IuAd&vX5w%_*f_i?mu}| zVrT2LXG7pKT(4hb`&FxBP7(PVk9^GsK-s4dIMc1$y(%$cW>?AfcBska2QXCXW4yTV!A z9eLoby>5|5>~jio`Dsl7S{$}-_(`4P)`#4Ns2|6x?UtQKa(DF~7|z(zUbpJKu8u|d@)-PR7may`2nXDI z!3XZWU^vPz6fB%1oSdLeKaQqW|ENSJg||;KH6Z6rJ^zYG-pR^BTvInM`AjSeNGJ5I&=Tnp2g02@#LB!Tv@%R zrRHwtwNMLp3%Ado&)nL@pz>!B$!Ijv!lCuMkj4{1MzeNlxEs>X3whsc^++(?Gw zm1v@fEryD55RZJ7bzex7mP`b4+3j4iu(Iguu12vZR299*ATE{{(IpT$ zFVV`Fv3w}~D~iU&ULas;q(YCY21IEGDcRid=)+d$4x z+~lu)KRn1~hdEGy*Hn6!*^N$6GCU1>L#=_0#h72TqCZ}_R5?ae0lP#|qg?(a)jYxG zN}}>Qs-Z+Sb4 zLN3?DSG~A){6TC_Q|(>%RZ7;hrl(ZFXHi94NM6Kg`=4~ae}-X4ui;8L<2YI;)|Nn{ z_{j4NYXwt=l9%3>N-W;HFsS+On7-9{{(h++mog!nBDh+QXHe;NF>_bx5N`5tZ>jN< zInw>|l(u`&#ic~eMB`7l^l9@k`=-)N#h)}@m)A+YveA{(=&1kMlOH&^`D2B1pCy#%ew8@>@F{8KUy8*$j&_T;9X zC~haTzjSJNDZ8)Buv;dhc6y|f^Nq9U=##P((cAk*XZF!`uZSD=gNt`;>$kYcW zk~hOiUr0}#^fN2QOWeq%uneN1-NzSBzNFYGG^URGd3nLE&8q>HW<1BE122E{ofGRr)4aLRFfg>DT}e4{@h0te>pBA)HJe8ZNa*3$EC}XA}1e^k}4=G=vW*HMb7VCW4NJ9&|K+oOkbR z>SX2M0z0%{?fY*M_7+z5ke^5QhpXz#k%bg^L?VuYdE#oS!2;%!R_3=`}NzmV|7fY zG?kkc%m!KNo8p7LFprli@W}I=#o}Hr@d;Q;JJk|#W?jyLSID^*U7+_(340|@vn5Sq zKW5`N7lRAhoKzRbr;oka`7NrMceYg9XVDs^uEb1a<_(>}kyMIA7gGp6|Hx!oQZ?5X zi}tym=mR%zZMnEJECNy$`Fcu$s^P++mg!RTquTH5pZgPNvQ{^QU|@UWY}^X{B299F z=4*}8R+mF?KNA}1GhbDjSx-S6i8hB6i4Skp482TvPMlEtXqtWX1f^Mai&3RBlb`8n z_OD@ARIeCfoDWVNQuNLBck?8izn}cNpy@vMw+lo2MN@aY9cdcagv4S}AkS50Do^*w zYSNv&LDHY?w?K4>sr#+Y9Qnu{*9d6T0{IB_0d_lwvgCB|ht#lhktN=wAFuGWy|_Yj zGpm@KSJjF5QgvFktTg_*vFc_&2j!tIgIf&kjVQRK#07L4|7zhMmqvxFk3)Nv@eYKH zV&j-8$cDgGAM)7pRcVTR^yeixsGo8=wnyK1mRT6RCTm&0r=4_JS}*P8CXzxWl@iB)9^S^Pao0$pLiD8lv6cX@W5RAreoFwI;cIHZN z!wxqfz#=H6o5jHvdiz=jM^5tXVq&GuT7ZG0!bf&aaX+=zZhLOqa|Tb+s`QJVZs|yj zlnE$a=?Q=C$ezrr*?x;b|Ur(<~kOIAl--Kt0UH{W(v z(YHGGgWMI>#p&o%^NEnM<`xTS^@?e)+D0W#ingKFM9Vdx6^mT$zQxs~ z2%CW|Zmi9M{M5T>##>1_!ct5{6300hFLf<-6~yyu7`aoLH`|m*OyO(Ul;{UcxsJ7v zkCM{ah(mfxRBlly-GV-FSyt`3&-~s6&-xMX$M-=@GM!aX%x8{h{Ai1PWUM_Svq zde;Oht}U9~Zq68%s_qFCO^+l)8{QS+L^htZ)Rn0@$;q)%>^|w4Wa}6H7x>r z{J~zVUTaoX84?`jl1s(SB$f*P%DAFdxo((pS|_XSk5Fyj?322&z*oEDe^%I7Dw@Xh zNyPbwjxD#^y}IaQv*@@vinfN=cSfAMgtqS9+W)r4cH4fJ=-L%U3`bJ-6}GHYzLU@> z{=6}H6s)e}ZvxL~`$QzHi}Y>`7^C>PmfsF_^}uvAU}N$~Y!9xys~;cXeP-}^D&Wgv6Ri%bejGG zU7>tsl?b=p{pXEVjXV#FP;aE^d#VSs2-1%&m1Vj3X2q5iRA-Wwu$eytHzTRdQuD6y zlZaqtQ=ef&J5`RxJkJUkOpi-QXO%L*MrOT8~poeJ{ z$BRz%B%xQcwXArmrgCLDfj|~<#szaD=}r?x8b42&@PWs5u>}RGW30g}wiprOr$Py! zrZTCZQnRytS^h{)PpV8`yI6|_|E7LDM#LOl3%2x3*;wRUHjL`bnL zG3kw(Grw-Pq6+Psleb6*ZV1PTpa$68SHur)xwwRRnP>*JU!Xts+p`hw<62koC?B6s zaof>H7qpzhl&+Gbbh{>o)-5@41CIwSz1R)k-Phyv8!d7Dz#t-J!a1!#hCT)T zw`pJ2fBuH{>h27$bqt}w#wpbHDf*oYV-vBMJC6}z zsq=cWhyD3EzK|xN!rZ3y0V%_7v0a%Lk_N0c^H<5cCS}Z1bVMfUBjkHF=TIY_r{5&B z>!i3iww+WNH%OExlD>2|@y_;n_;FPD@hc<-pqJeN;Z5*gLmSl2!O9k5_TS)22CPy1 zoUPd@5sKj5EY;)pCf5>)B~ixjvB4%+&y&TE%}Sy_d7h5$=5VQvkl<$0XvxG&Rlf_? z6W~gmvlhDNGRb9%+Lt;P1=kDLhxhl_C(qozR2@{`RP3wL8D>OMhNB8yxX+E(EE;w- z^!W1lO&k(cS=n5_u!sv37jYWvy;}{nAX>w#=PnJ|t%+5+#+K~KHatlQ`pIRHiEA4>19=&)zMD`vZ zXFx9fgx0$k<}{%v=;I&Q)T@3~gVc~Xb31=l>ToD8uZ&=SZ|`!;FZGUv?aH0ozg;Fep% z&w-FBAsWi%kSfYFAEF*OTS!J8)+{ z^Vm?z*URtJzx8opBlqyJE6m!%fcIOug@o!Y zF#fLuMfmRg^%qi7bGQ3aBD+VkN~ab7Iab*f@5<40R(TquA1n1+hxSZ>Jzg@=8Q>-nz+ zt&z*vjO^crP!lZ_-0tp@7PaS6v9V*b6j#29s2bRE8}ZxowjYkTV=z&=Gy3VW&D|>^ zv+H4tI(T3&itjtwoM2&X^+zYO7e*qw@$hMKW#h!dS{6z_%H6RiUC5qyK&LX|ZS0Bc z->Sa6Y3e(30PY?Znwl-ynqFRy%h;%)i7v~fPeHFGETRh4K8gE0!%%K` zfkH|3yIMx zboK80QG>@iqH7B@gL>#kyLdoAVk*>sJhgZZ+~d3G9!Qc8b}AOq#Y_Z&5s{SCVmh;FcAu%F|cbS4ws;n-VX3 z+iD&kaHw?Bs-p=JJ~YobJ#O>79;Br(z(Oq3zj@M+b=d2{x?}_R2SRv@h0i!o+Tv_e zVZMN1;*AZKyqF{n3X8krP*30Nn#0z6M)n;# z>P>+dKH?1|f-M+VUj;_4j!*h{JUspA-inN1{X5}ykZxWjO8L~tje7M$+KHJ8?MI&) zEzo^5@0@-_xax^%Sa;@v52oR##_Q)+Gpx?Lmy*HlKxj=7RQ*Ya$fNSGuo zZ47k;G(^%OLP6mXqkP+&*(PbT-Knc=VS-uZMaM_(QDqqM03yVw)<>Z*nmbcHiwRX)VGjh|ODnP-PQHSlxaX1*BT7SM2E z*x(e)%K+8NlQoTH&l4={rv2UDOg^vPg`DL4HqMQsSzU%foGEiB!;hFv9)c+o+}!6< zY2jdWd%Ph3OEACam)?-@3(0Ym=^l((+Da-dOw}qaR>MqV-dwej=Q&&wD1}A%6<8gU za42Ms3CE@xYX=;|8s(MC{zx)EQ`^QEYV9I%srQTW9P`rB`Pdgh+&B;P($J~p&g#f% zYAn#j(zb11s8nGK9oV#-NUhB*9u(>m?s*xQmWlqHH1uLIc9attN!z>1Liuk6x*eH| zUjqnRv&3l2{Apu94z8sY`PrSg_iaUrD?MmkWV-QA7||$=DTW2c?)~m+7E?@j%x%oA zCM5{nO3`kj>`3ys{ z-Cf1H&yd|?x6H~b&Q1I2O+P~4)ow9#coOz<0;(Z<%CY@r%uolrSsO>Rx@}oyO}S5e z!s_YWw-uzD7ca7?ykNTJ{W$TiIq{05foA1v?f@_Mvanm@AG!7$H@0&*%J1RY=b(1> z=%olTC2Dk1N4$n8=_k%qm}Q@{h%cqa`IbZAG^bW6hhEa;b8l2}WwY2zPp#8G<3(pd zR2jWvb5NvByQhS6p^GPxlEVU1o{OepF_CwfAiwU-1GyzLQY~TcDvb(-=Mr~~Z@Id5 zD?ntRg_ImR`sM~|O}Sn-n{qtOEPN7fF^z3r8 zv7Jk#`4`e#wl3AIas7;9^u3&{iCv^Q??#i;KXJQBhL336Uv#RtY`RHfWuIRl&crYA zEnb$AFWS6UFhO-GD~CDqx^kWV;QRzffPg(ew9Rv&UKs7WOx? z@H`$};P`yfrB{#jP1c=jP!fH6f)^WfrIj*G6v3|}q@b9-l0~u^s+miwqqE% zGTeiG%1hXIA$Zg2b=1}6;pKBU-aB5QyTkl?0|VoZ^aAt!^N$0%FhBD4&QK3dKqD+1 z#WL7?yfOItCnBoz38!qx2B%3Y-vlUb9)CWTbxzOWb{`FYog3=fI-e6+6${!r)x01@ z4@qxxNjo{wd+Wrck1;#yC*Dbh%yy8QoDy=$wC`F-JM~(m7;idA;6P%rlU)tEz~W7z zJHO{E_dfAsop_5j)U8RV+xWVH7lwPjb4_W!D?>?0MBT+~ziVGc$$gynQFNP^+YRy` z=}S`eCP;jqd@qvmnPw+Yh#!4smm)<22WLR#{Rt-JV&0}RoA0snnOMY~-t$T2=Ib}_ z=QeKi+wQ%Sx%!}y!}C+>mNH3M&#p0z_V6o5yf;BqH8VA4)10AB`#c|7Jr$p{&A;vU z-0bleytYnAlAIp(Hr<&w^m1TXrAP9IQ~0Z;qNgG&0PI{R;Mb4v;i9b%8p0{+Rvz zxS!piu$@g#r?-a)O*LDZjDU(5pOuPL!rDgc+MOOPyAgUhEu07CAE>r9ay1Sl*u5t6 zN|SQP`A0n?ZZ$aXQqOmqi=mdX`CA8tXk!>Yk4^BfUz1*wZKfGD zu?cSG3MFIdWf|3!8CG9W#I9UrV;E6&(5?5z;yLTCj$S}T`bv4yD9A@Ui&wrX%w5dRvWvqndL9-`^+Ur6shaNHQQsxkCgvvm> z7ruG!y+7+5$(Aekf+f05;)eJxdeV(o5^0b^*(Y(G=o^eS{AI2MT}4Cw*qt^c$81Lk zE|c-Mfm3{jlP?K1h7Xm$u+Jwce5-Ty5m?x=QycU0`{I{!yliAe`TmOD2e$a7*t`!r zmG*-N-QW=1>11tx@+E~ay{T-4ufy{n{jMc|GZ`OYQ|yS-f7YuxKY4$JHe#LY>gFV& z&wOi#N3&9l*JvcREpE}JmVWY2b41CNV(-AeWlOCV<@2rjdPK9fcrR;Is;YWYEJtf} zXoh-+ZnRuKU-NUJC8&9^_l(GRsLnnAkLl0l?iMT!`_@nqc@`N@m3f%opgT5 zj(7D-Il33NCR+--jm>KK#`rlpmHv5^n?C;eR*ai()4+W;NqN*#PkFXVB)Eo@r4-dY+@L{evZ_Le)GB;8*X7PIaf zSzbsn@vRk#d`t1-c;j-~lXf!JKE*~UvUjha)s003G}I{M@HmJI3S-}Km&`h#t=x(! z{pP`=X}YyF7qTPY<86lAo$7{MrttVwjAv6`2UvkO}caoB(N@0>=<> zj3r{hBEfR*`Hiq0(b{`k)Lx>sCoD1Lj*0pwH1-;`@pYztySln0d@CT+=tO>lDn|09 z_<<;gs;vr^M*EJjqQ2(2Ar-spw1S}-51fKeddozX-?cEk5|g6BMCU5hGyy<;3o22^h210NB zn)QI0P9c*t2ynkX1mHIX33U-x8AVBUaND(;6}aG-{daVP{rxFS-Wk}|f7n)4E`)z? zZR}?3!S-J^ob7+t-F`&L4tCjr4km@p-isZVdM_%ny<%Z}v(BV|bG%4zy_b7kb%Y>B zZY`7<$axHv2n_^busOElrYW4Hm?$7XfB)d2EQ!E=`6c)ME7+CTKOa4b@(Mi48%-&u z1OCVYe2HLx{o|A23tLe7^{9e~qKu@3nmU_;5TM}3=%bzh z%LP9^uqQtJc;fpV)BpPzOw^x$2>S_+`~C6xUQ3YWfED!XYU=-e^stQhKcDS5`(xi# zMkizM;OZg?lD~*4DOWh2Qh`!+K;ft0C~v@jg2KO35I@VB8xs8toOXR4lm}Y>uTO?A z1rP{4Yl`?eMXI2j1YqN6ApP%_1Cx9eoc{UUP(N4x4_ErQi!Y@sc+3e@`nTV~9xbB! z`RHG2{Fr{pH5Z5*53Gg#OJ*2Cm-YwZPqDwZ+GQK5K2Yu=P}fi_bql8NLGChcNO`aCyCpu?vJw-ql#_M^i>DoLuN|^BSm5 z>KPOi@}EfXGs9Pv2N@MHDXWrn!4}8{Q}a1E(#>mskW4j=oqjBp9-&X@vD7GDs5;o3LQkSG*t3o-ujCfi|go|jxD zCV%-pz@)ra$8)YSx0>w}Rr^kkoB zfVxS7Y$h38{eq1DB>m4eyTi3}OLlFC1#V&h18wNnC&L#4`4c4RYH#}coxj5@G>Q9r zv%qk@pnIUtfb&=!1?QMLaQrD*kIS?VwbLs3d| z9@GvOywM1+@W+k_Fs^nc$QqvnRo#`RAk-Z&A11Xr|49Px@PMrVh?~jR4e^Qv;M&K) zrdfE?<@oJL!r=0I~$H6`9eA8Qa=|$Y5%NSU3lL zW%;u}S=k`Y(ZDgO5|A>#M;gRD6IR^2w}B1sf`KQz0X!cf;~^&bORu>lfFSA*Vimlj za%cWY(g0&yGh-J7Js_<0TyLxHZvk#$1~dn|ZQ{CIO@whWK>0{ zJ(4IyPd+;+0chHQ#sEi?&qqd6Hnws)Qp7A`w)^-X>gOvS_UiruBv8b59tfU4n+~L^ z248A8>8Lsmfs~vaERF3UX6oNv8!-+Wx8WN1X%rMA5Rl*pJI6W?;gms}bwNydmUp0_ z1=J-E91z}(t%v@gKwY3No(@Qqzs1qUy9bmX1xPe-)!Q98L{c}lvNZ+G^+>&&Nkyr_ zTtgB_2jA)Pj~(J^IDGeH#5F{bi@#(EIClZ(0-RiR|K6l{|>kLz2+0W7C^Q_U{WSH)fuiF$viqp5fgsiHv!lJfQ1(ocl}80 z5mqi`PiWKx;awdBQFuQt+CaucY?RvFJH9HwC~QDNc#_z+LnPQtRMZxVtjl@MG)F!M z)aC(b@T9I?1SBy_S9>I#*Yyfqy5oS-0KV`VTiruIlJIb#6S0Td!v;0t5Oc)!+?>+m zp$0ruP)}Mo<6b#H!UP)up$-6!7-;h~ksSp93&9s2m<;|m+#m_2IGB(>@B2XveEj@_ zgFS%N{vqM$F(g1qD~PQbatZgvRP+Gw`5(Y=G-N=aLfFUxv4nc|D|jLR=<^4V83PGW z#@-C#fmFgPMK3dN0U!ow$?(DI8L&S>9V$RvETLw|WrPsRufvdqKt>ukJKLW`f>boN zgCG@AN17-06yPm@FC83@6$=Ru3@#w{&Pa*l_Y7!W0um`8!dLnRHZr1JMLHf_kvs=te+}N@K8YD90ud6iOFvY**D?#l;sL=K_VU}$Plm4#2?7o* z#E2jrGo1#>+lo#d7bYYcD% z6j+`UeulCMa>#!;+jsF`9tR7Zu>U~pDCuJDAyj~h2dMD&)nq-2inQO=GcuZojcfG) z5WX)jV?zd%g4jcxtV|_;zEXI&X@t(d)OG^Q)<2lC9LSh5=IWLZdkI@-BrT-e_&y)3 z;$z?oKbb<|LdKMbf?@qpCU=N5kCOpF%|C1e;XV?2=<+jT(V0{7UJ@{b;78uCD3HEDMOx)GZ;fSaw=W`^dWIb0ARtG@Zr(i9T`s^;_;u!I1$%9 z!XaMmG^lq4_`)_C{rqJ3a(Mie32UI>>*54OGOxmM6gzPYkjudr-V?$-|4NsaRx>m{ zV%VWF8v{#;pnwhsh4rW0;Ae*Kkk?<~Ae9DnvT{K(L>-upo&xg$lt%DnfkP95K^S5W z{-tR(h@FhRIg-Gv!X76Z2B=FQ#=!fU^^L!h|L3rZ!}0afUbZ+aM*$#*?06MS8vi0O z#KQsB;OI2y)DU}#jf08cFd*-OKnou&TyOt79Wgt**l`**swKuatn1`E|H?*8*0{yY z(*wj^Gd?`S74`oc88J~@)q5fZjOXh?Af|%z3-w~8M6ka3Ck?i~PS-7?~B&|duH5WkqsN3e)a<*M}U0}@Lgqd2XZ=MNk8d+d=>;e z=_ObmqJ^{2-FFCBVo)cjs|$D^A1D?vFiAjP#}|Oo!Iv5ir~vv-xP}EYk~qY~)dFTE z1o0MTo?~2T*V@6Xa2C{;2@Zz~8W?iicP`?v0>e7YM#hGMYO~@V4l5Mnf5jphCcwBZ zGkd-FfXRjt%~Y-r zRA~rQ32*9r45Ya4P$XXN_3d0a4rtkrK<5gd=T*Q$21Hy_O98``WKdIKP*WN>E60!_ zAc1sX2no207oGK zLSBF~jTI{bmXbXLq{WW5j+)+__zD=FGXvj&_nURF`0$5cD>(z(AQmoAC<;punB)p@ zYxw9uaTx(g8LX0nOM+phR6sIRF|B2O5PR#$8o85-bJUq^YHd zs|R8oux9mLiv_~+gB@V-0{g2S$^DK!B9PZvu{o*%f$4#F!Gle}n*ATP`mKpyzajCh zc;W=ddjNdz5AeR>zk!i>SB^>+Dh5b`2T>g!YYiA51xBn`FTL;xSXRvocmsSBIOl|b z_C5aqbA+G2AQ5tk4@2k$@BwWQ?%-1fj9`=5A8P$cLoDO?VoIVlP^BRN!pBY$Ped@V zso?LysU!Ug6>QmD2|(dnRkIf&s5|tp@vim4-A!tsOLL%0c%%bZK>MT8AW!mFWDA2o z#u*^xTY!b1+VD2kKa%+nlRwaLtEYjk<_q|OO|QQ`8NPNQ|49Dsg}?4CI6PY#t!=<41>=KB&`rR1 zJ%*wGRsdqb!;PmGOhJ(70<+P}zr=>6Q}jV>Kf*ykLs5sq+RT4D(2kZKJD+hj6)1fT zI19+&{rZ6IXR-fS3T!Xz(S;bjqpK_cXlhUpybZA9|FMvx3wTDng&PQL5CBGf0>A12 z(-ls_KNj#~-QwtSvh<R)I~HK=%S>V81>Yz6%fju^c56Ylx}K(ZyI2n3rRNViZ6? zhcAXZ^&gA*Z(F9nVWzn0VIVd*5@5T6te~SO2otgbT{!a;EvQlPI#B}Ek23}GOXY8 z%upvfC9u?N3%1Q8E?}Q(M!g!q^A}$AC#0<9>Im> z$Bpex5v)nVhR?5riRQlo=#xK25SBGZKouZ}w?D&>%zI_Rp8+xym<>KfnNfEn61MB+ zFS-p@izOrgq7vd99`Jl@{3{!=T9@-NBOt&Z&H<4xz?qAu9U0OY@+0+!7|Cz`;fX&$ z<$y0da`+W;?((bcpyH-rmIvPfXLS4x2}|7kK91>dFXnvHM*tH*-B$}vdGz*9Az5@NnAw28* z{~J7#abNGtf!0xgjs?nwx81i7f5jtK2!@wnx+GA>dw`^cQwaG8a^w-o2{*b1^J759 zQ^0KWaKOi7$brhX#xCYyHjP+Fp5P9i3xN3&2nruvW+#qdIzhopq0Y#L=f^dK*02DO z9Q2y-%2b{HD-^Mua{AU86fh)+F7R?bnni*H!y?#=eXvO+5}$H?Xt&n_WLyTjzv1OP zw)j^lVmV)6n{}-MH>CnbzXoR`tS^U=Ki@or^@U>K94fFmh3@rJBs_ zL~>9X^pDcc9{hilhGY&!sgy8X2<#RFdypfsAc15}#>miy@7H1SsWZ%o8eMjmHLWCyPJ0es;rep=>FB6#r_3`(p_zwZb^ zCS=G}s2V-M)&GI?mHitMNiZNNfBn)A;PQbNz)LwV_ctVx7SDQoSRWN2VN2-nBZvZp zzad4Pz+l(%NQdfgeayrMEKdstk)ZAU`egVX1G%}w;R{Z$hz-@QN3MlUje_E!a@h2q zAkmKi2=gORS1Yi&#tAWzo+qOw5cs?U$Uam35)d|#YH>qK1la=aqnvrvcmMgq&A%YRmBgaKvu#h3BOtBjkZBD~yJ$ z3G%ak3aJO;o%n-?_UK3+lJ>W0v!NvjqAx5n0l%Jro_Zut+0yEVsEEBLh=y4n%m7dt zfHJAz3=<4qCr04aN75n*8+z^l%Aa$h`%ezhejI`Td zYp$RDH>9jAY?CsQ6hSoaYS|J1gIzBuJa9F?_w;XIc_`Gz*b=-xtLAD78yX|lZNSqR zL27Cglo;c~EwVf3FC`!bPCcaF`T}Cw&L8tb&d$F8f4(w=L{!?Um52MFk@G1Y-Z=(+ z`xo-}T~Z3h_F!ccNt`=;h3rpdXZTjGA%=f%I4A_Pvj07m z2U%M?eC@(-Fgr*dz*QXy7)kg#e2D&Ua3%J?fe{_4e^@Vv&$IqrN*vxlmV)GT>%%1- zK7sgmNeYDjR?;8m5g#t%@X@rti%1~;ry>xCki#e4{l-3`_$Msfxp%*XMtri=e{|R( zIN>ztzYksdpL3>uAKHZIq^aN1)gXM{8Vs?HI(JH04g-Ws6qFh8kFqS7ywHL^6y^T_ DZn1=+ literal 0 HcmV?d00001 diff --git a/luaj-2.0.3/.classpath b/luaj-2.0.3/.classpath new file mode 100644 index 0000000000..eded28b8ce --- /dev/null +++ b/luaj-2.0.3/.classpath @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/luaj-2.0.3/.project b/luaj-2.0.3/.project new file mode 100644 index 0000000000..15180d1141 --- /dev/null +++ b/luaj-2.0.3/.project @@ -0,0 +1,17 @@ + + + luaj-vm + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/luaj-2.0.3/LICENSE.txt b/luaj-2.0.3/LICENSE.txt new file mode 100644 index 0000000000..2cc1808644 --- /dev/null +++ b/luaj-2.0.3/LICENSE.txt @@ -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. \ No newline at end of file diff --git a/luaj-2.0.3/README.html b/luaj-2.0.3/README.html new file mode 100644 index 0000000000..c635954d6f --- /dev/null +++ b/luaj-2.0.3/README.html @@ -0,0 +1,780 @@ + + + + +Getting Started with LuaJ + + + + + + +


+

+ + +Getting Started with LuaJ + +

+James Roseborough, Ian Farmer, Version 2.0.3 +

+ +Copyright © 2009-2012 Luaj.org. +Freely available under the terms of the +Luaj license. + +


+

+ +introduction +· +examples +· +concepts +· +libraries +· +luaj api +· +parser +· +building +· +downloads +· +release notes + + +

+ +

1 - Introduction

+

Goals of Luaj

+Luaj is a lua interpreter based on the 5.1.x version of lua with the following goals in mind: +
    +
  • Java-centric implementation of lua vm built to leverage standard Java features. +
  • Lightweight, high performance execution of lua. +
  • Multi-platform to be able to run on JME, JSE, or JEE environments. +
  • Complete set of libraries and tools for integration into real-world projects. +
  • Dependable due to sufficient unit testing of vm and library features. +
+ +

Differences with 1.0

+In addition to the basic goals of luaj, version 2.0 is aimed +at improving on the 1.0 vm in the following aspects. +
    +
  • Support for compiling lua source code into Java source code. +
  • Support for compiling lua bytecode directly into Java bytecode. +
  • Improved performance of of lua bytecode processing. +
  • Stackless vm design centered around dynamically typed objects. +
  • More alignment with C API (see names.csv for details) +
  • Improved class and package naming conventions. +
  • Improved unit tests of core classes. +
  • Improved quality due to major redesign and rewrite of core elements. +
  • More complete implementation including weak keys and values, and all metatags. +
+ +

Performance

+Good performance is a major goal of luaj. +The following table provides measured execution times on a subset of benchmarks from +the computer language benchmarks game +in comparison with the standard C distribution. +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ProjectVersionMode  Benchmark execution time (sec)  LanguageSample command
binarytrees 15fannkuch 10nbody 1e6nsieve 9
luaj2.0-b (luajc)2.9805.07316.79411.274Javajava -cp luaj-jse-2.0.3.jar;bcel-5.2.jar lua -b fannkuch.lua 10
-j (lua2java)4.4635.88416.70113.789java -cp luaj-jse-2.0.3.jar lua -j fannkuch.lua 10
-n (interpreted)12.83823.29036.89415.163java -cp luaj-jse-2.0.3.jar lua -n fannkuch.lua 10
lua5.1.417.63716.04415.2015.477Clua fannkuch.lua 10
jill1.0.144.51254.63072.17220.779Java
kahlua1.0jse22.96363.27768.22321.529Java
mochalua1.050.45770.36882.86841.262Java
+ +Luaj in interpreted mode performs well for the benchmarks, and even better when source-to-source (lua2java) +or bytecode-to-bytecode (luajc) compilers are used, +and actually executes faster than C-based lua in some cases. +It is also faster than Java-lua implementations Jill, Kahlua, and Mochalua for all benchmarks tested. + +

2 - Simple Examples

+ +

Run a lua script in Java SE

+ +

+From the main distribution directory line type: + +

+	java -cp lib/luaj-jse-2.0.3.jar lua examples/lua/hello.lua
+
+ +

+You should see the following output: +

+	hello, world
+
+ +To see how luaj can be used to acccess most Java API's including swing, try: + +
+	java -cp lib/luaj-jse-2.0.3.jar lua examples/lua/swingapp.lua
+
+ +

Compile lua source to lua bytecode

+ +

+From the main distribution directory line type: + +

+	java -cp lib/luaj-jse-2.0.3.jar luac examples/lua/hello.lua
+	java -cp lib/luaj-jse-2.0.3.jar lua luac.out
+
+ +

+The compiled output "luac.out" is lua bytecode and should run and produce the same result. + +

Compile lua source to java source

+ +

+Luaj can compile to lua source code to Java source code: + +

+	java -cp lib/luaj-jse-2.0.3.jar lua2java -s examples/lua -d . hello.lua
+	javac -cp lib/luaj-jse-2.0.3.jar hello.java
+	java -cp "lib/luaj-jse-2.0.3.jar;." lua -l hello
+
+ +

+The output hello.java is Java source, that implements the logic in hello.lua directly. +Once hello.java is compiled into hello.class it can be required and used in place of the original lua script, but with better performance. +There are no additional dependencies for compiling or running source-to-source compiled lua. + +

+Lua scripts can also be run directly in this mode without precompiling using the lua command with the -j option when run in JDK 1.5 or higher: +

+	java -cp lib/luaj-jse-2.0.3.jar lua -j examples/lua/hello.lua
+
+ +

Compile lua bytecode to java bytecode

+ +

+Luaj can compile lua sources or binaries directly to java bytecode if the bcel library is on the class path. From the main distribution directory line type: + +

+	ant bcel-lib
+	java -cp "lib/luaj-jse-2.0.3.jar;lib/bcel-5.2.jar" luajc -s examples/lua -d . hello.lua
+	java -cp "lib/luaj-jse-2.0.3.jar;." lua -l hello
+
+ +

+The output hello.class is Java bytecode, should run and produce the same result. +There is no runtime dependency on the bcel library, +but the compiled classes must be in the class path at runtime, unless runtime jit-compiling via luajc and bcel are desired (see later sections). + +

+Lua scripts can also be run directly in this mode without precompiling using the lua command with the -b option and providing the bcel library in the class path: +

+	java -cp "lib/luaj-jse-2.0.3.jar;lib/bcel-5.2.jar" lua -b examples/lua/hello.lua
+
+ + +

Run a script in a Java Application

+ +

+The following pattern is used within Java SE + +

+	import org.luaj.vm2.*;
+	import org.luaj.vm2.lib.jse.*;
+
+	String script = "examples/lua/hello.lua";
+	LuaValue _G = JsePlatform.standardGlobals();
+	_G.get("dofile").call( LuaValue.valueOf(script) );
+
+ +

+A simple example may be found in +

+	examples/jse/SampleJseMain.java
+
+ +

+You must include the library lib/luaj-jse-2.0.3.jar in your class path. + +

Run a script in a MIDlet

+ +

+The for MIDlets the JmePlatform is used instead: + +

+	import org.luaj.vm2.*;
+	import org.luaj.vm2.lib.jme.*;
+
+	String script = "examples/lua/hello.lua";
+	LuaValue _G = JmePlatform.standardGlobals();
+	_G.get("dofile").call( LuaValue.valueOf(script) );
+
+ +

+The file must be a resource within within the midlet jar for dofile() to find it. +Any files included via require() must also be part of the midlet resources. + +

+A simple example may be found in +

+	examples/jme/SampleMIDlet.java
+
+ +

+You must include the library lib/luaj-jme-2.0.3.jar in your midlet jar. + +

+An ant script to build and run the midlet is in +

+	build-midlet.xml
+
+ +

+You must install the wireless toolkit and define WTK_HOME for this script to work. + +

Run a script using JSR-223 Dynamic Scripting

+ +

+The standard use of JSR-223 scripting engines may be used: + +

+	ScriptEngineManager mgr = new ScriptEngineManager();
+	ScriptEngine e = mgr.getEngineByExtension(".lua");
+	e.put("x", 25);
+	e.eval("y = math.sqrt(x)");
+	System.out.println( "y="+e.get("y") );
+
+ +

+All standard aspects of script engines including compiled statements should be supported. + +

+You must include the library lib/luaj-jse-2.0.3.jar in your class path. + +

+A working example may be found in +

+	examples/jse/ScriptEngineSample.java
+
+ +To compile and run it using Java 1.6 or higher: + +
+	javac examples/jse/ScriptEngineSample.java
+	java -cp "lib/luaj-jse-2.0.3.jar;examples/jse" ScriptEngineSample
+
+ +

Excluding the lua bytecode compiler

+ +By default, the compiler is included whenever standardGlobals() or debugGlobals() are called. +Without a compiler, files can still be executed, but they must be compiled elsewhere beforehand. +The "luac" utility is provided in the jse jar for this purpose, or a standard lua compiler can be used. + +

+To exclude the lua-to-lua-bytecode compiler, do not call +standardGlobals() or debugGlobals() +but instead initialize globals with including only those libraries +that are needed and omitting the line: +

+	org.luaj.vm2.compiler.LuaC.install();
+
+ + +

Including the Lua2Java lua-source-to-Java-source compiler

+ +

+To compile from lua sources to Java sources for all lua loaded at runtime, +install the Lua2Java compiler after globals have been created using: + +

+	org.luaj.vm2.jse.lua2java.Lua2Java.install();
+
+ +This uses the system Java compiler to compile from Java source to Java bytecode, +and cannot compile lua binary files containing lua bytecode at runtime. + +

Including the LuaJC lua-bytecode-to-Java-bytecode compiler

+ +

+To compile from lua to Java bytecode for all lua loaded at runtime, +install the LuaJC compiler after globals have been created using: + +

+	org.luaj.vm2.jse.luajc.LuaJC.install();
+
+ +

+This will compile all lua bytecode into Java bytecode, regardless of if they are loaded as +lua source or lua binary files. + +

+The requires bcel to be on the class path, and the ClassLoader of JSE or CDC. + +

3 - Concepts

+ +

Globals

+The old notion of platform has been replaced with creation of globals. +Two classes are provided to encapsulate common combinations of libraries. + +

JsePlatform

+ +This class can be used as a factory for globals in a typical Java SE application. +All standard libraries are included, as well as the luajava library. +The default search path is the current directory, +and the math operations include all those supported by Java SE. + +

JmePlatform

+ +This class can be used to set up the basic environment for a Java ME application. +The default search path is limited to the jar resources, +and the math operations are limited to those supported by Java ME. +All libraries are included except luajava, and the os, io, and math libraries are +limited to those functions that can be supported on that platform. + + +

4 - Libraries

+ +

Standard Libraries

+ +Libraries are coded to closely match the behavior specified in +See standard lua documentation for details on the library API's + +

+The following libraries are loaded by both JsePlatform.standardGlobals() and JmePlatform.standardGlobals(): +

	base
+	coroutine
+	io
+	math
+	os
+	package
+	string
+	table
+
+ +

+The JsePlatform.standardGlobals() globals also include: +

	luajava 
+
+ +

+The JsePlatform.debugGlobals() and JsePlatform.debugGlobals() functions produce globals that include: +

	debug
+
+ +

I/O Library

+The implementation of the io library differs by platform owing to platform limitations. + +

+The JmePlatform.standardGlobals() instantiated the io library io in +

+	src/jme/org/luaj/vm2/lib/jme/JmeIoLib.java
+
+ +The JsePlatform.standardGlobals() includes support for random access and is in +
+	src/jse/org/luaj/vm2/lib/jse/JseIoLib.java
+
+ +

OS Library

+The implementation of the os library also differs per platform. + +

+The basic os library implementation us used by JmePlatform and is in: +

+	src/core/org/luaj/lib/OsLib.java
+
+ +A richer version for use by JsePlatform is : +
+	src/jse/org/luaj/vm2/lib/jse/JseOsLib.java
+
+ +Time is a represented as number of milliseconds since the epoch, +and most time and date formatting, locales, and other features +are not implemented. + +

Coroutine Library

+The coroutine library is implemented using one JavaThread per coroutine. +This allows coroutine.yield() can be called from anywhere, +as with the yield-from-anywhere patch in C-based lua. + +

+Luaj uses WeakReferences and the OrphanedThread error to ensure that coroutines that are no longer referenced +are properly garbage collected. For thread safety, OrphanedThread should not be caught by Java code. +See LuaThread +and OrphanedThread +javadoc for details. + +

Debug Library

+The debug library is not included by default by +JmePlatform.standardGlobals() or JsePlatform.standardGlobsls() . + +The functions JmePlatform.debugGlobals() and JsePlatform.debugGlobsls() +create globals that contain the debug library in addition to the other standard libraries. + +To install dynamically from lua use java-class-based require:: +
+	require 'org.luaj.vm2.lib.DebugLib'
+
+ +The lua command line utility includes the debug library by default. + + +

The Luajava Library

+The JsePlatform.standardGlobals() includes the luajava library, which simplifies binding to Java classes and methods. +It is patterned after the original luajava project. + +

+The following lua script will open a swing frame on Java SE: +

+	jframe = luajava.bindClass( "javax.swing.JFrame" )
+	frame = luajava.newInstance( "javax.swing.JFrame", "Texts" );
+	frame:setDefaultCloseOperation(jframe.EXIT_ON_CLOSE)
+	frame:setSize(300,400)
+	frame:setVisible(true)
+
+ +

+See a longer sample in examples/lua/swingapp.lua for details, including a simple animation loop, rendering graphics, mouse and key handling, and image loading. +Or try running it using: +

+	java -cp lib/luaj-jse-2.0.3.jar lua examples/lua/swingapp.lua
+
+ +

+The Java ME platform does not include this library, and it cannot be made to work because of the lack of a reflection API in Java ME. + +

+The lua connand line tool includes luajava. + +

5 - LuaJ API

+ +

API Javadoc

+The javadoc for the main classes in the LuaJ API are on line at +
+	 http://luaj.sourceforge.net/api/2.0
+
+ +You can also build a local version from sources using +
+	 ant doc
+
+ +

LuaValue and Varargs

+All lua value manipulation is now organized around +LuaValue +which exposes the majority of interfaces used for lua computation. +
+	 org.luaj.vm2.LuaValue
+
+ +

Common Functions

+LuaValue exposes functions for each of the operations in LuaJ. +Some commonly used functions and constants include: +
+	call();               // invoke the function with no arguments
+	call(LuaValue arg1);  // call the function with 1 argument
+	invoke(Varargs arg);  // call the function with variable arguments, variable return values
+	get(int index);       // get a table entry using an integer key
+	get(LuaValue key);    // get a table entry using an arbitrary key, may be a LuaInteger
+	rawget(int index);    // raw get without metatable calls
+	valueOf(int i);       // return LuaValue corresponding to an integer
+	valueOf(String s);    // return LuaValue corresponding to a String
+	toint();              // return value as a Java int
+	tojstring();          // return value as a Java String
+	isnil();              // is the value nil
+	NIL;                  // the value nil
+	NONE;                 // a Varargs instance with no values	 
+
+ +

Varargs

+The interface Varargs provides an abstraction for +both a variable argument list and multiple return values. +For convenience, LuaValue implements Varargs so a single value can be supplied anywhere +variable arguments are expected. +
+	 org.luaj.vm2.Varargs
+
+ +

Common Functions

+Varargs exposes functions for accessing elements, and coercing them to specific types: +
+	narg();                 // return number of arguments
+	arg1();                 // return the first argument
+	arg(int n);             // return the nth argument
+	isnil(int n);           // true if the nth argument is nil
+	checktable(int n);      // return table or throw error
+	optlong(int n,long d);  // return n if a long, d if no argument, or error if not a long
+
+ +See the Varargs API for a complete list. + +

LibFunction

+The simplest way to implement a function is to choose a base class based on the number of arguments to the function. +LuaJ provides 5 base classes for this purpose, depending if the function has 0, 1, 2, 3 or variable arguments, +and if it provide multiple return values. +
+	 org.luaj.vm2.lib.ZeroArgFunction
+	 org.luaj.vm2.lib.OneArgFunction
+	 org.luaj.vm2.lib.TwoArgFunction
+	 org.luaj.vm2.lib.ThreeArgFunction
+	 org.luaj.vm2.lib.VarArgFunction
+
+ +Each of these functions has an abstract method that must be implemented, +and argument fixup is done automatically by the classes as each Java function is invoked. + +

+For example, to implement a "hello, world" function, we could supply: +

+	pubic class hello extends ZeroArgFunction {
+		public LuaValue call() {
+			env.get("print").call(valueOf("hello, world"));
+		}
+	}
+
+ +The value env is the environment of the function, and is normally supplied +by the instantiating object whenever default loading is used. + +

+Calling this function from lua could be done by: +

 
+	require( 'hello' )()
+
+ +while calling this function from Java would look like: +
 
+	new hello().call();
+
+ +Note that in both the lua and Java case, extra arguments will be ignored, and the function will be called. +Also, no virtual machine instance is necessary to call the function. +To allow for arguments, or return multiple values, extend one of the other base classes. + +

Closures

+Closures still exist in this framework, but are optional, and are only used to implement lua bytecode execution. + +

6 - Parser

+ +

Javacc Grammar

+A Javacc grammarwas developed to simplify the creation of Java-based parsers for the lua language. +The grammar is specified for javacc version 5.0 because that tool generates standalone +parsers that do not require a separate runtime. + +

+A plain undecorated grammer that can be used for validation is available in grammar/Lua51.jj +while a grammar that generates a typed parse tree is in grammar/LuaParser.jj + +

Creating a Parse Tree from Lua Source

+The default lu compiler does a single-pass compile of lua source to lua bytecode, so no explicit parse tree is produced. + +

+To simplify the creation of abstract syntax trees from lua sources, the LuaParser class is generated as part of the JME build. +To use it, provide an input stream, and invoke the root generator, which will return a Chunk if the file is valid, +or throw a ParseException if there is a syntax error. + +

+For example, to parse a file and print all variable names, use code like: +

+	try {
+		String file = "main.lua";
+		LuaParser parser = new LuaParser(new FileInputStream(file));
+		Chunk chunk = parser.Chunk();
+		chunk.accept( new Visitor() {
+			public void visit(Exp.NameExp exp) {
+				System.out.println("Name in use: "+exp.name.name);
+			}
+		} );
+	} catch ( ParseException e ) {
+		System.out.println("parse failed: " + e.getMessage() + "\n"
+			+ "Token Image: '" + e.currentToken.image + "'\n"
+			+ "Location: " + e.currentToken.beginLine + ":" + e.currentToken.beginColumn 
+			         + "-" + e.currentToken.endLine + "," + e.currentToken.endColumn);
+	}
+
+In luaj 2.0.3 error reporting was turned on in the parser so line numbers are avaiable for most parse exceptions. +This example may be found in +
+	examples/jse/SampleParser.java
+
+ +

+See the org.luaj.vm2.ast package javadoc for the API relating to the syntax tree that is produced. + +

7 - Building and Testing

+ +

Building the jars

+An ant file is included in the root directory which builds the libraries by default. + +

+Other targets exist for creating distribution file an measuring code coverage of unit tests. + +

Unit tests

+ +

+The main luaj JUnit tests are organized into a JUnit 3 suite: +

+	test/junit/org/luaj/vm2/AllTests.lua
+
+ +

+Unit test scripts can be found in these locations +

+	test/lua/*.lua
+	test/junit/org/luaj/vm2/compiler/lua5.1-tests.zip
+	test/junit/org/luaj/vm2/compiler/regressions.zip
+	test/junit/org/luaj/vm2/vm1/luajvm1-tests.zip
+
+ +

Code coverage

+ +

+A build script for running unit tests and producing code coverage statistics is in +

+	build-coverage.xml
+
+ +It relies on the cobertura code coverage library. + +

8 - Downloads

+ +

Downloads and Project Pages

+Downloads for all version available on SourceForge or LuaForge. +Sources are hosted on SourceForge and available via sourceforge.net +
+
+	SourceForge Luaj Project Page
+	SourceForge Luaj Download Area
+
+

+and LuaForge: +

+	LuaForge Luaj Project Page
+	LuaForge Luaj Project Area
+
+ +

9 - Release Notes

+ +

Main Changes by Version

+
+ + + +
  2.0
    +
  • Initial release of 2.0 version
  • +
  2.0.1
    +
  • Improve correctness of singleton construction related to static initialization
  • +
  • Fix nan-related error in constant folding logic that was failing on some JVMs
  • +
  • JSR-223 fixes: add META-INF/services entry in jse jar, improve bindings implementation
  • +
  2.0.2
    +
  • JSR-223 bindings change: non Java-primitives will now be passed as LuaValue
  • +
  • JSR-223 enhancement: allow both ".lua" and "lua" as extensions in getScriptEngine()
  • +
  • JSR-223 fix: use system class loader to support using luaj as JRE extension
  • +
  • Improve selection logic when binding to overloaded functions using luajava
  • +
  • Enhance javadoc, put it in distribution and on line
  • +
  • Major refactor of luajava type coercion logic, improve method selection.
  • +
  • Add lib/luaj-sources-2.0.2.jar for easier integration into an IDE such as Netbeans
  • +
  2.0.3
    +
  • Improve coroutine state logic including let unreferenced coroutines be garbage collected
  • +
  • Fix lua command vararg values passed into main script to match what is in global arg table
  • +
  • Add arithmetic metatag processing when left hand side is a number and right hand side has metatable
  • +
  • Fix load(func) when mutiple string fragments are supplied by calls to func
  • +
  • Allow access to public members of private inner classes where possible
  • +
  • Turn on error reporting in LuaParser so line numbers ar available in ParseException
  • +
  • Improve compatibility of table.remove()
  • +
  • Disallow base library setfenv() calls on Java functions
  • +
+ +

Known Issues

+
    +
  • debug code may not be completely removed by some obfuscators +
  • tail calls are not tracked in debug information +
  • using both version 1 and 2 libraries together in the same java vm has not been tested +
  • module() and setfenv() only partially supported for lau2java or luajc compiled lua +
  • values associated with weak keys may linger longer than expected +
  • behavior of luaj when a SecurityManager is used has not been fully characterized +
+ diff --git a/luaj-2.0.3/build-coverage.xml b/luaj-2.0.3/build-coverage.xml new file mode 100644 index 0000000000..8a491f8cc5 --- /dev/null +++ b/luaj-2.0.3/build-coverage.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/luaj-2.0.3/build-libs.xml b/luaj-2.0.3/build-libs.xml new file mode 100644 index 0000000000..872c5bb81e --- /dev/null +++ b/luaj-2.0.3/build-libs.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/luaj-2.0.3/build.xml b/luaj-2.0.3/build.xml new file mode 100644 index 0000000000..b2af82f7f4 --- /dev/null +++ b/luaj-2.0.3/build.xml @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Luaj API]]> + Copyright © 2007-2008 Luaj.org. All Rights Reserved.
]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/luaj-2.0.3/docs/api/allclasses-frame.html b/luaj-2.0.3/docs/api/allclasses-frame.html new file mode 100644 index 0000000000..6ddfdee4f3 --- /dev/null +++ b/luaj-2.0.3/docs/api/allclasses-frame.html @@ -0,0 +1,143 @@ + + + + + + +All Classes (Luaj API) + + + + + + + + + + + +All Classes +
+ + + + + +
BaseLib +
+Buffer +
+CoerceJavaToLua +
+CoerceLuaToJava +
+CoroutineLib +
+DebugLib +
+IoLib +
+JmeIoLib +
+JmePlatform +
+JseBaseLib +
+JseIoLib +
+JseMathLib +
+JseMathLib.JseMathLib1 +
+JseMathLib.JseMathLib2 +
+JseOsLib +
+JsePlatform +
+JseProcess +
+LibFunction +
+LoadState +
+LoadState.LuaCompiler +
+LocVars +
+Lua +
+LuaBoolean +
+LuaC +
+LuaClosure +
+LuaDouble +
+LuaError +
+LuaFunction +
+LuaInteger +
+LuajavaLib +
+LuaJC +
+LuaNil +
+LuaNumber +
+LuaString +
+LuaTable +
+LuaThread +
+LuaThread.CallStack +
+LuaUserdata +
+LuaValue +
+MathLib +
+OneArgFunction +
+OrphanedThread +
+OsLib +
+PackageLib +
+Print +
+Prototype +
+ResourceFinder +
+StringLib +
+TableLib +
+TailcallVarargs +
+ThreeArgFunction +
+TwoArgFunction +
+UpValue +
+VarArgFunction +
+Varargs +
+WeakTable +
+ZeroArgFunction +
+
+ + + diff --git a/luaj-2.0.3/docs/api/allclasses-noframe.html b/luaj-2.0.3/docs/api/allclasses-noframe.html new file mode 100644 index 0000000000..cdc91184b9 --- /dev/null +++ b/luaj-2.0.3/docs/api/allclasses-noframe.html @@ -0,0 +1,143 @@ + + + + + + +All Classes (Luaj API) + + + + + + + + + + + +All Classes +
+ + + + + +
BaseLib +
+Buffer +
+CoerceJavaToLua +
+CoerceLuaToJava +
+CoroutineLib +
+DebugLib +
+IoLib +
+JmeIoLib +
+JmePlatform +
+JseBaseLib +
+JseIoLib +
+JseMathLib +
+JseMathLib.JseMathLib1 +
+JseMathLib.JseMathLib2 +
+JseOsLib +
+JsePlatform +
+JseProcess +
+LibFunction +
+LoadState +
+LoadState.LuaCompiler +
+LocVars +
+Lua +
+LuaBoolean +
+LuaC +
+LuaClosure +
+LuaDouble +
+LuaError +
+LuaFunction +
+LuaInteger +
+LuajavaLib +
+LuaJC +
+LuaNil +
+LuaNumber +
+LuaString +
+LuaTable +
+LuaThread +
+LuaThread.CallStack +
+LuaUserdata +
+LuaValue +
+MathLib +
+OneArgFunction +
+OrphanedThread +
+OsLib +
+PackageLib +
+Print +
+Prototype +
+ResourceFinder +
+StringLib +
+TableLib +
+TailcallVarargs +
+ThreeArgFunction +
+TwoArgFunction +
+UpValue +
+VarArgFunction +
+Varargs +
+WeakTable +
+ZeroArgFunction +
+
+ + + diff --git a/luaj-2.0.3/docs/api/constant-values.html b/luaj-2.0.3/docs/api/constant-values.html new file mode 100644 index 0000000000..3608e3102f --- /dev/null +++ b/luaj-2.0.3/docs/api/constant-values.html @@ -0,0 +1,960 @@ + + + + + + +Constant Field Values (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Constant Field Values

+
+
+Contents + + + + + + +
+org.luaj.*
+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
org.luaj.vm2.LoadState
+public static final intLUA_TBOOLEAN1
+public static final intLUA_TFUNCTION6
+public static final intLUA_TINT-2
+public static final intLUA_TLIGHTUSERDATA2
+public static final intLUA_TNIL0
+public static final intLUA_TNONE-1
+public static final intLUA_TNUMBER3
+public static final intLUA_TSTRING4
+public static final intLUA_TTABLE5
+public static final intLUA_TTHREAD8
+public static final intLUA_TUSERDATA7
+public static final intLUA_TVALUE9
+public static final intLUAC_FORMAT0
+public static final intLUAC_HEADERSIZE12
+public static final intLUAC_VERSION81
+public static final intNUMBER_FORMAT_FLOATS_OR_DOUBLES0
+public static final intNUMBER_FORMAT_INTS_ONLY1
+public static final intNUMBER_FORMAT_NUM_PATCH_INT324
+public static final java.lang.StringSOURCE_BINARY_STRING"binary string"
+ +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
org.luaj.vm2.Lua
+public static final java.lang.String_VERSION"Luaj 0.0"
+public static final intBITRK256
+public static final intiABC0
+public static final intiABx1
+public static final intiAsBx2
+public static final intLFIELDS_PER_FLUSH50
+public static final intLUA_MULTRET-1
+public static final intMASK_A16320
+public static final intMASK_B-8388608
+public static final intMASK_Bx-16384
+public static final intMASK_C8372224
+public static final intMASK_NOT_A-16321
+public static final intMASK_NOT_B8388607
+public static final intMASK_NOT_Bx16383
+public static final intMASK_NOT_C-8372225
+public static final intMASK_NOT_OP-64
+public static final intMASK_OP63
+public static final intMAX_OP63
+public static final intMAXARG_A255
+public static final intMAXARG_B511
+public static final intMAXARG_Bx262143
+public static final intMAXARG_C511
+public static final intMAXARG_sBx131071
+public static final intMAXINDEXRK255
+public static final intNO_REG255
+public static final intNUM_OPCODES38
+public static final intOP_ADD12
+public static final intOP_AND60
+public static final intOP_CALL28
+public static final intOP_CLOSE35
+public static final intOP_CLOSURE36
+public static final intOP_CONCAT21
+public static final intOP_DIV15
+public static final intOP_EQ23
+public static final intOP_FORLOOP31
+public static final intOP_FORPREP32
+public static final intOP_GE62
+public static final intOP_GETGLOBAL5
+public static final intOP_GETTABLE6
+public static final intOP_GETUPVAL4
+public static final intOP_GT63
+public static final intOP_JMP22
+public static final intOP_LE25
+public static final intOP_LEN20
+public static final intOP_LOADBOOL2
+public static final intOP_LOADK1
+public static final intOP_LOADNIL3
+public static final intOP_LT24
+public static final intOP_MOD16
+public static final intOP_MOVE0
+public static final intOP_MUL14
+public static final intOP_NEQ61
+public static final intOP_NEWTABLE10
+public static final intOP_NOT19
+public static final intOP_OR59
+public static final intOP_POW17
+public static final intOP_RETURN30
+public static final intOP_SELF11
+public static final intOP_SETGLOBAL7
+public static final intOP_SETLIST34
+public static final intOP_SETTABLE9
+public static final intOP_SETUPVAL8
+public static final intOP_SUB13
+public static final intOP_TAILCALL29
+public static final intOP_TEST26
+public static final intOP_TESTSET27
+public static final intOP_TFORLOOP33
+public static final intOP_UNM18
+public static final intOP_VARARG37
+public static final intOpArgK3
+public static final intOpArgN0
+public static final intOpArgR2
+public static final intOpArgU1
+public static final intPOS_A6
+public static final intPOS_B23
+public static final intPOS_Bx14
+public static final intPOS_C14
+public static final intPOS_OP0
+public static final intSIZE_A8
+public static final intSIZE_B9
+public static final intSIZE_Bx18
+public static final intSIZE_C9
+public static final intSIZE_OP6
+public static final intVARARG_HASARG1
+public static final intVARARG_ISVARARG2
+public static final intVARARG_NEEDSARG4
+ +

+ +

+ + + + + + + + + + + + + + + + + + + + + + +
org.luaj.vm2.LuaDouble
+public static final java.lang.StringJSTR_NAN"nan"
+public static final java.lang.StringJSTR_NEGINF"-inf"
+public static final java.lang.StringJSTR_POSINF"inf"
+ +

+ +

+ + + + + + + + + + + + +
org.luaj.vm2.LuaThread
+public static final intMAX_CALLSTACK256
+ +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
org.luaj.vm2.LuaValue
+public static final intTBOOLEAN1
+public static final intTFUNCTION6
+public static final intTINT-2
+public static final intTLIGHTUSERDATA2
+public static final intTNIL0
+public static final intTNONE-1
+public static final intTNUMBER3
+public static final intTSTRING4
+public static final intTTABLE5
+public static final intTTHREAD8
+public static final intTUSERDATA7
+public static final intTVALUE9
+ +

+ +

+ + + + + + + + + + + + +
org.luaj.vm2.compiler.LuaC
+public static final intMAXSTACK250
+ +

+ +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/deprecated-list.html b/luaj-2.0.3/docs/api/deprecated-list.html new file mode 100644 index 0000000000..807e0a8565 --- /dev/null +++ b/luaj-2.0.3/docs/api/deprecated-list.html @@ -0,0 +1,146 @@ + + + + + + +Deprecated List (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Deprecated API

+
+
+Contents
    +
+ +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/help-doc.html b/luaj-2.0.3/docs/api/help-doc.html new file mode 100644 index 0000000000..44c84fe55d --- /dev/null +++ b/luaj-2.0.3/docs/api/help-doc.html @@ -0,0 +1,223 @@ + + + + + + +API Help (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+How This API Document Is Organized

+
+This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.

+Overview

+
+ +

+The Overview page is the front page of this API document and provides a list of all packages with a summary for each. This page can also contain an overall description of the set of packages.

+

+Package

+
+ +

+Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain four categories:

    +
  • Interfaces (italic)
  • Classes
  • Enums
  • Exceptions
  • Errors
  • Annotation Types
+
+

+Class/Interface

+
+ +

+Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:

    +
  • Class inheritance diagram
  • Direct Subclasses
  • All Known Subinterfaces
  • All Known Implementing Classes
  • Class/interface declaration
  • Class/interface description +

    +

  • Nested Class Summary
  • Field Summary
  • Constructor Summary
  • Method Summary +

    +

  • Field Detail
  • Constructor Detail
  • Method Detail
+Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.
+ +

+Annotation Type

+
+ +

+Each annotation type has its own separate page with the following sections:

    +
  • Annotation Type declaration
  • Annotation Type description
  • Required Element Summary
  • Optional Element Summary
  • Element Detail
+
+ +

+Enum

+
+ +

+Each enum has its own separate page with the following sections:

    +
  • Enum declaration
  • Enum description
  • Enum Constant Summary
  • Enum Constant Detail
+
+

+Use

+
+Each documented package, class and interface has its own Use page. This page describes what packages, classes, methods, constructors and fields use any part of the given class or package. Given a class or interface A, its Use page includes subclasses of A, fields declared as A, methods that return A, and methods and constructors with parameters of type A. You can access this page by first going to the package, class or interface, then clicking on the "Use" link in the navigation bar.
+

+Tree (Class Hierarchy)

+
+There is a Class Hierarchy page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. The classes are organized by inheritance structure starting with java.lang.Object. The interfaces do not inherit from java.lang.Object.
    +
  • When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.
  • When viewing a particular package, class or interface page, clicking "Tree" displays the hierarchy for only that package.
+
+

+Deprecated API

+
+The Deprecated API page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.
+

+Index

+
+The Index contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.
+

+Prev/Next

+These links take you to the next or previous class, interface, package, or related page.

+Frames/No Frames

+These links show and hide the HTML frames. All pages are available with or without frames. +

+

+Serialized Form

+Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description. +

+

+Constant Field Values

+The Constant Field Values page lists the static final fields and their values. +

+ + +This help file applies to API documentation generated using the standard doclet. + +
+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/index-all.html b/luaj-2.0.3/docs/api/index-all.html new file mode 100644 index 0000000000..6fcb0fc970 --- /dev/null +++ b/luaj-2.0.3/docs/api/index-all.html @@ -0,0 +1,4272 @@ + + + + + + +Index (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +A B C D E F G H I J K L M N O P R S T U V W Y Z _
+

+A

+
+
add(LuaValue) - +Method in class org.luaj.vm2.LuaDouble +
  +
add(double) - +Method in class org.luaj.vm2.LuaDouble +
  +
add(LuaValue) - +Method in class org.luaj.vm2.LuaInteger +
  +
add(double) - +Method in class org.luaj.vm2.LuaInteger +
  +
add(int) - +Method in class org.luaj.vm2.LuaInteger +
  +
add(LuaValue) - +Method in class org.luaj.vm2.LuaString +
  +
add(double) - +Method in class org.luaj.vm2.LuaString +
  +
add(int) - +Method in class org.luaj.vm2.LuaString +
  +
ADD - +Static variable in class org.luaj.vm2.LuaValue +
LuaString constant with value "__add" for use as metatag +
add(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Add: Perform numeric add operation with another value + including metatag processing. +
add(double) - +Method in class org.luaj.vm2.LuaValue +
Add: Perform numeric add operation with another value + of double type with metatag processing +
add(int) - +Method in class org.luaj.vm2.LuaValue +
Add: Perform numeric add operation with another value + of int type with metatag processing +
and(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Perform boolean and with another operand, based on lua rules for boolean evaluation. +
append(byte) - +Method in class org.luaj.vm2.Buffer +
Append a single byte to the buffer. +
append(LuaValue) - +Method in class org.luaj.vm2.Buffer +
Append a LuaValue to the buffer. +
append(LuaString) - +Method in class org.luaj.vm2.Buffer +
Append a LuaString to the buffer. +
append(String) - +Method in class org.luaj.vm2.Buffer +
Append a Java String to the buffer. +
arg(int) - +Method in class org.luaj.vm2.LuaValue +
  +
arg(int) - +Method in class org.luaj.vm2.TailcallVarargs +
  +
arg(int) - +Method in class org.luaj.vm2.Varargs +
Get the n-th argument value (1-based). +
arg1() - +Method in class org.luaj.vm2.LuaValue +
  +
arg1() - +Method in class org.luaj.vm2.TailcallVarargs +
  +
arg1() - +Method in class org.luaj.vm2.Varargs +
Get the first argument in the list. +
argcheck(boolean, int, String) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a LuaValue when a user-supplied assertion passes, or throw an error. +
argerror(String) - +Method in class org.luaj.vm2.LuaValue +
Throw a LuaError indicating an invalid argument was supplied to a function +
argerror(int, String) - +Static method in class org.luaj.vm2.LuaValue +
Throw a LuaError indicating an invalid argument was supplied to a function +
aritherror() - +Method in class org.luaj.vm2.LuaValue +
Throw a LuaError based on an arithmetic error such as add, or pow, + typically due to an invalid operand type +
aritherror(String) - +Method in class org.luaj.vm2.LuaValue +
Throw a LuaError based on an arithmetic error such as add, or pow, + typically due to an invalid operand type +
arithmt(LuaValue, LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Perform metatag processing for arithmetic operations. +
arithmtwith(LuaValue, double) - +Method in class org.luaj.vm2.LuaValue +
Perform metatag processing for arithmetic operations when the left-hand-side is a number. +
array - +Variable in class org.luaj.vm2.LuaTable +
the array values +
assert_(boolean, String) - +Static method in class org.luaj.vm2.LuaValue +
Assert a condition is true, or throw a LuaError if not +
+
+

+B

+
+
BaseLib - Class in org.luaj.vm2.lib
Subclass of LibFunction which implements the lua basic library functions.
BaseLib() - +Constructor for class org.luaj.vm2.lib.BaseLib +
Construct a base libarary instance. +
bind(LuaValue, Class, String[]) - +Method in class org.luaj.vm2.lib.LibFunction +
Bind a set of library functions. +
bind(LuaValue, Class, String[], int) - +Method in class org.luaj.vm2.lib.LibFunction +
Bind a set of library functions, with an offset +
BITRK - +Static variable in class org.luaj.vm2.Lua +
this bit 1 means constant (0 means register) +
booleanValue() - +Method in class org.luaj.vm2.LuaBoolean +
Return the boolean value for this boolean +
Buffer - Class in org.luaj.vm2
String buffer for use in string library methods, optimized for production + of StrValue instances.
Buffer() - +Constructor for class org.luaj.vm2.Buffer +
Create buffer with default capacity +
Buffer(int) - +Constructor for class org.luaj.vm2.Buffer +
Create buffer with specified initial capacity +
Buffer(LuaValue) - +Constructor for class org.luaj.vm2.Buffer +
Create buffer with specified initial value +
buffer() - +Method in class org.luaj.vm2.LuaValue +
Convert the value to a Buffer for more efficient concatenation of + multiple strings. +
+
+

+C

+
+
call(LuaValue) - +Method in class org.luaj.vm2.lib.BaseLib +
  +
call(LuaValue) - +Method in class org.luaj.vm2.lib.IoLib +
  +
call(LuaValue) - +Method in class org.luaj.vm2.lib.jse.JseMathLib +
  +
call(LuaValue) - +Method in class org.luaj.vm2.lib.jse.JseMathLib.JseMathLib1 +
  +
call(LuaValue, LuaValue) - +Method in class org.luaj.vm2.lib.jse.JseMathLib.JseMathLib2 +
  +
call(LuaValue) - +Method in class org.luaj.vm2.lib.MathLib +
  +
call(LuaValue) - +Method in class org.luaj.vm2.lib.OneArgFunction +
  +
call() - +Method in class org.luaj.vm2.lib.OneArgFunction +
  +
call(LuaValue, LuaValue) - +Method in class org.luaj.vm2.lib.OneArgFunction +
  +
call(LuaValue, LuaValue, LuaValue) - +Method in class org.luaj.vm2.lib.OneArgFunction +
  +
call(LuaValue) - +Method in class org.luaj.vm2.lib.PackageLib +
  +
call(LuaValue) - +Method in class org.luaj.vm2.lib.StringLib +
  +
call(LuaValue) - +Method in class org.luaj.vm2.lib.TableLib +
  +
call(LuaValue, LuaValue, LuaValue) - +Method in class org.luaj.vm2.lib.ThreeArgFunction +
  +
call() - +Method in class org.luaj.vm2.lib.ThreeArgFunction +
  +
call(LuaValue) - +Method in class org.luaj.vm2.lib.ThreeArgFunction +
  +
call(LuaValue, LuaValue) - +Method in class org.luaj.vm2.lib.ThreeArgFunction +
  +
call(LuaValue, LuaValue) - +Method in class org.luaj.vm2.lib.TwoArgFunction +
  +
call() - +Method in class org.luaj.vm2.lib.TwoArgFunction +
  +
call(LuaValue) - +Method in class org.luaj.vm2.lib.TwoArgFunction +
  +
call(LuaValue, LuaValue, LuaValue) - +Method in class org.luaj.vm2.lib.TwoArgFunction +
  +
call() - +Method in class org.luaj.vm2.lib.VarArgFunction +
  +
call(LuaValue) - +Method in class org.luaj.vm2.lib.VarArgFunction +
  +
call(LuaValue, LuaValue) - +Method in class org.luaj.vm2.lib.VarArgFunction +
  +
call(LuaValue, LuaValue, LuaValue) - +Method in class org.luaj.vm2.lib.VarArgFunction +
  +
call() - +Method in class org.luaj.vm2.lib.ZeroArgFunction +
  +
call(LuaValue) - +Method in class org.luaj.vm2.lib.ZeroArgFunction +
  +
call(LuaValue, LuaValue) - +Method in class org.luaj.vm2.lib.ZeroArgFunction +
  +
call(LuaValue, LuaValue, LuaValue) - +Method in class org.luaj.vm2.lib.ZeroArgFunction +
  +
call() - +Method in class org.luaj.vm2.LuaClosure +
  +
call(LuaValue) - +Method in class org.luaj.vm2.LuaClosure +
  +
call(LuaValue, LuaValue) - +Method in class org.luaj.vm2.LuaClosure +
  +
call(LuaValue, LuaValue, LuaValue) - +Method in class org.luaj.vm2.LuaClosure +
  +
CALL - +Static variable in class org.luaj.vm2.LuaValue +
LuaString constant with value "__call" for use as metatag +
call() - +Method in class org.luaj.vm2.LuaValue +
Call this with 0 arguments, including metatag processing, + and return only the first return value. +
call(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Call this with 1 argument, including metatag processing, + and return only the first return value. +
call(LuaValue, LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Call this with 2 arguments, including metatag processing, + and return only the first return value. +
call(LuaValue, LuaValue, LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Call this with 3 arguments, including metatag processing, + and return only the first return value. +
callmt() - +Method in class org.luaj.vm2.LuaValue +
Get the metatag value for the CALL metatag, if it exists. +
CALLS - +Static variable in class org.luaj.vm2.lib.DebugLib +
  +
changemode(boolean, boolean) - +Method in class org.luaj.vm2.LuaTable +
Change the mode of a table +
changemode(boolean, boolean) - +Method in class org.luaj.vm2.WeakTable +
  +
char_(Varargs) - +Static method in class org.luaj.vm2.lib.StringLib +
string.char (...) + + Receives zero or more integers. +
charAt(int) - +Method in class org.luaj.vm2.LuaString +
  +
checkboolean() - +Method in class org.luaj.vm2.LuaBoolean +
  +
checkboolean() - +Method in class org.luaj.vm2.LuaValue +
Check that the value is a LuaBoolean, + or throw LuaError if not +
checkboolean(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a boolean value, or throw an error if any other type. +
checkclosure() - +Method in class org.luaj.vm2.LuaClosure +
  +
checkclosure() - +Method in class org.luaj.vm2.LuaValue +
Check that the value is a LuaClosure , + or throw LuaError if not +
checkclosure(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a closure, or throw an error if any other type. +
checkdouble() - +Method in class org.luaj.vm2.LuaDouble +
  +
checkdouble() - +Method in class org.luaj.vm2.LuaInteger +
  +
checkdouble() - +Method in class org.luaj.vm2.LuaString +
  +
checkdouble() - +Method in class org.luaj.vm2.LuaValue +
Check that the value is numeric and return the value as a double, + or throw LuaError if not numeric +
checkdouble(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a double, or throw an error if it cannot be converted to one. +
checkfunction() - +Method in class org.luaj.vm2.LuaFunction +
  +
checkfunction() - +Method in class org.luaj.vm2.LuaValue +
Check that the value is a function , or throw LuaError if not +
checkfunction(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a function, or throw an error if an incompatible type. +
checkint() - +Method in class org.luaj.vm2.LuaDouble +
  +
checkint() - +Method in class org.luaj.vm2.LuaInteger +
  +
checkint() - +Method in class org.luaj.vm2.LuaString +
  +
checkint() - +Method in class org.luaj.vm2.LuaValue +
Check that the value is numeric, and convert and cast value to int, or throw LuaError if not numeric +
checkint(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java int value, discarding any fractional part, or throw an error if not a number. +
checkinteger() - +Method in class org.luaj.vm2.LuaDouble +
  +
checkinteger() - +Method in class org.luaj.vm2.LuaInteger +
  +
checkinteger() - +Method in class org.luaj.vm2.LuaString +
  +
checkinteger() - +Method in class org.luaj.vm2.LuaValue +
Check that the value is numeric, and convert and cast value to int, or throw LuaError if not numeric +
checkinteger(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java int value, or throw an error if not a number or is not representable by a java int. +
checkjstring() - +Method in class org.luaj.vm2.LuaDouble +
  +
checkjstring() - +Method in class org.luaj.vm2.LuaInteger +
  +
checkjstring() - +Method in class org.luaj.vm2.LuaString +
  +
checkjstring() - +Method in class org.luaj.vm2.LuaValue +
Convert this value to a Java String. +
checkjstring(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java String if a string or number, or throw an error if any other type +
checklong() - +Method in class org.luaj.vm2.LuaDouble +
  +
checklong() - +Method in class org.luaj.vm2.LuaInteger +
  +
checklong() - +Method in class org.luaj.vm2.LuaString +
  +
checklong() - +Method in class org.luaj.vm2.LuaValue +
Check that the value is numeric, and convert and cast value to long, or throw LuaError if not numeric +
checklong(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java long value, discarding any fractional part, or throw an error if not a number. +
checkmetatag(LuaValue, String) - +Method in class org.luaj.vm2.LuaValue +
Get particular metatag, or throw LuaError if it doesn't exist +
checknotnil() - +Method in class org.luaj.vm2.LuaNil +
  +
checknotnil() - +Method in class org.luaj.vm2.LuaValue +
Check that this is not the value NIL, or throw LuaError if it is +
checknotnil(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a LuaValue if it is not nil, or throw an error if it is nil. +
checknumber() - +Method in class org.luaj.vm2.LuaDouble +
  +
checknumber() - +Method in class org.luaj.vm2.LuaNumber +
  +
checknumber(String) - +Method in class org.luaj.vm2.LuaNumber +
  +
checknumber() - +Method in class org.luaj.vm2.LuaString +
  +
checknumber(String) - +Method in class org.luaj.vm2.LuaString +
  +
checknumber() - +Method in class org.luaj.vm2.LuaValue +
Check that the value is numeric, and return as a LuaNumber if so, or throw LuaError +
checknumber(String) - +Method in class org.luaj.vm2.LuaValue +
Check that the value is numeric, and return as a LuaNumber if so, or throw LuaError +
checknumber(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a LuaNumber, or throw an error if not a number or string that can be converted to a number. +
checkstring() - +Method in class org.luaj.vm2.LuaDouble +
  +
checkstring() - +Method in class org.luaj.vm2.LuaInteger +
  +
checkstring() - +Method in class org.luaj.vm2.LuaString +
  +
checkstring() - +Method in class org.luaj.vm2.LuaValue +
Check that this is a lua string, or throw LuaError if it is not. +
checkstring(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a LuaString if a string or number, or throw an error if any other type +
checktable() - +Method in class org.luaj.vm2.LuaTable +
  +
checktable() - +Method in class org.luaj.vm2.LuaValue +
Check that this is a LuaTable, or throw LuaError if it is not +
checktable(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a LuaTable if a lua table, or throw an error if any other type. +
checkthread() - +Method in class org.luaj.vm2.LuaThread +
  +
checkthread() - +Method in class org.luaj.vm2.LuaValue +
Check that this is a LuaThread, or throw LuaError if it is not +
checkthread(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a LuaThread if a lua thread, or throw an error if any other type. +
checkuserdata() - +Method in class org.luaj.vm2.LuaUserdata +
  +
checkuserdata(Class) - +Method in class org.luaj.vm2.LuaUserdata +
  +
checkuserdata() - +Method in class org.luaj.vm2.LuaValue +
Check that this is a LuaUserdata, or throw LuaError if it is not +
checkuserdata(Class) - +Method in class org.luaj.vm2.LuaValue +
Check that this is a LuaUserdata, or throw LuaError if it is not +
checkuserdata(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java Object if a userdata, or throw an error if any other type. +
checkuserdata(int, Class) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java Object if it is a userdata whose instance Class c or a subclass, + or throw an error if any other type. +
checkvalidkey() - +Method in class org.luaj.vm2.LuaDouble +
  +
checkvalidkey() - +Method in class org.luaj.vm2.LuaNil +
  +
checkvalidkey() - +Method in class org.luaj.vm2.LuaValue +
Check that this is a valid key in a table index operation, or throw LuaError if not +
checkvalue(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a LuaValue if it exists, or throw an error. +
classForName(String) - +Method in class org.luaj.vm2.lib.jse.LuajavaLib +
  +
clock() - +Method in class org.luaj.vm2.lib.OsLib +
  +
close() - +Method in class org.luaj.vm2.lib.IoLib.File +
  +
close() - +Method in class org.luaj.vm2.UpValue +
Close this upvalue so it is no longer on the stack +
code - +Variable in class org.luaj.vm2.Prototype +
  +
coerce(Object) - +Static method in class org.luaj.vm2.lib.jse.CoerceJavaToLua +
Coerse a Java object to a corresponding lua value. +
coerce(LuaValue, Class) - +Static method in class org.luaj.vm2.lib.jse.CoerceLuaToJava +
Coerce a LuaValue value to a specified java class +
CoerceJavaToLua - Class in org.luaj.vm2.lib.jse
Helper class to coerce values from Java to lua within the luajava library.
CoerceJavaToLua() - +Constructor for class org.luaj.vm2.lib.jse.CoerceJavaToLua +
  +
CoerceLuaToJava - Class in org.luaj.vm2.lib.jse
Helper class to coerce values from lua to Java within the luajava library.
CoerceLuaToJava() - +Constructor for class org.luaj.vm2.lib.jse.CoerceLuaToJava +
  +
compareerror(String) - +Method in class org.luaj.vm2.LuaValue +
Throw a LuaError based on a comparison error such as greater-than or less-than, + typically due to an invalid operand type +
compareerror(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Throw a LuaError based on a comparison error such as greater-than or less-than, + typically due to an invalid operand type +
comparemt(LuaValue, LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Perform metatag processing for comparison operations. +
compile(InputStream, String) - +Static method in class org.luaj.vm2.compiler.LuaC +
Compile a prototype or load as a binary chunk +
compileAll(InputStream, String, String) - +Method in class org.luaj.vm2.luajc.LuaJC +
  +
compiler - +Static variable in class org.luaj.vm2.LoadState +
Compiler instance, if installed +
concat(LuaValue) - +Method in class org.luaj.vm2.LuaNumber +
  +
concat(Buffer) - +Method in class org.luaj.vm2.LuaNumber +
  +
concat(LuaValue) - +Method in class org.luaj.vm2.LuaString +
  +
concat(Buffer) - +Method in class org.luaj.vm2.LuaString +
  +
concat(LuaString, int, int) - +Method in class org.luaj.vm2.LuaTable +
Concatenate the contents of a table efficiently, using Buffer +
CONCAT - +Static variable in class org.luaj.vm2.LuaValue +
LuaString constant with value "__concat" for use as metatag +
concat(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Concatenate another value onto this value and return the result + using rules of lua string concatenation including metatag processing. +
concat(Buffer) - +Method in class org.luaj.vm2.LuaValue +
Concatenate a Buffer onto this value and return the result + using rules of lua string concatenation including metatag processing. +
concatmt(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Perform metatag processing for concatenation operations. +
concatTo(LuaValue) - +Method in class org.luaj.vm2.Buffer +
Concatenate this buffer onto a LuaValue +
concatTo(LuaString) - +Method in class org.luaj.vm2.Buffer +
Concatenate this buffer onto a LuaString +
concatTo(LuaNumber) - +Method in class org.luaj.vm2.Buffer +
Concatenate this buffer onto a LuaNumber +
concatTo(LuaNumber) - +Method in class org.luaj.vm2.LuaNumber +
  +
concatTo(LuaString) - +Method in class org.luaj.vm2.LuaNumber +
  +
concatTo(LuaNumber) - +Method in class org.luaj.vm2.LuaString +
  +
concatTo(LuaString) - +Method in class org.luaj.vm2.LuaString +
  +
concatTo(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Reverse-concatenation: concatenate this value onto another value + whose type is unknwon + and return the result using rules of lua string concatenation including + metatag processing. +
concatTo(LuaNumber) - +Method in class org.luaj.vm2.LuaValue +
Reverse-concatenation: concatenate this value onto another value + known to be a LuaNumber + and return the result using rules of lua string concatenation including + metatag processing. +
concatTo(LuaString) - +Method in class org.luaj.vm2.LuaValue +
Reverse-concatenation: concatenate this value onto another value + known to be a LuaString + and return the result using rules of lua string concatenation including + metatag processing. +
copyInto(int, byte[], int, int) - +Method in class org.luaj.vm2.LuaString +
Copy the bytes of the string into the given byte array. +
coroutine_count - +Static variable in class org.luaj.vm2.LuaThread +
  +
CoroutineLib - Class in org.luaj.vm2.lib
Subclass of LibFunction which implements the lua standard coroutine + library.
CoroutineLib() - +Constructor for class org.luaj.vm2.lib.CoroutineLib +
  +
+
+

+D

+
+
date(String, double) - +Method in class org.luaj.vm2.lib.OsLib +
If the time argument is present, this is the time to be formatted + (see the os.time function for a description of this value). +
ddiv(double, double) - +Static method in class org.luaj.vm2.LuaDouble +
Divide two double numbers according to lua math, and return a LuaValue result. +
ddiv_d(double, double) - +Static method in class org.luaj.vm2.LuaDouble +
Divide two double numbers according to lua math, and return a double result. +
DEBUG_ENABLED - +Static variable in class org.luaj.vm2.lib.DebugLib +
  +
debugBytecode(int, Varargs, int) - +Static method in class org.luaj.vm2.lib.DebugLib +
Called by Closures on bytecode execution +
debugGlobals() - +Static method in class org.luaj.vm2.lib.jme.JmePlatform +
Create standard globals including the debug library. +
debugGlobals() - +Static method in class org.luaj.vm2.lib.jse.JsePlatform +
Create standard globals including the debug library. +
DebugLib - Class in org.luaj.vm2.lib
Subclass of LibFunction which implements the lua standard debug + library.
DebugLib() - +Constructor for class org.luaj.vm2.lib.DebugLib +
  +
debugOnCall(LuaThread, int, LuaFunction) - +Static method in class org.luaj.vm2.lib.DebugLib +
Called by Closures and recursing java functions on entry +
debugOnReturn(LuaThread, int) - +Static method in class org.luaj.vm2.lib.DebugLib +
Called by Closures and recursing java functions on return +
debugSetupCall(Varargs, LuaValue[]) - +Static method in class org.luaj.vm2.lib.DebugLib +
Called by Closures to set up stack and arguments to next call +
debugState - +Variable in class org.luaj.vm2.LuaThread +
Thread-local used by DebugLib to store debugging state. +
decodeAsUtf8(byte[], int, int) - +Static method in class org.luaj.vm2.LuaString +
Convert to Java String interpreting as utf8 characters. +
DEFAULT_LUA_PATH - +Static variable in class org.luaj.vm2.lib.PackageLib +
  +
difftime(double, double) - +Method in class org.luaj.vm2.lib.OsLib +
Returns the number of seconds from time t1 to time t2. +
div(LuaValue) - +Method in class org.luaj.vm2.LuaDouble +
  +
div(double) - +Method in class org.luaj.vm2.LuaDouble +
  +
div(int) - +Method in class org.luaj.vm2.LuaDouble +
  +
div(LuaValue) - +Method in class org.luaj.vm2.LuaInteger +
  +
div(double) - +Method in class org.luaj.vm2.LuaInteger +
  +
div(int) - +Method in class org.luaj.vm2.LuaInteger +
  +
div(LuaValue) - +Method in class org.luaj.vm2.LuaString +
  +
div(double) - +Method in class org.luaj.vm2.LuaString +
  +
div(int) - +Method in class org.luaj.vm2.LuaString +
  +
DIV - +Static variable in class org.luaj.vm2.LuaValue +
LuaString constant with value "__div" for use as metatag +
div(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Divide: Perform numeric divide operation by another value + of unknown type, + including metatag processing. +
div(double) - +Method in class org.luaj.vm2.LuaValue +
Divide: Perform numeric divide operation by another value + of double type without metatag processing +
div(int) - +Method in class org.luaj.vm2.LuaValue +
Divide: Perform numeric divide operation by another value + of int type without metatag processing +
divInto(double) - +Method in class org.luaj.vm2.LuaDouble +
  +
divInto(double) - +Method in class org.luaj.vm2.LuaInteger +
  +
divInto(double) - +Method in class org.luaj.vm2.LuaString +
  +
divInto(double) - +Method in class org.luaj.vm2.LuaValue +
Reverse-divide: Perform numeric divide operation into another value + with metatag processing +
dmod(double, double) - +Static method in class org.luaj.vm2.LuaDouble +
Take modulo double numbers according to lua math, and return a LuaValue result. +
dmod_d(double, double) - +Static method in class org.luaj.vm2.LuaDouble +
Take modulo for double numbers according to lua math, and return a double result. +
dpow(double, double) - +Static method in class org.luaj.vm2.lib.MathLib +
compute power using installed math library, or default if there is no math library installed +
dpow_d(double, double) - +Static method in class org.luaj.vm2.lib.MathLib +
  +
dpow_default(double, double) - +Static method in class org.luaj.vm2.lib.MathLib +
Default JME version computes using longhand heuristics. +
dpow_lib(double, double) - +Method in class org.luaj.vm2.lib.jse.JseMathLib +
Faster, better version of pow() used by arithmetic operator ^ +
dpow_lib(double, double) - +Method in class org.luaj.vm2.lib.MathLib +
Hook to override default dpow behavior with faster implementation. +
+
+

+E

+
+
EMPTYSTRING - +Static variable in class org.luaj.vm2.LuaValue +
LuaString constant with value "" +
encodeToUtf8(char[], byte[], int) - +Static method in class org.luaj.vm2.LuaString +
Encode the given Java string as UTF-8 bytes, writing the result to bytes + starting at offset. +
endpc - +Variable in class org.luaj.vm2.LocVars +
The instruction offset when the variable goes out of scope +
env - +Variable in class org.luaj.vm2.LuaFunction +
  +
eq(LuaValue) - +Method in class org.luaj.vm2.LuaDouble +
  +
eq(LuaValue) - +Method in class org.luaj.vm2.LuaInteger +
  +
eq(LuaValue) - +Method in class org.luaj.vm2.LuaString +
  +
eq(LuaValue) - +Method in class org.luaj.vm2.LuaTable +
  +
eq(LuaValue) - +Method in class org.luaj.vm2.LuaUserdata +
  +
EQ - +Static variable in class org.luaj.vm2.LuaValue +
LuaString constant with value "__eq" for use as metatag +
eq(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Equals: Perform equality comparison with another value + including metatag processing using EQ. +
eq_b(LuaValue) - +Method in class org.luaj.vm2.LuaDouble +
  +
eq_b(LuaValue) - +Method in class org.luaj.vm2.LuaInteger +
  +
eq_b(LuaValue) - +Method in class org.luaj.vm2.LuaString +
  +
eq_b(LuaValue) - +Method in class org.luaj.vm2.LuaTable +
  +
eq_b(LuaValue) - +Method in class org.luaj.vm2.LuaUserdata +
  +
eq_b(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Equals: Perform equality comparison with another value + including metatag processing using EQ, + and return java boolean +
eqmt(LuaValue) - +Method in class org.luaj.vm2.LuaUserdata +
  +
eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue) - +Static method in class org.luaj.vm2.LuaValue +
Perform equality testing metatag processing +
equals(Object) - +Method in class org.luaj.vm2.LuaDouble +
  +
equals(Object) - +Method in class org.luaj.vm2.LuaInteger +
  +
equals(Object) - +Method in class org.luaj.vm2.LuaNil +
  +
equals(Object) - +Method in class org.luaj.vm2.LuaString +
  +
equals(LuaString, int, LuaString, int, int) - +Static method in class org.luaj.vm2.LuaString +
  +
equals(byte[], int, byte[], int, int) - +Static method in class org.luaj.vm2.LuaString +
  +
equals(Object) - +Method in class org.luaj.vm2.LuaUserdata +
  +
equals(Object) - +Method in class org.luaj.vm2.LuaValue +
  +
err - +Variable in class org.luaj.vm2.LuaThread +
Field to hold state of error condition during debug hook function calls. +
error(String) - +Static method in class org.luaj.vm2.LuaValue +
Throw a LuaError with a particular message +
eval() - +Method in class org.luaj.vm2.TailcallVarargs +
  +
eval() - +Method in class org.luaj.vm2.Varargs +
Evaluate any pending tail call and return result. +
EXEC_ERROR - +Static variable in class org.luaj.vm2.lib.jse.JseOsLib +
return code indicating the execute() threw an unknown exception +
EXEC_INTERRUPTED - +Static variable in class org.luaj.vm2.lib.jse.JseOsLib +
return code indicating the execute() was interrupted +
EXEC_IOEXCEPTION - +Static variable in class org.luaj.vm2.lib.jse.JseOsLib +
return code indicating the execute() threw an I/O exception +
execute(String) - +Method in class org.luaj.vm2.lib.jse.JseOsLib +
  +
execute(String) - +Method in class org.luaj.vm2.lib.OsLib +
This function is equivalent to the C function system. +
execute(LuaValue[], Varargs) - +Method in class org.luaj.vm2.LuaClosure +
  +
exit(int) - +Method in class org.luaj.vm2.lib.OsLib +
Calls the C function exit, with an optional code, to terminate the host program. +
exitValue() - +Method in class org.luaj.vm2.lib.jse.JseProcess +
Get the exit value of the process. +
+
+

+F

+
+
FALSE - +Static variable in class org.luaj.vm2.LuaValue +
LuaBoolean constant corresponding to lua false +
FILE_NAMES - +Static variable in class org.luaj.vm2.lib.IoLib +
  +
fileline() - +Static method in class org.luaj.vm2.lib.DebugLib +
Get file and line for the nearest calling closure. +
fileline(int) - +Static method in class org.luaj.vm2.lib.DebugLib +
Get file and line for a particular level, even if it is a java function. +
FINDER - +Static variable in class org.luaj.vm2.lib.BaseLib +
Singleton file opener for this Java ClassLoader realm. +
findResource(String) - +Method in class org.luaj.vm2.lib.BaseLib +
ResourceFinder implementation + + Tries to open the file as a resource, which can work for . +
findResource(String) - +Method in class org.luaj.vm2.lib.jse.JseBaseLib +
Try to open a file in the current working directory, + or fall back to base opener if not found. +
findResource(String) - +Method in interface org.luaj.vm2.lib.ResourceFinder +
Try to open a file, or return null if not found. +
flush() - +Method in class org.luaj.vm2.lib.IoLib.File +
  +
foreach(LuaValue) - +Method in class org.luaj.vm2.LuaTable +
Call the supplied function once for each key-value pair +
foreachi(LuaValue) - +Method in class org.luaj.vm2.LuaTable +
Call the supplied function once for each key-value pair + in the contiguous array part +
freadall(IoLib.File) - +Static method in class org.luaj.vm2.lib.IoLib +
  +
freadbytes(IoLib.File, int) - +Static method in class org.luaj.vm2.lib.IoLib +
  +
freadline(IoLib.File) - +Static method in class org.luaj.vm2.lib.IoLib +
  +
freadnumber(IoLib.File) - +Static method in class org.luaj.vm2.lib.IoLib +
  +
freaduntil(IoLib.File, boolean) - +Static method in class org.luaj.vm2.lib.IoLib +
  +
+
+

+G

+
+
GC_INTERVAL - +Static variable in class org.luaj.vm2.LuaThread +
Interval to check for LuaThread dereferencing. +
get(LuaValue) - +Method in class org.luaj.vm2.lib.IoLib.File +
  +
get(LuaValue) - +Method in class org.luaj.vm2.LuaString +
  +
get(int) - +Method in class org.luaj.vm2.LuaTable +
  +
get(LuaValue) - +Method in class org.luaj.vm2.LuaTable +
  +
get(LuaValue) - +Method in class org.luaj.vm2.LuaUserdata +
  +
get(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Get a value in a table including metatag processing using INDEX. +
get(int) - +Method in class org.luaj.vm2.LuaValue +
Get a value in a table including metatag processing using INDEX. +
get(String) - +Method in class org.luaj.vm2.LuaValue +
Get a value in a table including metatag processing using INDEX. +
GET_OPCODE(int) - +Static method in class org.luaj.vm2.Lua +
  +
GETARG_A(int) - +Static method in class org.luaj.vm2.Lua +
  +
GETARG_B(int) - +Static method in class org.luaj.vm2.Lua +
  +
GETARG_Bx(int) - +Static method in class org.luaj.vm2.Lua +
  +
GETARG_C(int) - +Static method in class org.luaj.vm2.Lua +
  +
GETARG_sBx(int) - +Static method in class org.luaj.vm2.Lua +
  +
getArrayLength() - +Method in class org.luaj.vm2.LuaTable +
Get the length of the array part of the table. +
getArrayLength() - +Method in class org.luaj.vm2.WeakTable +
  +
getBMode(int) - +Static method in class org.luaj.vm2.Lua +
  +
getCallstackDepth() - +Method in class org.luaj.vm2.LuaThread.CallStack +
Get number of calls in stack +
getCallstackFunction(int) - +Static method in class org.luaj.vm2.LuaThread +
Get the function called as a specific location on the stack. +
getCause() - +Method in exception org.luaj.vm2.LuaError +
Get the cause, if any. +
getCMode(int) - +Static method in class org.luaj.vm2.Lua +
  +
getenv(String) - +Method in class org.luaj.vm2.lib.OsLib +
Returns the value of the process environment variable varname, + or null if the variable is not defined. +
getfenv() - +Method in class org.luaj.vm2.LuaFunction +
  +
getfenv() - +Method in class org.luaj.vm2.LuaThread +
  +
getfenv() - +Method in class org.luaj.vm2.LuaValue +
Get the environemnt for an instance. +
getGlobals() - +Static method in class org.luaj.vm2.LuaThread +
Get the current thread's environment +
getHashLength() - +Method in class org.luaj.vm2.LuaTable +
Get the length of the hash part of the table. +
getHashLength() - +Method in class org.luaj.vm2.WeakTable +
  +
getInstance() - +Static method in class org.luaj.vm2.luajc.LuaJC +
  +
getlocalname(int, int) - +Method in class org.luaj.vm2.Prototype +
Get the name of a local variable. +
getmetatable() - +Method in class org.luaj.vm2.LuaBoolean +
  +
getmetatable() - +Method in class org.luaj.vm2.LuaClosure +
  +
getmetatable() - +Method in class org.luaj.vm2.LuaFunction +
  +
getmetatable() - +Method in class org.luaj.vm2.LuaNil +
  +
getmetatable() - +Method in class org.luaj.vm2.LuaNumber +
  +
getmetatable() - +Method in class org.luaj.vm2.LuaString +
  +
getmetatable() - +Method in class org.luaj.vm2.LuaTable +
  +
getmetatable() - +Method in class org.luaj.vm2.LuaThread +
  +
getmetatable() - +Method in class org.luaj.vm2.LuaUserdata +
  +
getmetatable() - +Method in class org.luaj.vm2.LuaValue +
Get the metatable for this LuaValue +
getn() - +Method in class org.luaj.vm2.LuaTable +
  +
getn() - +Method in class org.luaj.vm2.LuaValue +
Implementation of lua 5.0 getn() function. +
getOpMode(int) - +Static method in class org.luaj.vm2.Lua +
  +
getRunning() - +Static method in class org.luaj.vm2.LuaThread +
Get the currently running thread. +
getSourceName(String) - +Static method in class org.luaj.vm2.LoadState +
Construct a source name from a supplied chunk name +
getStatus() - +Method in class org.luaj.vm2.LuaThread +
  +
gettable(LuaValue, LuaValue) - +Static method in class org.luaj.vm2.LuaValue +
get value from metatable operations, or NIL if not defined by metatables +
getUpvalue(int) - +Method in class org.luaj.vm2.LuaClosure +
  +
getValue() - +Method in class org.luaj.vm2.UpValue +
Get the value of the upvalue +
gt(LuaValue) - +Method in class org.luaj.vm2.LuaDouble +
  +
gt(double) - +Method in class org.luaj.vm2.LuaDouble +
  +
gt(int) - +Method in class org.luaj.vm2.LuaDouble +
  +
gt(LuaValue) - +Method in class org.luaj.vm2.LuaInteger +
  +
gt(double) - +Method in class org.luaj.vm2.LuaInteger +
  +
gt(int) - +Method in class org.luaj.vm2.LuaInteger +
  +
gt(LuaValue) - +Method in class org.luaj.vm2.LuaString +
  +
gt(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Greater than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue. +
gt(double) - +Method in class org.luaj.vm2.LuaValue +
Greater than: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue. +
gt(int) - +Method in class org.luaj.vm2.LuaValue +
Greater than: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue. +
gt_b(LuaValue) - +Method in class org.luaj.vm2.LuaDouble +
  +
gt_b(int) - +Method in class org.luaj.vm2.LuaDouble +
  +
gt_b(double) - +Method in class org.luaj.vm2.LuaDouble +
  +
gt_b(LuaValue) - +Method in class org.luaj.vm2.LuaInteger +
  +
gt_b(int) - +Method in class org.luaj.vm2.LuaInteger +
  +
gt_b(double) - +Method in class org.luaj.vm2.LuaInteger +
  +
gt_b(LuaValue) - +Method in class org.luaj.vm2.LuaString +
  +
gt_b(int) - +Method in class org.luaj.vm2.LuaString +
  +
gt_b(double) - +Method in class org.luaj.vm2.LuaString +
  +
gt_b(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Greater than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +
gt_b(int) - +Method in class org.luaj.vm2.LuaValue +
Greater than: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean. +
gt_b(double) - +Method in class org.luaj.vm2.LuaValue +
Greater than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +
gteq(LuaValue) - +Method in class org.luaj.vm2.LuaDouble +
  +
gteq(double) - +Method in class org.luaj.vm2.LuaDouble +
  +
gteq(int) - +Method in class org.luaj.vm2.LuaDouble +
  +
gteq(LuaValue) - +Method in class org.luaj.vm2.LuaInteger +
  +
gteq(double) - +Method in class org.luaj.vm2.LuaInteger +
  +
gteq(int) - +Method in class org.luaj.vm2.LuaInteger +
  +
gteq(LuaValue) - +Method in class org.luaj.vm2.LuaString +
  +
gteq(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Greater than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue. +
gteq(double) - +Method in class org.luaj.vm2.LuaValue +
Greater than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue. +
gteq(int) - +Method in class org.luaj.vm2.LuaValue +
Greater than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue. +
gteq_b(LuaValue) - +Method in class org.luaj.vm2.LuaDouble +
  +
gteq_b(int) - +Method in class org.luaj.vm2.LuaDouble +
  +
gteq_b(double) - +Method in class org.luaj.vm2.LuaDouble +
  +
gteq_b(LuaValue) - +Method in class org.luaj.vm2.LuaInteger +
  +
gteq_b(int) - +Method in class org.luaj.vm2.LuaInteger +
  +
gteq_b(double) - +Method in class org.luaj.vm2.LuaInteger +
  +
gteq_b(LuaValue) - +Method in class org.luaj.vm2.LuaString +
  +
gteq_b(int) - +Method in class org.luaj.vm2.LuaString +
  +
gteq_b(double) - +Method in class org.luaj.vm2.LuaString +
  +
gteq_b(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Greater than or equals: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +
gteq_b(int) - +Method in class org.luaj.vm2.LuaValue +
Greater than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean. +
gteq_b(double) - +Method in class org.luaj.vm2.LuaValue +
Greater than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, + and returning java boolean. +
+
+

+H

+
+
hashClearSlot(int) - +Method in class org.luaj.vm2.LuaTable +
Clear a particular slot in the table +
hashCode() - +Method in class org.luaj.vm2.LuaDouble +
  +
hashCode() - +Method in class org.luaj.vm2.LuaInteger +
  +
hashCode() - +Method in class org.luaj.vm2.LuaString +
  +
hashCode() - +Method in class org.luaj.vm2.LuaUserdata +
  +
hashEntries - +Variable in class org.luaj.vm2.LuaTable +
the number of hash entries +
hashFindSlot(LuaValue) - +Method in class org.luaj.vm2.LuaTable +
Find the hashtable slot to use +
hashFindSlot(LuaValue) - +Method in class org.luaj.vm2.WeakTable +
  +
hashget(LuaValue) - +Method in class org.luaj.vm2.LuaTable +
  +
hashget(LuaValue) - +Method in class org.luaj.vm2.WeakTable +
Get the hash value for a key + key the key to look up +
hashKeys - +Variable in class org.luaj.vm2.LuaTable +
the hash keys +
hashset(LuaValue, LuaValue) - +Method in class org.luaj.vm2.LuaTable +
Set a hashtable value +
hashValues - +Variable in class org.luaj.vm2.LuaTable +
the hash values +
+
+

+I

+
+
iABC - +Static variable in class org.luaj.vm2.Lua +
  +
iABx - +Static variable in class org.luaj.vm2.Lua +
  +
iAsBx - +Static variable in class org.luaj.vm2.Lua +
  +
illegal(String, String) - +Method in class org.luaj.vm2.LuaValue +
Throw a LuaError indicating an illegal operation occurred, + typically involved in managing weak references +
INDEX - +Static variable in class org.luaj.vm2.LuaValue +
LuaString constant with value "__index" for use as metatag +
INDEXK(int) - +Static method in class org.luaj.vm2.Lua +
gets the index of the constant +
indexOf(byte, int) - +Method in class org.luaj.vm2.LuaString +
Find the index of a byte starting at a point in this string +
indexOf(LuaString, int) - +Method in class org.luaj.vm2.LuaString +
Find the index of a string starting at a point in this string +
indexOfAny(LuaString) - +Method in class org.luaj.vm2.LuaString +
Java version of strpbrk - find index of any byte that in an accept string. +
inext(LuaValue) - +Method in class org.luaj.vm2.LuaTable +
Get the next element after a particular key in the + contiguous array part of a table +
inext(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Find the next integer-key,value pair if this is a table, + return NIL if there are no more, or throw a LuaError if not a table. +
init() - +Method in class org.luaj.vm2.lib.OsLib +
  +
insert(int, LuaValue) - +Method in class org.luaj.vm2.LuaTable +
Insert an element at a position in a list-table +
install() - +Static method in class org.luaj.vm2.compiler.LuaC +
Install the compiler so that LoadState will first + try to use it when handed bytes that are + not already a compiled lua chunk. +
install() - +Static method in class org.luaj.vm2.luajc.LuaJC +
Install the compiler as the main compiler to use. +
instance - +Static variable in class org.luaj.vm2.compiler.LuaC +
  +
instance - +Static variable in class org.luaj.vm2.lib.BaseLib +
  +
instance - +Static variable in class org.luaj.vm2.lib.PackageLib +
Most recent instance of PackageLib +
instance - +Static variable in class org.luaj.vm2.lib.StringLib +
  +
invoke(Varargs) - +Method in class org.luaj.vm2.lib.CoroutineLib +
  +
invoke(Varargs) - +Method in class org.luaj.vm2.lib.DebugLib +
  +
invoke(Varargs) - +Method in class org.luaj.vm2.lib.jse.LuajavaLib +
  +
invoke(Varargs) - +Method in class org.luaj.vm2.lib.OneArgFunction +
  +
invoke(Varargs) - +Method in class org.luaj.vm2.lib.OsLib +
  +
invoke(Varargs) - +Method in class org.luaj.vm2.lib.ThreeArgFunction +
  +
invoke(Varargs) - +Method in class org.luaj.vm2.lib.TwoArgFunction +
  +
invoke(Varargs) - +Method in class org.luaj.vm2.lib.VarArgFunction +
Override and implement for the best performance. +
invoke(Varargs) - +Method in class org.luaj.vm2.lib.ZeroArgFunction +
  +
invoke(Varargs) - +Method in class org.luaj.vm2.LuaClosure +
  +
invoke() - +Method in class org.luaj.vm2.LuaValue +
Call this with 0 arguments, including metatag processing, + and retain all return values in a Varargs. +
invoke(Varargs) - +Method in class org.luaj.vm2.LuaValue +
Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs. +
invoke(LuaValue, Varargs) - +Method in class org.luaj.vm2.LuaValue +
Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs. +
invoke(LuaValue, LuaValue, Varargs) - +Method in class org.luaj.vm2.LuaValue +
Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs. +
invoke(LuaValue[]) - +Method in class org.luaj.vm2.LuaValue +
Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs. +
invoke(LuaValue[], Varargs) - +Method in class org.luaj.vm2.LuaValue +
Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs. +
invokemethod(String) - +Method in class org.luaj.vm2.LuaValue +
Call named method on this with 0 arguments, including metatag processing, + and retain all return values in a Varargs. +
invokemethod(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Call named method on this with 0 arguments, including metatag processing, + and retain all return values in a Varargs. +
invokemethod(String, Varargs) - +Method in class org.luaj.vm2.LuaValue +
Call named method on this with 1 argument, including metatag processing, + and retain all return values in a Varargs. +
invokemethod(LuaValue, Varargs) - +Method in class org.luaj.vm2.LuaValue +
Call named method on this with variable arguments, including metatag processing, + and retain all return values in a Varargs. +
invokemethod(String, LuaValue[]) - +Method in class org.luaj.vm2.LuaValue +
Call named method on this with 1 argument, including metatag processing, + and retain all return values in a Varargs. +
invokemethod(LuaValue, LuaValue[]) - +Method in class org.luaj.vm2.LuaValue +
Call named method on this with variable arguments, including metatag processing, + and retain all return values in a Varargs. +
IO_NAMES - +Static variable in class org.luaj.vm2.lib.IoLib +
  +
IoLib - Class in org.luaj.vm2.lib
Abstract base class extending LibFunction which implements the + core of the lua standard io library.
IoLib() - +Constructor for class org.luaj.vm2.lib.IoLib +
  +
IoLib.File - Class in org.luaj.vm2.lib
 
IoLib.File() - +Constructor for class org.luaj.vm2.lib.IoLib.File +
  +
is - +Variable in class org.luaj.vm2.LoadState +
input stream from which we are loading +
is_vararg - +Variable in class org.luaj.vm2.Prototype +
  +
isboolean() - +Method in class org.luaj.vm2.LuaBoolean +
  +
isboolean() - +Method in class org.luaj.vm2.LuaValue +
Check if this is a boolean +
isclosed() - +Method in class org.luaj.vm2.lib.IoLib.File +
  +
isclosure() - +Method in class org.luaj.vm2.LuaClosure +
  +
isclosure() - +Method in class org.luaj.vm2.LuaValue +
Check if this is a function that is a closure, + meaning interprets lua bytecode for its execution +
isfunction() - +Method in class org.luaj.vm2.LuaFunction +
  +
isfunction() - +Method in class org.luaj.vm2.LuaValue +
Check if this is a function +
isfunction(int) - +Method in class org.luaj.vm2.Varargs +
Tests if argument i is a function. +
isint() - +Method in class org.luaj.vm2.LuaInteger +
  +
isint() - +Method in class org.luaj.vm2.LuaString +
  +
isint() - +Method in class org.luaj.vm2.LuaValue +
Check if this is a number and is representable by java int + without rounding or truncation +
isinttype() - +Method in class org.luaj.vm2.LuaInteger +
  +
isinttype() - +Method in class org.luaj.vm2.LuaValue +
Check if this is a LuaInteger +
ISK(int) - +Static method in class org.luaj.vm2.Lua +
test whether value is a constant +
islong() - +Method in class org.luaj.vm2.LuaDouble +
  +
islong() - +Method in class org.luaj.vm2.LuaInteger +
  +
islong() - +Method in class org.luaj.vm2.LuaString +
  +
islong() - +Method in class org.luaj.vm2.LuaValue +
Check if this is a number and is representable by java long + without rounding or truncation +
isMainThread(LuaThread) - +Static method in class org.luaj.vm2.LuaThread +
Test if this is the main thread +
isnil() - +Method in class org.luaj.vm2.LuaNil +
  +
isnil() - +Method in class org.luaj.vm2.LuaValue +
Check if this is nil +
isnil(int) - +Method in class org.luaj.vm2.Varargs +
Tests if argument i is nil. +
isnoneornil(int) - +Method in class org.luaj.vm2.Varargs +
Return true if there is no argument or nil at argument i. +
isnumber() - +Method in class org.luaj.vm2.LuaDouble +
  +
isnumber() - +Method in class org.luaj.vm2.LuaNumber +
  +
isnumber() - +Method in class org.luaj.vm2.LuaString +
  +
isnumber() - +Method in class org.luaj.vm2.LuaValue +
Check if this is a number +
isnumber(int) - +Method in class org.luaj.vm2.Varargs +
Tests if argument i is a number. +
isstdfile() - +Method in class org.luaj.vm2.lib.IoLib.File +
  +
isstring() - +Method in class org.luaj.vm2.LuaDouble +
  +
isstring() - +Method in class org.luaj.vm2.LuaInteger +
  +
isstring() - +Method in class org.luaj.vm2.LuaNumber +
  +
isstring() - +Method in class org.luaj.vm2.LuaString +
  +
isstring() - +Method in class org.luaj.vm2.LuaValue +
Check if this is a string +
isstring(int) - +Method in class org.luaj.vm2.Varargs +
Tests if argument i is a string. +
istable() - +Method in class org.luaj.vm2.LuaTable +
  +
istable() - +Method in class org.luaj.vm2.LuaValue +
Check if this is a table +
istable(int) - +Method in class org.luaj.vm2.Varargs +
Tests if argument i is a table. +
isTailcall() - +Method in class org.luaj.vm2.TailcallVarargs +
  +
isTailcall() - +Method in class org.luaj.vm2.Varargs +
Return true if this is a TailcallVarargs +
isthread() - +Method in class org.luaj.vm2.LuaThread +
  +
isthread() - +Method in class org.luaj.vm2.LuaValue +
Check if this is a thread +
isthread(int) - +Method in class org.luaj.vm2.Varargs +
Tests if argument i is a thread. +
isuserdata() - +Method in class org.luaj.vm2.LuaUserdata +
  +
isuserdata(Class) - +Method in class org.luaj.vm2.LuaUserdata +
  +
isuserdata() - +Method in class org.luaj.vm2.LuaValue +
Check if this is a userdata +
isuserdata(Class) - +Method in class org.luaj.vm2.LuaValue +
Check if this is a userdata of type c +
isuserdata(int) - +Method in class org.luaj.vm2.Varargs +
Tests if argument i is a userdata. +
isValidUtf8() - +Method in class org.luaj.vm2.LuaString +
Check that a byte sequence is valid UTF-8 +
isvalue(int) - +Method in class org.luaj.vm2.Varargs +
Tests if a value exists at argument i. +
isweaknil() - +Method in class org.luaj.vm2.LuaValue +
Test if this is a weak reference and its value no longer is referenced. +
+
+

+J

+
+
java_loader - +Variable in class org.luaj.vm2.lib.PackageLib +
Loader that loads as a Java class. +
JmeIoLib - Class in org.luaj.vm2.lib.jme
Subclass of IoLib and therefore LibFunction which implements the lua standard io + library for the JSE platform.
JmeIoLib() - +Constructor for class org.luaj.vm2.lib.jme.JmeIoLib +
  +
JmePlatform - Class in org.luaj.vm2.lib.jme
The JmePlatform class is a convenience class to standardize + how globals tables are initialized for the JME platform.
JmePlatform() - +Constructor for class org.luaj.vm2.lib.jme.JmePlatform +
  +
JseBaseLib - Class in org.luaj.vm2.lib.jse
Subclass of BaseLib and LibFunction which implements the lua basic library functions + and provides a directory based ResourceFinder as the BaseLib.FINDER.
JseBaseLib() - +Constructor for class org.luaj.vm2.lib.jse.JseBaseLib +
Construct a JSE base library instance +
JseIoLib - Class in org.luaj.vm2.lib.jse
Subclass of IoLib and therefore LibFunction which implements the lua standard io + library for the JSE platform.
JseIoLib() - +Constructor for class org.luaj.vm2.lib.jse.JseIoLib +
  +
JseMathLib - Class in org.luaj.vm2.lib.jse
Subclass of LibFunction which implements the lua standard math + library.
JseMathLib() - +Constructor for class org.luaj.vm2.lib.jse.JseMathLib +
  +
JseMathLib.JseMathLib1 - Class in org.luaj.vm2.lib.jse
 
JseMathLib.JseMathLib1() - +Constructor for class org.luaj.vm2.lib.jse.JseMathLib.JseMathLib1 +
  +
JseMathLib.JseMathLib2 - Class in org.luaj.vm2.lib.jse
 
JseMathLib.JseMathLib2() - +Constructor for class org.luaj.vm2.lib.jse.JseMathLib.JseMathLib2 +
  +
JseOsLib - Class in org.luaj.vm2.lib.jse
Subclass of LibFunction which implements the standard lua os library.
JseOsLib() - +Constructor for class org.luaj.vm2.lib.jse.JseOsLib +
public constructor +
JsePlatform - Class in org.luaj.vm2.lib.jse
The JsePlatform class is a convenience class to standardize + how globals tables are initialized for the JSE platform.
JsePlatform() - +Constructor for class org.luaj.vm2.lib.jse.JsePlatform +
  +
JseProcess - Class in org.luaj.vm2.lib.jse
Analog of Process that pipes input and output to client-specified streams.
JseProcess(String[], InputStream, OutputStream, OutputStream) - +Constructor for class org.luaj.vm2.lib.jse.JseProcess +
Construct a process around a command, with specified streams to redirect input and output to. +
JseProcess(String, InputStream, OutputStream, OutputStream) - +Constructor for class org.luaj.vm2.lib.jse.JseProcess +
Construct a process around a command, with specified streams to redirect input and output to. +
JSTR_NAN - +Static variable in class org.luaj.vm2.LuaDouble +
Constant String representation for NaN (not a number), "nan" +
JSTR_NEGINF - +Static variable in class org.luaj.vm2.LuaDouble +
Constant String representation for negative infinity, "-inf" +
JSTR_POSINF - +Static variable in class org.luaj.vm2.LuaDouble +
Constant String representation for positive infinity, "inf" +
+
+

+K

+
+
k - +Variable in class org.luaj.vm2.Prototype +
  +
keyCount() - +Method in class org.luaj.vm2.LuaTable +
This may be deprecated in a future release. +
keys() - +Method in class org.luaj.vm2.LuaTable +
This may be deprecated in a future release. +
+
+

+L

+
+
lastIndexOf(LuaString) - +Method in class org.luaj.vm2.LuaString +
Find the last index of a string in this string +
lastlinedefined - +Variable in class org.luaj.vm2.Prototype +
  +
LE - +Static variable in class org.luaj.vm2.LuaValue +
LuaString constant with value "__le" for use as metatag +
len() - +Method in class org.luaj.vm2.LuaString +
  +
len() - +Method in class org.luaj.vm2.LuaTable +
  +
LEN - +Static variable in class org.luaj.vm2.LuaValue +
LuaString constant with value "__len" for use as metatag +
len() - +Method in class org.luaj.vm2.LuaValue +
Length operator: return lua length of object (#this) including metatag processing as java int +
lenerror() - +Method in class org.luaj.vm2.LuaValue +
Throw a LuaError based on the len operator, + typically due to an invalid operand type +
length() - +Method in class org.luaj.vm2.LuaString +
  +
length() - +Method in class org.luaj.vm2.LuaTable +
  +
length() - +Method in class org.luaj.vm2.LuaValue +
Length operator: return lua length of object (#this) including metatag processing as java int +
lengthAsUtf8(char[]) - +Static method in class org.luaj.vm2.LuaString +
Count the number of bytes required to encode the string as UTF-8. +
LFIELDS_PER_FLUSH - +Static variable in class org.luaj.vm2.Lua +
  +
LibFunction - Class in org.luaj.vm2.lib
Subclass of LuaFunction common to Java functions exposed to lua.
LibFunction() - +Constructor for class org.luaj.vm2.lib.LibFunction +
Default constructor for use by subclasses +
linedefined - +Variable in class org.luaj.vm2.Prototype +
  +
lineinfo - +Variable in class org.luaj.vm2.Prototype +
  +
listOf(LuaValue[]) - +Static method in class org.luaj.vm2.LuaValue +
Construct a LuaTable initialized with supplied array values. +
listOf(LuaValue[], Varargs) - +Static method in class org.luaj.vm2.LuaValue +
Construct a LuaTable initialized with supplied array values. +
load(InputStream, String, LuaValue) - +Method in class org.luaj.vm2.compiler.LuaC +
Load into a Closure or LuaFunction, with the supplied initial environment +
load(Prototype, String, LuaValue) - +Method in class org.luaj.vm2.compiler.LuaC +
  +
load(InputStream, String, LuaValue) - +Static method in class org.luaj.vm2.LoadState +
Load lua in either binary or text form from an input stream. +
load(InputStream, String, LuaValue) - +Method in interface org.luaj.vm2.LoadState.LuaCompiler +
Load into a Closure or LuaFunction from a Stream and initializes the environment +
load(InputStream, String, LuaValue) - +Method in class org.luaj.vm2.luajc.LuaJC +
  +
load(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Load a library instance by setting its environment to this + and calling it, which should iniitalize the library instance and + install itself into this instance. +
loadBinaryChunk(int, InputStream, String) - +Static method in class org.luaj.vm2.LoadState +
Load lua thought to be a binary chunk from its first byte from an input stream. +
LOADED - +Variable in class org.luaj.vm2.lib.PackageLib +
  +
loadFile(String) - +Static method in class org.luaj.vm2.lib.BaseLib +
Load from a named file, returning the chunk or nil,error of can't load +
loadFunction(LuaString) - +Method in class org.luaj.vm2.LoadState +
Load a function prototype from the input stream +
loadHeader() - +Method in class org.luaj.vm2.LoadState +
Load the lua chunk header values. +
loadlib(Varargs) - +Static method in class org.luaj.vm2.lib.PackageLib +
  +
LoadState - Class in org.luaj.vm2
Class to manage loading of Prototype instances.
LoadState.LuaCompiler - Interface in org.luaj.vm2
Interface for the compiler, if it is installed.
loadStream(InputStream, String) - +Static method in class org.luaj.vm2.lib.BaseLib +
  +
LocVars - Class in org.luaj.vm2
Data class to hold debug information relatign to local variables for a Prototype
LocVars(LuaString, int, int) - +Constructor for class org.luaj.vm2.LocVars +
Construct a LocVars instance. +
locvars - +Variable in class org.luaj.vm2.Prototype +
  +
longBitsToLuaNumber(long) - +Static method in class org.luaj.vm2.LoadState +
Convert bits in a long value to a LuaValue. +
lt(LuaValue) - +Method in class org.luaj.vm2.LuaDouble +
  +
lt(double) - +Method in class org.luaj.vm2.LuaDouble +
  +
lt(int) - +Method in class org.luaj.vm2.LuaDouble +
  +
lt(LuaValue) - +Method in class org.luaj.vm2.LuaInteger +
  +
lt(double) - +Method in class org.luaj.vm2.LuaInteger +
  +
lt(int) - +Method in class org.luaj.vm2.LuaInteger +
  +
lt(LuaValue) - +Method in class org.luaj.vm2.LuaString +
  +
LT - +Static variable in class org.luaj.vm2.LuaValue +
LuaString constant with value "__lt" for use as metatag +
lt(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Less than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue. +
lt(double) - +Method in class org.luaj.vm2.LuaValue +
Less than: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue. +
lt(int) - +Method in class org.luaj.vm2.LuaValue +
Less than: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue. +
lt_b(LuaValue) - +Method in class org.luaj.vm2.LuaDouble +
  +
lt_b(int) - +Method in class org.luaj.vm2.LuaDouble +
  +
lt_b(double) - +Method in class org.luaj.vm2.LuaDouble +
  +
lt_b(LuaValue) - +Method in class org.luaj.vm2.LuaInteger +
  +
lt_b(int) - +Method in class org.luaj.vm2.LuaInteger +
  +
lt_b(double) - +Method in class org.luaj.vm2.LuaInteger +
  +
lt_b(LuaValue) - +Method in class org.luaj.vm2.LuaString +
  +
lt_b(int) - +Method in class org.luaj.vm2.LuaString +
  +
lt_b(double) - +Method in class org.luaj.vm2.LuaString +
  +
lt_b(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Less than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +
lt_b(int) - +Method in class org.luaj.vm2.LuaValue +
Less than: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean. +
lt_b(double) - +Method in class org.luaj.vm2.LuaValue +
Less than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +
lteq(LuaValue) - +Method in class org.luaj.vm2.LuaDouble +
  +
lteq(double) - +Method in class org.luaj.vm2.LuaDouble +
  +
lteq(int) - +Method in class org.luaj.vm2.LuaDouble +
  +
lteq(LuaValue) - +Method in class org.luaj.vm2.LuaInteger +
  +
lteq(double) - +Method in class org.luaj.vm2.LuaInteger +
  +
lteq(int) - +Method in class org.luaj.vm2.LuaInteger +
  +
lteq(LuaValue) - +Method in class org.luaj.vm2.LuaString +
  +
lteq(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Less than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue. +
lteq(double) - +Method in class org.luaj.vm2.LuaValue +
Less than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue. +
lteq(int) - +Method in class org.luaj.vm2.LuaValue +
Less than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue. +
lteq_b(LuaValue) - +Method in class org.luaj.vm2.LuaDouble +
  +
lteq_b(int) - +Method in class org.luaj.vm2.LuaDouble +
  +
lteq_b(double) - +Method in class org.luaj.vm2.LuaDouble +
  +
lteq_b(LuaValue) - +Method in class org.luaj.vm2.LuaInteger +
  +
lteq_b(int) - +Method in class org.luaj.vm2.LuaInteger +
  +
lteq_b(double) - +Method in class org.luaj.vm2.LuaInteger +
  +
lteq_b(LuaValue) - +Method in class org.luaj.vm2.LuaString +
  +
lteq_b(int) - +Method in class org.luaj.vm2.LuaString +
  +
lteq_b(double) - +Method in class org.luaj.vm2.LuaString +
  +
lteq_b(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Less than or equals: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +
lteq_b(int) - +Method in class org.luaj.vm2.LuaValue +
Less than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean. +
lteq_b(double) - +Method in class org.luaj.vm2.LuaValue +
Less than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, + and returning java boolean. +
Lua - Class in org.luaj.vm2
Constants for lua limits and opcodes.
Lua() - +Constructor for class org.luaj.vm2.Lua +
  +
lua_loader - +Variable in class org.luaj.vm2.lib.PackageLib +
Loader that loads as a lua script using the LUA_PATH +
LUA_MULTRET - +Static variable in class org.luaj.vm2.Lua +
use return values from previous op +
LUA_TBOOLEAN - +Static variable in class org.luaj.vm2.LoadState +
  +
LUA_TFUNCTION - +Static variable in class org.luaj.vm2.LoadState +
  +
LUA_TINT - +Static variable in class org.luaj.vm2.LoadState +
  +
LUA_TLIGHTUSERDATA - +Static variable in class org.luaj.vm2.LoadState +
  +
LUA_TNIL - +Static variable in class org.luaj.vm2.LoadState +
  +
LUA_TNONE - +Static variable in class org.luaj.vm2.LoadState +
  +
LUA_TNUMBER - +Static variable in class org.luaj.vm2.LoadState +
  +
LUA_TSTRING - +Static variable in class org.luaj.vm2.LoadState +
  +
LUA_TTABLE - +Static variable in class org.luaj.vm2.LoadState +
  +
LUA_TTHREAD - +Static variable in class org.luaj.vm2.LoadState +
  +
LUA_TUSERDATA - +Static variable in class org.luaj.vm2.LoadState +
  +
LUA_TVALUE - +Static variable in class org.luaj.vm2.LoadState +
  +
LuaBoolean - Class in org.luaj.vm2
Extension of LuaValue which can hold a Java boolean as its value.
luaByte(int) - +Method in class org.luaj.vm2.LuaString +
  +
LuaC - Class in org.luaj.vm2.compiler
Compiler for Lua.
LuaC() - +Constructor for class org.luaj.vm2.compiler.LuaC +
  +
LUAC_FORMAT - +Static variable in class org.luaj.vm2.LoadState +
for header of binary files -- this is the official format +
LUAC_HEADERSIZE - +Static variable in class org.luaj.vm2.LoadState +
size of header of binary files +
LUAC_VERSION - +Static variable in class org.luaj.vm2.LoadState +
for header of binary files -- this is Lua 5.1 +
LuaClosure - Class in org.luaj.vm2
Extension of LuaFunction which executes lua bytecode.
LuaClosure(Prototype, LuaValue) - +Constructor for class org.luaj.vm2.LuaClosure +
Supply the initial environment +
LuaClosure(int, LuaValue) - +Constructor for class org.luaj.vm2.LuaClosure +
  +
LuaDouble - Class in org.luaj.vm2
Extension of LuaNumber which can hold a Java double as its value.
LuaError - Exception in org.luaj.vm2
RuntimeException that is thrown and caught in response to a lua error.
LuaError(Throwable) - +Constructor for exception org.luaj.vm2.LuaError +
Construct LuaError when a program exception occurs. +
LuaError(String) - +Constructor for exception org.luaj.vm2.LuaError +
Construct a LuaError with a specific message. +
LuaError(String, int) - +Constructor for exception org.luaj.vm2.LuaError +
Construct a LuaError with a message, and level to draw line number information from. +
LuaFunction - Class in org.luaj.vm2
Base class for functions implemented in Java.
LuaFunction() - +Constructor for class org.luaj.vm2.LuaFunction +
  +
LuaFunction(LuaValue) - +Constructor for class org.luaj.vm2.LuaFunction +
  +
LuaInteger - Class in org.luaj.vm2
Extension of LuaNumber which can hold a Java int as its value.
LuajavaLib - Class in org.luaj.vm2.lib.jse
Subclass of LibFunction which implements the features of the luajava package.
LuajavaLib() - +Constructor for class org.luaj.vm2.lib.jse.LuajavaLib +
  +
LuaJC - Class in org.luaj.vm2.luajc
Implementation of LoadState.LuaCompiler which does direct + lua-to-java-bytecode compiling.
LuaJC() - +Constructor for class org.luaj.vm2.luajc.LuaJC +
  +
LuaNil - Class in org.luaj.vm2
Class to encapsulate behavior of the singleton instance nil
LuaNumber - Class in org.luaj.vm2
Base class for representing numbers as lua values directly.
LuaNumber() - +Constructor for class org.luaj.vm2.LuaNumber +
  +
luaP_opmodes - +Static variable in class org.luaj.vm2.Lua +
  +
LuaString - Class in org.luaj.vm2
Subclass of LuaValue for representing lua strings.
LuaTable - Class in org.luaj.vm2
Subclass of LuaValue for representing lua tables.
LuaTable() - +Constructor for class org.luaj.vm2.LuaTable +
Construct empty table +
LuaTable(int, int) - +Constructor for class org.luaj.vm2.LuaTable +
Construct table with preset capacity. +
LuaTable(LuaValue[], LuaValue[], Varargs) - +Constructor for class org.luaj.vm2.LuaTable +
Construct table with named and unnamed parts. +
LuaTable(Varargs) - +Constructor for class org.luaj.vm2.LuaTable +
Construct table of unnamed elements. +
LuaTable(Varargs, int) - +Constructor for class org.luaj.vm2.LuaTable +
Construct table of unnamed elements. +
LuaThread - Class in org.luaj.vm2
Subclass of LuaValue that implements + a lua coroutine thread using Java Threads.
LuaThread(LuaValue, LuaValue) - +Constructor for class org.luaj.vm2.LuaThread +
Create a LuaThread around a function and environment +
LuaThread.CallStack - Class in org.luaj.vm2
 
LuaThread.CallStack() - +Constructor for class org.luaj.vm2.LuaThread.CallStack +
  +
LuaUserdata - Class in org.luaj.vm2
 
LuaUserdata(Object) - +Constructor for class org.luaj.vm2.LuaUserdata +
  +
LuaUserdata(Object, LuaValue) - +Constructor for class org.luaj.vm2.LuaUserdata +
  +
LuaValue - Class in org.luaj.vm2
Base class for all concrete lua type values.
LuaValue() - +Constructor for class org.luaj.vm2.LuaValue +
  +
+
+

+M

+
+
m_bytes - +Variable in class org.luaj.vm2.LuaString +
The bytes for the string +
m_instance - +Variable in class org.luaj.vm2.LuaUserdata +
  +
m_length - +Variable in class org.luaj.vm2.LuaString +
The number of bytes that comprise this string +
m_metatable - +Variable in class org.luaj.vm2.LuaTable +
metatable for this table, or null +
m_metatable - +Variable in class org.luaj.vm2.LuaUserdata +
  +
m_offset - +Variable in class org.luaj.vm2.LuaString +
The offset into the byte array, 0 means start at the first byte +
makeroom(int, int) - +Method in class org.luaj.vm2.Buffer +
Ensure there is enough room before and after the bytes. +
MASK_A - +Static variable in class org.luaj.vm2.Lua +
  +
MASK_B - +Static variable in class org.luaj.vm2.Lua +
  +
MASK_Bx - +Static variable in class org.luaj.vm2.Lua +
  +
MASK_C - +Static variable in class org.luaj.vm2.Lua +
  +
MASK_NOT_A - +Static variable in class org.luaj.vm2.Lua +
  +
MASK_NOT_B - +Static variable in class org.luaj.vm2.Lua +
  +
MASK_NOT_Bx - +Static variable in class org.luaj.vm2.Lua +
  +
MASK_NOT_C - +Static variable in class org.luaj.vm2.Lua +
  +
MASK_NOT_OP - +Static variable in class org.luaj.vm2.Lua +
  +
MASK_OP - +Static variable in class org.luaj.vm2.Lua +
  +
MathLib - Class in org.luaj.vm2.lib
Subclass of LibFunction which implements the lua standard math + library.
MathLib() - +Constructor for class org.luaj.vm2.lib.MathLib +
  +
MATHLIB - +Static variable in class org.luaj.vm2.lib.MathLib +
  +
MAX_CALLSTACK - +Static variable in class org.luaj.vm2.LuaThread +
  +
MAX_OP - +Static variable in class org.luaj.vm2.Lua +
  +
MAXARG_A - +Static variable in class org.luaj.vm2.Lua +
  +
MAXARG_B - +Static variable in class org.luaj.vm2.Lua +
  +
MAXARG_Bx - +Static variable in class org.luaj.vm2.Lua +
  +
MAXARG_C - +Static variable in class org.luaj.vm2.Lua +
  +
MAXARG_sBx - +Static variable in class org.luaj.vm2.Lua +
  +
MAXINDEXRK - +Static variable in class org.luaj.vm2.Lua +
  +
maxn() - +Method in class org.luaj.vm2.LuaTable +
Return table.maxn() as defined by lua 5.0. +
maxn() - +Method in class org.luaj.vm2.WeakTable +
  +
MAXSTACK - +Static variable in class org.luaj.vm2.compiler.LuaC +
  +
maxstacksize - +Variable in class org.luaj.vm2.Prototype +
  +
METATABLE - +Static variable in class org.luaj.vm2.LuaValue +
LuaString constant with value "__metatable" for use as metatag +
metatag(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Get particular metatag, or return LuaValue.NIL if it doesn't exist +
method(String) - +Method in class org.luaj.vm2.LuaValue +
Call named method on this with 0 arguments, including metatag processing, + and return only the first return value. +
method(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Call named method on this with 0 arguments, including metatag processing, + and return only the first return value. +
method(String, LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Call named method on this with 1 argument, including metatag processing, + and return only the first return value. +
method(LuaValue, LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Call named method on this with 1 argument, including metatag processing, + and return only the first return value. +
method(String, LuaValue, LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Call named method on this with 2 arguments, including metatag processing, + and return only the first return value. +
method(LuaValue, LuaValue, LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Call named method on this with 2 arguments, including metatag processing, + and return only the first return value. +
MINUSONE - +Static variable in class org.luaj.vm2.LuaValue +
LuaValue number constant equal to -1 +
mod(LuaValue) - +Method in class org.luaj.vm2.LuaDouble +
  +
mod(double) - +Method in class org.luaj.vm2.LuaDouble +
  +
mod(int) - +Method in class org.luaj.vm2.LuaDouble +
  +
mod(LuaValue) - +Method in class org.luaj.vm2.LuaInteger +
  +
mod(double) - +Method in class org.luaj.vm2.LuaInteger +
  +
mod(int) - +Method in class org.luaj.vm2.LuaInteger +
  +
mod(LuaValue) - +Method in class org.luaj.vm2.LuaString +
  +
mod(double) - +Method in class org.luaj.vm2.LuaString +
  +
mod(int) - +Method in class org.luaj.vm2.LuaString +
  +
MOD - +Static variable in class org.luaj.vm2.LuaValue +
LuaString constant with value "__mod" for use as metatag +
mod(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Modulo: Perform numeric modulo operation with another value + of unknown type, + including metatag processing. +
mod(double) - +Method in class org.luaj.vm2.LuaValue +
Modulo: Perform numeric modulo operation with another value + of double type without metatag processing +
mod(int) - +Method in class org.luaj.vm2.LuaValue +
Modulo: Perform numeric modulo operation with another value + of int type without metatag processing +
MODE - +Static variable in class org.luaj.vm2.LuaValue +
LuaString constant with value "__mode" for use as metatag +
modFrom(double) - +Method in class org.luaj.vm2.LuaDouble +
  +
modFrom(double) - +Method in class org.luaj.vm2.LuaInteger +
  +
modFrom(double) - +Method in class org.luaj.vm2.LuaString +
  +
modFrom(double) - +Method in class org.luaj.vm2.LuaValue +
Reverse-modulo: Perform numeric modulo operation from another value + with metatag processing +
module(Varargs) - +Method in class org.luaj.vm2.lib.PackageLib +
module (name [, ...]) + + Creates a module. +
mul(LuaValue) - +Method in class org.luaj.vm2.LuaDouble +
  +
mul(double) - +Method in class org.luaj.vm2.LuaDouble +
  +
mul(int) - +Method in class org.luaj.vm2.LuaDouble +
  +
mul(LuaValue) - +Method in class org.luaj.vm2.LuaInteger +
  +
mul(double) - +Method in class org.luaj.vm2.LuaInteger +
  +
mul(int) - +Method in class org.luaj.vm2.LuaInteger +
  +
mul(LuaValue) - +Method in class org.luaj.vm2.LuaString +
  +
mul(double) - +Method in class org.luaj.vm2.LuaString +
  +
mul(int) - +Method in class org.luaj.vm2.LuaString +
  +
MUL - +Static variable in class org.luaj.vm2.LuaValue +
LuaString constant with value "__mul" for use as metatag +
mul(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Multiply: Perform numeric multiply operation with another value + of unknown type, + including metatag processing. +
mul(double) - +Method in class org.luaj.vm2.LuaValue +
Multiply: Perform numeric multiply operation with another value + of double type with metatag processing +
mul(int) - +Method in class org.luaj.vm2.LuaValue +
Multiply: Perform numeric multiply operation with another value + of int type with metatag processing +
+
+

+N

+
+
name - +Variable in class org.luaj.vm2.lib.LibFunction +
The common name for this function, useful for debugging. +
NAN - +Static variable in class org.luaj.vm2.LuaDouble +
Constant LuaDouble representing NaN (not a number) +
narg() - +Method in class org.luaj.vm2.LuaValue +
  +
narg() - +Method in class org.luaj.vm2.TailcallVarargs +
  +
narg() - +Method in class org.luaj.vm2.Varargs +
Get the number of arguments, or 0 if there are none. +
nCcalls - +Variable in class org.luaj.vm2.compiler.LuaC +
  +
neg() - +Method in class org.luaj.vm2.LuaDouble +
  +
neg() - +Method in class org.luaj.vm2.LuaInteger +
  +
neg() - +Method in class org.luaj.vm2.LuaString +
  +
neg() - +Method in class org.luaj.vm2.LuaValue +
Unary minus: return negative value (-this) as defined by lua unary minus operator +
NEGINF - +Static variable in class org.luaj.vm2.LuaDouble +
Constant LuaDouble representing negative infinity +
neq(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Notquals: Perform inequality comparison with another value + including metatag processing using EQ. +
neq_b(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Notquals: Perform inequality comparison with another value + including metatag processing using EQ. +
NEWINDEX - +Static variable in class org.luaj.vm2.LuaValue +
LuaString constant with value "__newindex" for use as metatag +
newTString(byte[], int, int) - +Method in class org.luaj.vm2.compiler.LuaC +
  +
newupe() - +Static method in class org.luaj.vm2.lib.LibFunction +
Java code generation utility to allocate storage for upvalue, leave it empty +
newupl(LuaValue) - +Static method in class org.luaj.vm2.lib.LibFunction +
Java code generation utility to allocate storage for upvalue, initialize with value +
newupn() - +Static method in class org.luaj.vm2.lib.LibFunction +
Java code generation utility to allocate storage for upvalue, initialize with nil +
next(LuaValue) - +Method in class org.luaj.vm2.LuaTable +
Get the next element after a particular key in the table +
next(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Find the next key,value pair if this is a table, + return NIL if there are no more, or throw a LuaError if not a table. +
next(LuaValue) - +Method in class org.luaj.vm2.WeakTable +
Get the next element after a particular key in the table +
NIL - +Static variable in class org.luaj.vm2.LuaValue +
LuaValue constant corresponding to lua nil +
NILS - +Static variable in class org.luaj.vm2.LuaValue +
Array of NIL values to optimize filling stacks using System.arraycopy(). +
NO_REG - +Static variable in class org.luaj.vm2.Lua +
invalid register that fits in 8 bits +
NONE - +Static variable in class org.luaj.vm2.LuaValue +
LuaValue constant corresponding to a Varargs list of no values +
not() - +Method in class org.luaj.vm2.LuaBoolean +
  +
not() - +Method in class org.luaj.vm2.LuaNil +
  +
not() - +Method in class org.luaj.vm2.LuaValue +
Unary not: return inverse boolean value (~this) as defined by lua not operator +
NOVALS - +Static variable in class org.luaj.vm2.LuaValue +
LuaValue array constant with no values +
NUM_OPCODES - +Static variable in class org.luaj.vm2.Lua +
  +
NUMBER_FORMAT_FLOATS_OR_DOUBLES - +Static variable in class org.luaj.vm2.LoadState +
format corresponding to non-number-patched lua, all numbers are floats or doubles +
NUMBER_FORMAT_INTS_ONLY - +Static variable in class org.luaj.vm2.LoadState +
format corresponding to non-number-patched lua, all numbers are ints +
NUMBER_FORMAT_NUM_PATCH_INT32 - +Static variable in class org.luaj.vm2.LoadState +
format corresponding to number-patched lua, all numbers are 32-bit (4 byte) ints +
numparams - +Variable in class org.luaj.vm2.Prototype +
  +
nups - +Variable in class org.luaj.vm2.Prototype +
  +
+
+

+O

+
+
onCall(LuaFunction) - +Static method in class org.luaj.vm2.LuaThread +
Callback used at the beginning of a call to prepare for possible getfenv/setfenv calls +
ONE - +Static variable in class org.luaj.vm2.LuaValue +
LuaValue number constant equal to 1 +
OneArgFunction - Class in org.luaj.vm2.lib
Abstract base class for Java function implementations that take one argument and + return one value.
OneArgFunction() - +Constructor for class org.luaj.vm2.lib.OneArgFunction +
Default constructor +
OneArgFunction(LuaValue) - +Constructor for class org.luaj.vm2.lib.OneArgFunction +
Constructor with specific environment +
onInvoke(Varargs) - +Method in class org.luaj.vm2.lib.VarArgFunction +
Override to provide a call implementation that runs in an environment + that can participate in setfenv, and behaves as expected + when returning TailcallVarargs. +
onInvoke(Varargs) - +Method in class org.luaj.vm2.LuaClosure +
  +
onInvoke(Varargs) - +Method in class org.luaj.vm2.LuaValue +
Callback used during tail call processing to invoke the function once. +
onReturn() - +Method in class org.luaj.vm2.LuaThread.CallStack +
Method to signal the end of a call +
OP_ADD - +Static variable in class org.luaj.vm2.Lua +
  +
OP_AND - +Static variable in class org.luaj.vm2.Lua +
  +
OP_CALL - +Static variable in class org.luaj.vm2.Lua +
  +
OP_CLOSE - +Static variable in class org.luaj.vm2.Lua +
  +
OP_CLOSURE - +Static variable in class org.luaj.vm2.Lua +
  +
OP_CONCAT - +Static variable in class org.luaj.vm2.Lua +
  +
OP_DIV - +Static variable in class org.luaj.vm2.Lua +
  +
OP_EQ - +Static variable in class org.luaj.vm2.Lua +
  +
OP_FORLOOP - +Static variable in class org.luaj.vm2.Lua +
  +
OP_FORPREP - +Static variable in class org.luaj.vm2.Lua +
  +
OP_GE - +Static variable in class org.luaj.vm2.Lua +
  +
OP_GETGLOBAL - +Static variable in class org.luaj.vm2.Lua +
  +
OP_GETTABLE - +Static variable in class org.luaj.vm2.Lua +
  +
OP_GETUPVAL - +Static variable in class org.luaj.vm2.Lua +
  +
OP_GT - +Static variable in class org.luaj.vm2.Lua +
  +
OP_JMP - +Static variable in class org.luaj.vm2.Lua +
  +
OP_LE - +Static variable in class org.luaj.vm2.Lua +
  +
OP_LEN - +Static variable in class org.luaj.vm2.Lua +
  +
OP_LOADBOOL - +Static variable in class org.luaj.vm2.Lua +
  +
OP_LOADK - +Static variable in class org.luaj.vm2.Lua +
  +
OP_LOADNIL - +Static variable in class org.luaj.vm2.Lua +
  +
OP_LT - +Static variable in class org.luaj.vm2.Lua +
  +
OP_MOD - +Static variable in class org.luaj.vm2.Lua +
  +
OP_MOVE - +Static variable in class org.luaj.vm2.Lua +
  +
OP_MUL - +Static variable in class org.luaj.vm2.Lua +
  +
OP_NEQ - +Static variable in class org.luaj.vm2.Lua +
  +
OP_NEWTABLE - +Static variable in class org.luaj.vm2.Lua +
  +
OP_NOT - +Static variable in class org.luaj.vm2.Lua +
  +
OP_OR - +Static variable in class org.luaj.vm2.Lua +
  +
OP_POW - +Static variable in class org.luaj.vm2.Lua +
  +
OP_RETURN - +Static variable in class org.luaj.vm2.Lua +
  +
OP_SELF - +Static variable in class org.luaj.vm2.Lua +
  +
OP_SETGLOBAL - +Static variable in class org.luaj.vm2.Lua +
  +
OP_SETLIST - +Static variable in class org.luaj.vm2.Lua +
  +
OP_SETTABLE - +Static variable in class org.luaj.vm2.Lua +
  +
OP_SETUPVAL - +Static variable in class org.luaj.vm2.Lua +
  +
OP_SUB - +Static variable in class org.luaj.vm2.Lua +
  +
OP_TAILCALL - +Static variable in class org.luaj.vm2.Lua +
  +
OP_TEST - +Static variable in class org.luaj.vm2.Lua +
  +
OP_TESTSET - +Static variable in class org.luaj.vm2.Lua +
  +
OP_TFORLOOP - +Static variable in class org.luaj.vm2.Lua +
  +
OP_UNM - +Static variable in class org.luaj.vm2.Lua +
  +
OP_VARARG - +Static variable in class org.luaj.vm2.Lua +
  +
OpArgK - +Static variable in class org.luaj.vm2.Lua +
  +
OpArgN - +Static variable in class org.luaj.vm2.Lua +
  +
OpArgR - +Static variable in class org.luaj.vm2.Lua +
  +
OpArgU - +Static variable in class org.luaj.vm2.Lua +
  +
opcode - +Variable in class org.luaj.vm2.lib.LibFunction +
User-defined opcode to differentiate between instances of the library function class. +
openFile(String, boolean, boolean, boolean, boolean) - +Method in class org.luaj.vm2.lib.IoLib +
Open a file in a particular mode. +
openFile(String, boolean, boolean, boolean, boolean) - +Method in class org.luaj.vm2.lib.jme.JmeIoLib +
  +
openFile(String, boolean, boolean, boolean, boolean) - +Method in class org.luaj.vm2.lib.jse.JseIoLib +
  +
openProgram(String, String) - +Method in class org.luaj.vm2.lib.IoLib +
Start a new process and return a file for input or output +
openProgram(String, String) - +Method in class org.luaj.vm2.lib.jme.JmeIoLib +
  +
openProgram(String, String) - +Method in class org.luaj.vm2.lib.jse.JseIoLib +
  +
OPNAMES - +Static variable in class org.luaj.vm2.Print +
  +
optboolean(boolean) - +Method in class org.luaj.vm2.LuaBoolean +
  +
optboolean(boolean) - +Method in class org.luaj.vm2.LuaNil +
  +
optboolean(boolean) - +Method in class org.luaj.vm2.LuaValue +
Check that optional argument is a boolean and return its boolean value +
optboolean(int, boolean) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a boolean value, defval if nil, or throw a LuaError if any other type. +
optclosure(LuaClosure) - +Method in class org.luaj.vm2.LuaClosure +
  +
optclosure(LuaClosure) - +Method in class org.luaj.vm2.LuaNil +
  +
optclosure(LuaClosure) - +Method in class org.luaj.vm2.LuaValue +
Check that optional argument is a closure and return as LuaClosure +
optclosure(int, LuaClosure) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a closure, defval if nil, or throw a LuaError if any other type. +
optdouble(double) - +Method in class org.luaj.vm2.LuaDouble +
  +
optdouble(double) - +Method in class org.luaj.vm2.LuaInteger +
  +
optdouble(double) - +Method in class org.luaj.vm2.LuaNil +
  +
optdouble(double) - +Method in class org.luaj.vm2.LuaString +
  +
optdouble(double) - +Method in class org.luaj.vm2.LuaValue +
Check that optional argument is a number or string convertible to number and return as double +
optdouble(int, double) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a double, defval if nil, or throw a LuaError if it cannot be converted to one. +
optfunction(LuaFunction) - +Method in class org.luaj.vm2.LuaFunction +
  +
optfunction(LuaFunction) - +Method in class org.luaj.vm2.LuaNil +
  +
optfunction(LuaFunction) - +Method in class org.luaj.vm2.LuaValue +
Check that optional argument is a function and return as LuaFunction +
optfunction(int, LuaFunction) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a function, defval if nil, or throw a LuaError if an incompatible type. +
optint(int) - +Method in class org.luaj.vm2.LuaDouble +
  +
optint(int) - +Method in class org.luaj.vm2.LuaInteger +
  +
optint(int) - +Method in class org.luaj.vm2.LuaNil +
  +
optint(int) - +Method in class org.luaj.vm2.LuaString +
  +
optint(int) - +Method in class org.luaj.vm2.LuaValue +
Check that optional argument is a number or string convertible to number and return as int +
optint(int, int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java int value, discarding any fractional part, defval if nil, or throw a LuaError if not a number. +
optinteger(LuaInteger) - +Method in class org.luaj.vm2.LuaDouble +
  +
optinteger(LuaInteger) - +Method in class org.luaj.vm2.LuaInteger +
  +
optinteger(LuaInteger) - +Method in class org.luaj.vm2.LuaNil +
  +
optinteger(LuaInteger) - +Method in class org.luaj.vm2.LuaString +
  +
optinteger(LuaInteger) - +Method in class org.luaj.vm2.LuaValue +
Check that optional argument is a number or string convertible to number and return as LuaInteger +
optinteger(int, LuaInteger) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java int value, defval if nil, or throw a LuaError if not a number or is not representable by a java int. +
optjstring(String) - +Method in class org.luaj.vm2.LuaDouble +
  +
optjstring(String) - +Method in class org.luaj.vm2.LuaInteger +
  +
optjstring(String) - +Method in class org.luaj.vm2.LuaNil +
  +
optjstring(String) - +Method in class org.luaj.vm2.LuaString +
  +
optjstring(String) - +Method in class org.luaj.vm2.LuaValue +
Check that optional argument is a string or number and return as Java String +
optjstring(int, String) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java String if a string or number, defval if nil, or throw a LuaError if any other type +
optlong(long) - +Method in class org.luaj.vm2.LuaDouble +
  +
optlong(long) - +Method in class org.luaj.vm2.LuaInteger +
  +
optlong(long) - +Method in class org.luaj.vm2.LuaNil +
  +
optlong(long) - +Method in class org.luaj.vm2.LuaString +
  +
optlong(long) - +Method in class org.luaj.vm2.LuaValue +
Check that optional argument is a number or string convertible to number and return as long +
optlong(int, long) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java long value, discarding any fractional part, defval if nil, or throw a LuaError if not a number. +
optnumber(LuaNumber) - +Method in class org.luaj.vm2.LuaDouble +
  +
optnumber(LuaNumber) - +Method in class org.luaj.vm2.LuaNil +
  +
optnumber(LuaNumber) - +Method in class org.luaj.vm2.LuaNumber +
  +
optnumber(LuaNumber) - +Method in class org.luaj.vm2.LuaString +
  +
optnumber(LuaNumber) - +Method in class org.luaj.vm2.LuaValue +
Check that optional argument is a number or string convertible to number and return as LuaNumber +
optnumber(int, LuaNumber) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a LuaNumber, defval if nil, or throw a LuaError if not a number or string that can be converted to a number. +
optstring(LuaString) - +Method in class org.luaj.vm2.LuaDouble +
  +
optstring(LuaString) - +Method in class org.luaj.vm2.LuaInteger +
  +
optstring(LuaString) - +Method in class org.luaj.vm2.LuaNil +
  +
optstring(LuaString) - +Method in class org.luaj.vm2.LuaString +
  +
optstring(LuaString) - +Method in class org.luaj.vm2.LuaValue +
Check that optional argument is a string or number and return as LuaString +
optstring(int, LuaString) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a LuaString if a string or number, defval if nil, or throw a LuaError if any other type +
opttable(LuaTable) - +Method in class org.luaj.vm2.LuaNil +
  +
opttable(LuaTable) - +Method in class org.luaj.vm2.LuaTable +
  +
opttable(LuaTable) - +Method in class org.luaj.vm2.LuaValue +
Check that optional argument is a table and return as LuaTable +
opttable(int, LuaTable) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a LuaTable if a lua table, defval if nil, or throw a LuaError if any other type. +
optthread(LuaThread) - +Method in class org.luaj.vm2.LuaNil +
  +
optthread(LuaThread) - +Method in class org.luaj.vm2.LuaThread +
  +
optthread(LuaThread) - +Method in class org.luaj.vm2.LuaValue +
Check that optional argument is a thread and return as LuaThread +
optthread(int, LuaThread) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a LuaThread if a lua thread, defval if nil, or throw a LuaError if any other type. +
optuserdata(Object) - +Method in class org.luaj.vm2.LuaNil +
  +
optuserdata(Class, Object) - +Method in class org.luaj.vm2.LuaNil +
  +
optuserdata(Object) - +Method in class org.luaj.vm2.LuaUserdata +
  +
optuserdata(Class, Object) - +Method in class org.luaj.vm2.LuaUserdata +
  +
optuserdata(Object) - +Method in class org.luaj.vm2.LuaValue +
Check that optional argument is a userdata and return the Object instance +
optuserdata(Class, Object) - +Method in class org.luaj.vm2.LuaValue +
Check that optional argument is a userdata whose instance is of a type + and return the Object instance +
optuserdata(int, Object) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java Object if a userdata, defval if nil, or throw a LuaError if any other type. +
optuserdata(int, Class, Object) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java Object if it is a userdata whose instance Class c or a subclass, + defval if nil, or throw a LuaError if any other type. +
optvalue(LuaValue) - +Method in class org.luaj.vm2.LuaNil +
  +
optvalue(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Perform argument check that this is not nil or none. +
optvalue(int, LuaValue) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a LuaValue if it exists, or defval. +
or(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Perform boolean or with another operand, based on lua rules for boolean evaluation. +
org.luaj.vm2 - package org.luaj.vm2
 
org.luaj.vm2.compiler - package org.luaj.vm2.compiler
 
org.luaj.vm2.lib - package org.luaj.vm2.lib
 
org.luaj.vm2.lib.jme - package org.luaj.vm2.lib.jme
 
org.luaj.vm2.lib.jse - package org.luaj.vm2.lib.jse
 
org.luaj.vm2.luajc - package org.luaj.vm2.luajc
 
OrphanedThread - Error in org.luaj.vm2
Error sublcass that indicates a lua thread that is no + longer referenced has been detected.
OrphanedThread() - +Constructor for error org.luaj.vm2.OrphanedThread +
  +
OsLib - Class in org.luaj.vm2.lib
Subclass of LibFunction which implements the standard lua os library.
OsLib() - +Constructor for class org.luaj.vm2.lib.OsLib +
Create and OsLib instance. +
+
+

+P

+
+
p - +Variable in class org.luaj.vm2.LuaClosure +
  +
p - +Variable in class org.luaj.vm2.Prototype +
  +
PACKAGE - +Variable in class org.luaj.vm2.lib.PackageLib +
  +
PackageLib - Class in org.luaj.vm2.lib
Subclass of LibFunction which implements the lua standard package and module + library functions.
PackageLib() - +Constructor for class org.luaj.vm2.lib.PackageLib +
  +
pcall(LuaValue, Varargs, LuaValue) - +Static method in class org.luaj.vm2.lib.BaseLib +
  +
peek() - +Method in class org.luaj.vm2.lib.IoLib.File +
  +
POS_A - +Static variable in class org.luaj.vm2.Lua +
  +
POS_B - +Static variable in class org.luaj.vm2.Lua +
  +
POS_Bx - +Static variable in class org.luaj.vm2.Lua +
  +
POS_C - +Static variable in class org.luaj.vm2.Lua +
  +
POS_OP - +Static variable in class org.luaj.vm2.Lua +
  +
POSINF - +Static variable in class org.luaj.vm2.LuaDouble +
Constant LuaDouble representing positive infinity +
pow(LuaValue) - +Method in class org.luaj.vm2.LuaDouble +
  +
pow(double) - +Method in class org.luaj.vm2.LuaDouble +
  +
pow(int) - +Method in class org.luaj.vm2.LuaDouble +
  +
pow(LuaValue) - +Method in class org.luaj.vm2.LuaInteger +
  +
pow(double) - +Method in class org.luaj.vm2.LuaInteger +
  +
pow(int) - +Method in class org.luaj.vm2.LuaInteger +
  +
pow(LuaValue) - +Method in class org.luaj.vm2.LuaString +
  +
pow(double) - +Method in class org.luaj.vm2.LuaString +
  +
pow(int) - +Method in class org.luaj.vm2.LuaString +
  +
POW - +Static variable in class org.luaj.vm2.LuaValue +
LuaString constant with value "__pow" for use as metatag +
pow(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Raise to power: Raise this value to a power + including metatag processing. +
pow(double) - +Method in class org.luaj.vm2.LuaValue +
Raise to power: Raise this value to a power + of double type with metatag processing +
pow(int) - +Method in class org.luaj.vm2.LuaValue +
Raise to power: Raise this value to a power + of int type with metatag processing +
powWith(double) - +Method in class org.luaj.vm2.LuaDouble +
  +
powWith(int) - +Method in class org.luaj.vm2.LuaDouble +
  +
powWith(double) - +Method in class org.luaj.vm2.LuaInteger +
  +
powWith(int) - +Method in class org.luaj.vm2.LuaInteger +
  +
powWith(double) - +Method in class org.luaj.vm2.LuaString +
  +
powWith(int) - +Method in class org.luaj.vm2.LuaString +
  +
powWith(double) - +Method in class org.luaj.vm2.LuaValue +
Reverse-raise to power: Raise another value of double type to this power + with metatag processing +
powWith(int) - +Method in class org.luaj.vm2.LuaValue +
Reverse-raise to power: Raise another value of double type to this power + with metatag processing +
preload_loader - +Variable in class org.luaj.vm2.lib.PackageLib +
Loader that loads from preload table if found there +
prepend(LuaString) - +Method in class org.luaj.vm2.Buffer +
Concatenate bytes from a LuaString onto the front of this buffer +
presize(int) - +Method in class org.luaj.vm2.LuaTable +
  +
presize(int, int) - +Method in class org.luaj.vm2.LuaTable +
  +
presize(int) - +Method in class org.luaj.vm2.LuaValue +
Preallocate the array part of a table to be a certain size, +
presize(int) - +Method in class org.luaj.vm2.WeakTable +
  +
presize(int, int) - +Method in class org.luaj.vm2.WeakTable +
Presize capacity of both array and hash parts. +
Print - Class in org.luaj.vm2
Debug helper class to pretty-print lua bytecodes.
Print() - +Constructor for class org.luaj.vm2.Print +
  +
print(Prototype) - +Static method in class org.luaj.vm2.Print +
  +
printCode(Prototype) - +Static method in class org.luaj.vm2.Print +
Print the code in a prototype +
printFunction(Prototype, boolean) - +Static method in class org.luaj.vm2.Print +
  +
printOpCode(Prototype, int) - +Static method in class org.luaj.vm2.Print +
Print an opcode in a prototype +
printOpCode(PrintStream, Prototype, int) - +Static method in class org.luaj.vm2.Print +
Print an opcode in a prototype +
printStackTrace() - +Method in exception org.luaj.vm2.LuaError +
Print the message and stack trace +
printState(LuaClosure, int, LuaValue[], int, Varargs) - +Static method in class org.luaj.vm2.Print +
Print the state of a LuaClosure that is being executed +
Prototype - Class in org.luaj.vm2
Prototype representing compiled lua code.
Prototype() - +Constructor for class org.luaj.vm2.Prototype +
  +
ps - +Static variable in class org.luaj.vm2.Print +
  +
pushfstring(String) - +Method in class org.luaj.vm2.compiler.LuaC +
  +
+
+

+R

+
+
raweq(LuaValue) - +Method in class org.luaj.vm2.LuaDouble +
  +
raweq(double) - +Method in class org.luaj.vm2.LuaDouble +
  +
raweq(int) - +Method in class org.luaj.vm2.LuaDouble +
  +
raweq(LuaValue) - +Method in class org.luaj.vm2.LuaInteger +
  +
raweq(double) - +Method in class org.luaj.vm2.LuaInteger +
  +
raweq(int) - +Method in class org.luaj.vm2.LuaInteger +
  +
raweq(LuaValue) - +Method in class org.luaj.vm2.LuaString +
  +
raweq(LuaString) - +Method in class org.luaj.vm2.LuaString +
  +
raweq(LuaValue) - +Method in class org.luaj.vm2.LuaUserdata +
  +
raweq(LuaUserdata) - +Method in class org.luaj.vm2.LuaUserdata +
  +
raweq(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Equals: Perform direct equality comparison with another value + without metatag processing. +
raweq(LuaUserdata) - +Method in class org.luaj.vm2.LuaValue +
Equals: Perform direct equality comparison with a LuaUserdata value + without metatag processing. +
raweq(LuaString) - +Method in class org.luaj.vm2.LuaValue +
Equals: Perform direct equality comparison with a LuaString value + without metatag processing. +
raweq(double) - +Method in class org.luaj.vm2.LuaValue +
Equals: Perform direct equality comparison with a double value + without metatag processing. +
raweq(int) - +Method in class org.luaj.vm2.LuaValue +
Equals: Perform direct equality comparison with a int value + without metatag processing. +
rawget(int) - +Method in class org.luaj.vm2.LuaTable +
  +
rawget(LuaValue) - +Method in class org.luaj.vm2.LuaTable +
  +
rawget(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Get a value in a table without metatag processing. +
rawget(int) - +Method in class org.luaj.vm2.LuaValue +
Get a value in a table without metatag processing. +
rawget(String) - +Method in class org.luaj.vm2.LuaValue +
Get a value in a table without metatag processing. +
rawget(int) - +Method in class org.luaj.vm2.WeakTable +
  +
rawget(LuaValue) - +Method in class org.luaj.vm2.WeakTable +
  +
rawset(int, LuaValue) - +Method in class org.luaj.vm2.LuaTable +
  +
rawset(LuaValue, LuaValue) - +Method in class org.luaj.vm2.LuaTable +
caller must ensure key is not nil +
rawset(LuaValue, LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Set a value in a table without metatag processing. +
rawset(int, LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Set a value in a table without metatag processing. +
rawset(int, String) - +Method in class org.luaj.vm2.LuaValue +
Set a value in a table without metatag processing. +
rawset(String, LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Set a value in a table without metatag processing. +
rawset(String, double) - +Method in class org.luaj.vm2.LuaValue +
Set a value in a table without metatag processing. +
rawset(String, int) - +Method in class org.luaj.vm2.LuaValue +
Set a value in a table without metatag processing. +
rawset(String, String) - +Method in class org.luaj.vm2.LuaValue +
Set a value in a table without metatag processing. +
rawset(int, LuaValue) - +Method in class org.luaj.vm2.WeakTable +
  +
rawset(LuaValue, LuaValue) - +Method in class org.luaj.vm2.WeakTable +
  +
rawsetlist(int, Varargs) - +Method in class org.luaj.vm2.LuaValue +
Set list values in a table without invoking metatag processing +
read() - +Method in class org.luaj.vm2.lib.IoLib.File +
  +
read(byte[], int, int) - +Method in class org.luaj.vm2.lib.IoLib.File +
  +
remaining() - +Method in class org.luaj.vm2.lib.IoLib.File +
  +
remove(String) - +Method in class org.luaj.vm2.lib.jse.JseOsLib +
  +
remove(String) - +Method in class org.luaj.vm2.lib.OsLib +
Deletes the file or directory with the given name. +
remove(int) - +Method in class org.luaj.vm2.LuaTable +
Remove the element at a position in a list-table +
rename(String, String) - +Method in class org.luaj.vm2.lib.jse.JseOsLib +
  +
rename(String, String) - +Method in class org.luaj.vm2.lib.OsLib +
Renames file or directory named oldname to newname. +
require(LuaValue) - +Method in class org.luaj.vm2.lib.PackageLib +
require (modname) + + Loads the given module. +
ResourceFinder - Interface in org.luaj.vm2.lib
Interface for opening application resource files such as scripts sources.
resume(Varargs) - +Method in class org.luaj.vm2.LuaThread +
Start or resume this thread +
RKASK(int) - +Static method in class org.luaj.vm2.Lua +
code a constant index as a RK value +
+
+

+S

+
+
s_metatable - +Static variable in class org.luaj.vm2.LuaBoolean +
Shared static metatable for boolean values represented in lua. +
s_metatable - +Static variable in class org.luaj.vm2.LuaFunction +
Shared static metatable for all functions and closures. +
s_metatable - +Static variable in class org.luaj.vm2.LuaNil +
  +
s_metatable - +Static variable in class org.luaj.vm2.LuaNumber +
Shared static metatable for all number values represented in lua. +
s_metatable - +Static variable in class org.luaj.vm2.LuaString +
The singleton instance representing lua true +
s_metatable - +Static variable in class org.luaj.vm2.LuaThread +
  +
scannumber(int) - +Method in class org.luaj.vm2.LuaString +
Convert to a number in a base, or return Double.NaN if not a number. +
seek(String, int) - +Method in class org.luaj.vm2.lib.IoLib.File +
  +
set(int, LuaValue) - +Method in class org.luaj.vm2.LuaTable +
  +
set(LuaValue, LuaValue) - +Method in class org.luaj.vm2.LuaTable +
caller must ensure key is not nil +
set(LuaValue, LuaValue) - +Method in class org.luaj.vm2.LuaUserdata +
  +
set(LuaValue, LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Set a value in a table without metatag processing using NEWINDEX. +
set(int, LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Set a value in a table without metatag processing using NEWINDEX. +
set(int, String) - +Method in class org.luaj.vm2.LuaValue +
Set a value in a table without metatag processing using NEWINDEX. +
set(String, LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Set a value in a table without metatag processing using NEWINDEX. +
set(String, double) - +Method in class org.luaj.vm2.LuaValue +
Set a value in a table without metatag processing using NEWINDEX. +
set(String, int) - +Method in class org.luaj.vm2.LuaValue +
Set a value in a table without metatag processing using NEWINDEX. +
set(String, String) - +Method in class org.luaj.vm2.LuaValue +
Set a value in a table without metatag processing using NEWINDEX. +
setErrorFunc(LuaValue) - +Static method in class org.luaj.vm2.LuaThread +
Replace the error function of the currently running thread. +
setfenv(LuaValue) - +Method in class org.luaj.vm2.LuaFunction +
  +
setfenv(LuaValue) - +Method in class org.luaj.vm2.LuaThread +
  +
setfenv(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Set the environment on an object. +
setGlobals(LuaValue) - +Static method in class org.luaj.vm2.LuaThread +
Set the globals of the current thread. +
setIsLoaded(String, LuaTable) - +Method in class org.luaj.vm2.lib.PackageLib +
Allow packages to mark themselves as loaded +
setlocale(String, String) - +Method in class org.luaj.vm2.lib.OsLib +
Sets the current locale of the program. +
setLuaPath(String) - +Method in class org.luaj.vm2.lib.PackageLib +
  +
setmetatable(LuaValue) - +Method in class org.luaj.vm2.LuaTable +
  +
setmetatable(LuaValue) - +Method in class org.luaj.vm2.LuaUserdata +
  +
setmetatable(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Set the metatable for this LuaValue +
settable(LuaValue, LuaValue, LuaValue) - +Static method in class org.luaj.vm2.LuaValue +
Perform field assignment including metatag processing. +
setUpvalue(int, LuaValue) - +Method in class org.luaj.vm2.LuaClosure +
  +
setvalue(LuaValue) - +Method in class org.luaj.vm2.Buffer +
Set buffer contents as a LuaValue +
setValue(LuaValue) - +Method in class org.luaj.vm2.UpValue +
Set the value of the upvalue +
setvbuf(String, int) - +Method in class org.luaj.vm2.lib.IoLib.File +
  +
SIZE_A - +Static variable in class org.luaj.vm2.Lua +
  +
SIZE_B - +Static variable in class org.luaj.vm2.Lua +
  +
SIZE_Bx - +Static variable in class org.luaj.vm2.Lua +
  +
SIZE_C - +Static variable in class org.luaj.vm2.Lua +
  +
SIZE_OP - +Static variable in class org.luaj.vm2.Lua +
  +
sort(LuaValue) - +Method in class org.luaj.vm2.LuaTable +
Sort the table using a comparator. +
sort(LuaValue) - +Method in class org.luaj.vm2.WeakTable +
  +
source - +Variable in class org.luaj.vm2.Prototype +
  +
SOURCE_BINARY_STRING - +Static variable in class org.luaj.vm2.LoadState +
Name for compiled chunks +
sourceshort(Prototype) - +Static method in class org.luaj.vm2.lib.DebugLib +
  +
standardGlobals() - +Static method in class org.luaj.vm2.lib.jme.JmePlatform +
Create a standard set of globals for JME including all the libraries. +
standardGlobals() - +Static method in class org.luaj.vm2.lib.jse.JsePlatform +
Create a standard set of globals for JSE including all the libraries. +
startpc - +Variable in class org.luaj.vm2.LocVars +
The instruction offset when the variable comes into scope +
STDERR - +Variable in class org.luaj.vm2.lib.BaseLib +
  +
STDIN - +Variable in class org.luaj.vm2.lib.BaseLib +
  +
STDIN - +Variable in class org.luaj.vm2.lib.PackageLib +
  +
STDOUT - +Variable in class org.luaj.vm2.lib.BaseLib +
  +
STDOUT - +Variable in class org.luaj.vm2.lib.PackageLib +
  +
strcmp(LuaString) - +Method in class org.luaj.vm2.LuaDouble +
  +
strcmp(LuaString) - +Method in class org.luaj.vm2.LuaInteger +
  +
strcmp(LuaValue) - +Method in class org.luaj.vm2.LuaString +
  +
strcmp(LuaString) - +Method in class org.luaj.vm2.LuaString +
  +
strcmp(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Perform string comparison with another value + of any type + using string comparison based on byte values. +
strcmp(LuaString) - +Method in class org.luaj.vm2.LuaValue +
Perform string comparison with another value + known to be a LuaString + using string comparison based on byte values. +
StringLib - Class in org.luaj.vm2.lib
Subclass of LibFunction which implements the lua standard string + library.
StringLib() - +Constructor for class org.luaj.vm2.lib.StringLib +
  +
strongkey() - +Method in class org.luaj.vm2.LuaValue +
Return the key part of this value if it is a weak table entry, or NIL if it was weak and is no longer referenced. +
strongvalue() - +Method in class org.luaj.vm2.LuaValue +
Return this value as a strong reference, or NIL if it was weak and is no longer referenced. +
strvalue() - +Method in class org.luaj.vm2.LuaDouble +
  +
strvalue() - +Method in class org.luaj.vm2.LuaInteger +
  +
strvalue() - +Method in class org.luaj.vm2.LuaString +
  +
strvalue() - +Method in class org.luaj.vm2.LuaValue +
Convert this value to a string if it is a LuaString or LuaNumber, + or throw a LuaError if it is not +
sub(LuaValue) - +Method in class org.luaj.vm2.LuaDouble +
  +
sub(double) - +Method in class org.luaj.vm2.LuaDouble +
  +
sub(int) - +Method in class org.luaj.vm2.LuaDouble +
  +
sub(LuaValue) - +Method in class org.luaj.vm2.LuaInteger +
  +
sub(double) - +Method in class org.luaj.vm2.LuaInteger +
  +
sub(int) - +Method in class org.luaj.vm2.LuaInteger +
  +
sub(LuaValue) - +Method in class org.luaj.vm2.LuaString +
  +
sub(double) - +Method in class org.luaj.vm2.LuaString +
  +
sub(int) - +Method in class org.luaj.vm2.LuaString +
  +
SUB - +Static variable in class org.luaj.vm2.LuaValue +
LuaString constant with value "__sub" for use as metatag +
sub(LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Subtract: Perform numeric subtract operation with another value + of unknown type, + including metatag processing. +
sub(double) - +Method in class org.luaj.vm2.LuaValue +
Subtract: Perform numeric subtract operation with another value + of double type with metatag processing +
sub(int) - +Method in class org.luaj.vm2.LuaValue +
Subtract: Perform numeric subtract operation with another value + of int type with metatag processing +
subargs(int) - +Method in class org.luaj.vm2.Varargs +
Create a Varargs instance containing arguments starting at index start +
subFrom(double) - +Method in class org.luaj.vm2.LuaDouble +
  +
subFrom(double) - +Method in class org.luaj.vm2.LuaInteger +
  +
subFrom(int) - +Method in class org.luaj.vm2.LuaInteger +
  +
subFrom(double) - +Method in class org.luaj.vm2.LuaString +
  +
subFrom(double) - +Method in class org.luaj.vm2.LuaValue +
Reverse-subtract: Perform numeric subtract operation from an int value + with metatag processing +
subFrom(int) - +Method in class org.luaj.vm2.LuaValue +
Reverse-subtract: Perform numeric subtract operation from a double value + without metatag processing +
substring(int, int) - +Method in class org.luaj.vm2.LuaString +
  +
+
+

+T

+
+
TableLib - Class in org.luaj.vm2.lib
Subclass of LibFunction which implements the lua standard table + library.
TableLib() - +Constructor for class org.luaj.vm2.lib.TableLib +
  +
tableOf() - +Static method in class org.luaj.vm2.LuaValue +
Construct an empty LuaTable. +
tableOf(Varargs, int) - +Static method in class org.luaj.vm2.LuaValue +
Construct a LuaTable initialized with supplied array values. +
tableOf(int, int) - +Static method in class org.luaj.vm2.LuaValue +
Construct an empty LuaTable preallocated to hold array and hashed elements +
tableOf(LuaValue[]) - +Static method in class org.luaj.vm2.LuaValue +
Construct a LuaTable initialized with supplied named values. +
tableOf(LuaValue[], LuaValue[]) - +Static method in class org.luaj.vm2.LuaValue +
Construct a LuaTable initialized with supplied named values and sequential elements. +
tableOf(LuaValue[], LuaValue[], Varargs) - +Static method in class org.luaj.vm2.LuaValue +
Construct a LuaTable initialized with supplied named values and sequential elements in an array part and as varargs. +
tailcallOf(LuaValue, Varargs) - +Static method in class org.luaj.vm2.LuaValue +
Construct a TailcallVarargs around a function and arguments. +
TailcallVarargs - Class in org.luaj.vm2
Subclass of Varargs that represents a lua tail call + in a Java library function execution environment.
TailcallVarargs(LuaValue, Varargs) - +Constructor for class org.luaj.vm2.TailcallVarargs +
  +
TailcallVarargs(LuaValue, LuaValue, Varargs) - +Constructor for class org.luaj.vm2.TailcallVarargs +
  +
TBOOLEAN - +Static variable in class org.luaj.vm2.LuaValue +
Type enumeration constant for lua booleans +
testAMode(int) - +Static method in class org.luaj.vm2.Lua +
  +
testfor_b(LuaValue, LuaValue) - +Method in class org.luaj.vm2.LuaValue +
Perform end-condition test in for-loop processing. +
testTMode(int) - +Static method in class org.luaj.vm2.Lua +
  +
TFUNCTION - +Static variable in class org.luaj.vm2.LuaValue +
Type enumeration constant for lua functions +
ThreeArgFunction - Class in org.luaj.vm2.lib
Abstract base class for Java function implementations that take two arguments and + return one value.
ThreeArgFunction() - +Constructor for class org.luaj.vm2.lib.ThreeArgFunction +
Default constructor +
ThreeArgFunction(LuaValue) - +Constructor for class org.luaj.vm2.lib.ThreeArgFunction +
Constructor with specific environment +
time(LuaTable) - +Method in class org.luaj.vm2.lib.OsLib +
Returns the current time when called without arguments, + or a time representing the date and time specified by the given table. +
TINT - +Static variable in class org.luaj.vm2.LuaValue +
Type enumeration constant for lua numbers that are ints, for compatibility with lua 5.1 number patch only +
TLIGHTUSERDATA - +Static variable in class org.luaj.vm2.LuaValue +
Type enumeration constant for lua light userdata, for compatibility with C-based lua only +
TMP_PREFIX - +Static variable in class org.luaj.vm2.lib.OsLib +
  +
TMP_SUFFIX - +Static variable in class org.luaj.vm2.lib.OsLib +
  +
tmpFile() - +Method in class org.luaj.vm2.lib.IoLib +
Open a temporary file. +
tmpFile() - +Method in class org.luaj.vm2.lib.jme.JmeIoLib +
  +
tmpFile() - +Method in class org.luaj.vm2.lib.jse.JseIoLib +
  +
tmpname() - +Method in class org.luaj.vm2.lib.jse.JseOsLib +
  +
tmpname() - +Method in class org.luaj.vm2.lib.OsLib +
Returns a string with a file name that can be used for a temporary file. +
TNIL - +Static variable in class org.luaj.vm2.LuaValue +
Type enumeration constant for lua nil +
TNONE - +Static variable in class org.luaj.vm2.LuaValue +
Type enumeration constant for lua values that have no type, for example weak table entries +
TNUMBER - +Static variable in class org.luaj.vm2.LuaValue +
Type enumeration constant for lua numbers +
toboolean() - +Method in class org.luaj.vm2.LuaBoolean +
  +
toboolean() - +Method in class org.luaj.vm2.LuaNil +
  +
toboolean() - +Method in class org.luaj.vm2.LuaValue +
Convert to boolean false if LuaValue.NIL or FALSE, true if anything else +
toboolean(int) - +Method in class org.luaj.vm2.Varargs +
Convert argument i to java boolean based on lua rules for boolean evaluation. +
tobyte() - +Method in class org.luaj.vm2.LuaDouble +
  +
tobyte() - +Method in class org.luaj.vm2.LuaInteger +
  +
tobyte() - +Method in class org.luaj.vm2.LuaString +
  +
tobyte() - +Method in class org.luaj.vm2.LuaValue +
Convert to byte if numeric, or 0 if not. +
tobyte(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java byte value, discarding any fractional part and truncating, + or 0 if not a number. +
tochar() - +Method in class org.luaj.vm2.LuaDouble +
  +
tochar() - +Method in class org.luaj.vm2.LuaInteger +
  +
tochar() - +Method in class org.luaj.vm2.LuaString +
  +
tochar() - +Method in class org.luaj.vm2.LuaValue +
Convert to char if numeric, or 0 if not. +
tochar(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java char value, discarding any fractional part and truncating, + or 0 if not a number. +
toClassname(String) - +Static method in class org.luaj.vm2.lib.PackageLib +
Convert lua filename to valid class name +
todouble() - +Method in class org.luaj.vm2.LuaDouble +
  +
todouble() - +Method in class org.luaj.vm2.LuaInteger +
  +
todouble() - +Method in class org.luaj.vm2.LuaString +
  +
todouble() - +Method in class org.luaj.vm2.LuaValue +
Convert to double if numeric, or 0 if not. +
todouble(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java double value or 0 if not a number. +
tofloat() - +Method in class org.luaj.vm2.LuaDouble +
  +
tofloat() - +Method in class org.luaj.vm2.LuaInteger +
  +
tofloat() - +Method in class org.luaj.vm2.LuaString +
  +
tofloat() - +Method in class org.luaj.vm2.LuaValue +
Convert to float if numeric, or 0 if not. +
tofloat(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java float value, discarding excess fractional part and truncating, + or 0 if not a number. +
toInputStream() - +Method in class org.luaj.vm2.LuaString +
Convert value to an input stream. +
toint() - +Method in class org.luaj.vm2.LuaDouble +
  +
toint() - +Method in class org.luaj.vm2.LuaInteger +
  +
toint() - +Method in class org.luaj.vm2.LuaString +
  +
toint() - +Method in class org.luaj.vm2.LuaValue +
Convert to int if numeric, or 0 if not. +
toint(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java int value, discarding any fractional part and truncating, + or 0 if not a number. +
tojstring() - +Method in class org.luaj.vm2.Buffer +
Convert the buffer to a Java String +
tojstring() - +Method in class org.luaj.vm2.lib.IoLib.File +
  +
tojstring() - +Method in class org.luaj.vm2.lib.LibFunction +
  +
tojstring() - +Method in class org.luaj.vm2.lib.PackageLib +
  +
tojstring() - +Method in class org.luaj.vm2.LocVars +
  +
tojstring() - +Method in class org.luaj.vm2.LuaBoolean +
  +
tojstring() - +Method in class org.luaj.vm2.LuaDouble +
  +
tojstring() - +Method in class org.luaj.vm2.LuaInteger +
  +
tojstring() - +Method in class org.luaj.vm2.LuaNil +
  +
tojstring() - +Method in class org.luaj.vm2.LuaString +
  +
tojstring() - +Method in class org.luaj.vm2.LuaUserdata +
  +
tojstring() - +Method in class org.luaj.vm2.LuaValue +
Convert to human readable String for any type. +
tojstring() - +Method in class org.luaj.vm2.UpValue +
Convert this upvalue to a Java String +
tojstring(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java String based on the type of the argument. +
tojstring() - +Method in class org.luaj.vm2.Varargs +
Convert the list of varargs values to a human readable java String. +
tolong() - +Method in class org.luaj.vm2.LuaDouble +
  +
tolong() - +Method in class org.luaj.vm2.LuaInteger +
  +
tolong() - +Method in class org.luaj.vm2.LuaString +
  +
tolong() - +Method in class org.luaj.vm2.LuaValue +
Convert to long if numeric, or 0 if not. +
tolong(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java long value, discarding any fractional part and truncating, + or 0 if not a number. +
tonumber() - +Method in class org.luaj.vm2.LuaDouble +
  +
tonumber() - +Method in class org.luaj.vm2.LuaNumber +
  +
tonumber() - +Method in class org.luaj.vm2.LuaString +
  +
tonumber(int) - +Method in class org.luaj.vm2.LuaString +
convert to a number using a supplied base, or NIL if it can't be converted +
tonumber() - +Method in class org.luaj.vm2.LuaValue +
Conditionally convert to lua number without throwing errors. +
toshort() - +Method in class org.luaj.vm2.LuaDouble +
  +
toshort() - +Method in class org.luaj.vm2.LuaInteger +
  +
toshort() - +Method in class org.luaj.vm2.LuaString +
  +
toshort() - +Method in class org.luaj.vm2.LuaValue +
Convert to short if numeric, or 0 if not. +
toshort(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java short value, discarding any fractional part and truncating, + or 0 if not a number. +
tostring() - +Method in class org.luaj.vm2.Buffer +
Convert the buffer to a LuaString +
toString() - +Method in class org.luaj.vm2.Buffer +
Convert the buffer to a Java String +
tostring() - +Method in class org.luaj.vm2.LuaDouble +
  +
tostring() - +Method in class org.luaj.vm2.LuaInteger +
  +
tostring() - +Method in class org.luaj.vm2.LuaString +
  +
TOSTRING - +Static variable in class org.luaj.vm2.LuaValue +
LuaString constant with value "__tostring" for use as metatag +
toString() - +Method in class org.luaj.vm2.LuaValue +
Convert the value to a human readable string using LuaValue.tojstring() +
tostring() - +Method in class org.luaj.vm2.LuaValue +
Conditionally convert to lua string without throwing errors. +
toString() - +Method in class org.luaj.vm2.Prototype +
  +
toString() - +Method in class org.luaj.vm2.Varargs +
Convert the value or values to a java String using Varargs.tojstring() +
touserdata() - +Method in class org.luaj.vm2.LuaUserdata +
  +
touserdata(Class) - +Method in class org.luaj.vm2.LuaUserdata +
  +
touserdata() - +Method in class org.luaj.vm2.LuaValue +
Convert to userdata instance, or null. +
touserdata(Class) - +Method in class org.luaj.vm2.LuaValue +
Convert to userdata instance if specific type, or null. +
touserdata(int) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java Object if a userdata, or null. +
touserdata(int, Class) - +Method in class org.luaj.vm2.Varargs +
Return argument i as a java Object if it is a userdata whose instance Class c or a subclass, or null. +
TRACE - +Static variable in class org.luaj.vm2.lib.DebugLib +
  +
traceback(int) - +Static method in class org.luaj.vm2.lib.DebugLib +
Get a traceback as a string for the current thread +
traceback(LuaThread, int) - +Static method in class org.luaj.vm2.lib.DebugLib +
Get a traceback for a particular thread. +
TRUE - +Static variable in class org.luaj.vm2.LuaValue +
LuaBoolean constant corresponding to lua true +
TSTRING - +Static variable in class org.luaj.vm2.LuaValue +
Type enumeration constant for lua strings +
TTABLE - +Static variable in class org.luaj.vm2.LuaValue +
Type enumeration constant for lua tables +
TTHREAD - +Static variable in class org.luaj.vm2.LuaValue +
Type enumeration constant for lua threads +
TUSERDATA - +Static variable in class org.luaj.vm2.LuaValue +
Type enumeration constant for lua userdatas +
TVALUE - +Static variable in class org.luaj.vm2.LuaValue +
Type enumeration constant for unknown values, for compatibility with C-based lua only +
TwoArgFunction - Class in org.luaj.vm2.lib
Abstract base class for Java function implementations that take two arguments and + return one value.
TwoArgFunction() - +Constructor for class org.luaj.vm2.lib.TwoArgFunction +
Default constructor +
TwoArgFunction(LuaValue) - +Constructor for class org.luaj.vm2.lib.TwoArgFunction +
Constructor with specific environment +
type() - +Method in class org.luaj.vm2.lib.IoLib.File +
  +
type() - +Method in class org.luaj.vm2.LuaBoolean +
  +
type() - +Method in class org.luaj.vm2.LuaFunction +
  +
type() - +Method in class org.luaj.vm2.LuaNil +
  +
type() - +Method in class org.luaj.vm2.LuaNumber +
  +
type() - +Method in class org.luaj.vm2.LuaString +
  +
type() - +Method in class org.luaj.vm2.LuaTable +
  +
type() - +Method in class org.luaj.vm2.LuaThread +
  +
type() - +Method in class org.luaj.vm2.LuaUserdata +
  +
type() - +Method in class org.luaj.vm2.LuaValue +
Get the enumeration value for the type of this value. +
type(int) - +Method in class org.luaj.vm2.Varargs +
Gets the type of argument i +
TYPE_NAMES - +Static variable in class org.luaj.vm2.LuaValue +
String array constant containing names of each of the lua value types +
typename() - +Method in class org.luaj.vm2.lib.IoLib.File +
  +
typename() - +Method in class org.luaj.vm2.LuaBoolean +
  +
typename() - +Method in class org.luaj.vm2.LuaFunction +
  +
typename() - +Method in class org.luaj.vm2.LuaNil +
  +
typename() - +Method in class org.luaj.vm2.LuaNumber +
  +
typename() - +Method in class org.luaj.vm2.LuaString +
  +
typename() - +Method in class org.luaj.vm2.LuaTable +
  +
typename() - +Method in class org.luaj.vm2.LuaThread +
  +
typename() - +Method in class org.luaj.vm2.LuaUserdata +
  +
typename() - +Method in class org.luaj.vm2.LuaValue +
Get the String name of the type of this value. +
typerror(String) - +Method in class org.luaj.vm2.LuaValue +
Throw a LuaError indicating an invalid type was supplied to a function +
+
+

+U

+
+
unimplemented(String) - +Method in class org.luaj.vm2.LuaValue +
Throw a LuaError indicating an operation is not implemented +
UNM - +Static variable in class org.luaj.vm2.LuaValue +
LuaString constant with value "__unm" for use as metatag +
UpValue - Class in org.luaj.vm2
Upvalue used with Closure formulation
UpValue(LuaValue[], int) - +Constructor for class org.luaj.vm2.UpValue +
Create an upvalue relative to a stack +
upValues - +Variable in class org.luaj.vm2.LuaClosure +
  +
upvalues - +Variable in class org.luaj.vm2.Prototype +
  +
userdata() - +Method in class org.luaj.vm2.LuaUserdata +
  +
userdataOf(Object) - +Static method in class org.luaj.vm2.LuaValue +
Construct a LuaUserdata for an object. +
userdataOf(Object, LuaValue) - +Static method in class org.luaj.vm2.LuaValue +
Construct a LuaUserdata for an object with a user supplied metatable. +
+
+

+V

+
+
v - +Variable in class org.luaj.vm2.LuaBoolean +
The value of the boolean +
v - +Variable in class org.luaj.vm2.LuaInteger +
The value being held by this instance. +
value() - +Method in class org.luaj.vm2.Buffer +
Get buffer contents as a LuaValue +
valueOf(double) - +Static method in class org.luaj.vm2.LuaDouble +
  +
valueOf(int) - +Static method in class org.luaj.vm2.LuaInteger +
  +
valueOf(long) - +Static method in class org.luaj.vm2.LuaInteger +
Return a LuaNumber that represents the value provided +
valueOf(String) - +Static method in class org.luaj.vm2.LuaString +
Get a LuaString instance whose bytes match + the supplied Java String using the UTF8 encoding. +
valueOf(byte[], int, int) - +Static method in class org.luaj.vm2.LuaString +
Construct a LuaString around a byte array without copying the contents. +
valueOf(char[]) - +Static method in class org.luaj.vm2.LuaString +
Construct a LuaString using the supplied characters as byte values. +
valueOf(byte[]) - +Static method in class org.luaj.vm2.LuaString +
Construct a LuaString around a byte array without copying the contents. +
valueOf(boolean) - +Static method in class org.luaj.vm2.LuaValue +
Convert java boolean to a LuaValue. +
valueOf(int) - +Static method in class org.luaj.vm2.LuaValue +
Convert java int to a LuaValue. +
valueOf(double) - +Static method in class org.luaj.vm2.LuaValue +
Convert java double to a LuaValue. +
valueOf(String) - +Static method in class org.luaj.vm2.LuaValue +
Convert java string to a LuaValue. +
valueOf(byte[]) - +Static method in class org.luaj.vm2.LuaValue +
Convert bytes in an array to a LuaValue. +
valueOf(byte[], int, int) - +Static method in class org.luaj.vm2.LuaValue +
Convert bytes in an array to a LuaValue. +
VARARG_HASARG - +Static variable in class org.luaj.vm2.Lua +
masks for new-style vararg +
VARARG_ISVARARG - +Static variable in class org.luaj.vm2.Lua +
  +
VARARG_NEEDSARG - +Static variable in class org.luaj.vm2.Lua +
  +
VarArgFunction - Class in org.luaj.vm2.lib
Abstract base class for Java function implementations that takes varaiable arguments and + returns multiple return values.
VarArgFunction() - +Constructor for class org.luaj.vm2.lib.VarArgFunction +
  +
VarArgFunction(LuaValue) - +Constructor for class org.luaj.vm2.lib.VarArgFunction +
  +
Varargs - Class in org.luaj.vm2
Class to encapsulate varargs values, either as part of a variable argument list, or multiple return values.
Varargs() - +Constructor for class org.luaj.vm2.Varargs +
  +
varargsOf(LuaValue[]) - +Static method in class org.luaj.vm2.LuaValue +
Construct a Varargs around an array of LuaValues. +
varargsOf(LuaValue[], Varargs) - +Static method in class org.luaj.vm2.LuaValue +
Construct a Varargs around an array of LuaValues. +
varargsOf(LuaValue[], int, int) - +Static method in class org.luaj.vm2.LuaValue +
Construct a Varargs around an array of LuaValues. +
varargsOf(LuaValue[], int, int, Varargs) - +Static method in class org.luaj.vm2.LuaValue +
Construct a Varargs around an array of LuaValues. +
varargsOf(LuaValue, Varargs) - +Static method in class org.luaj.vm2.LuaValue +
Construct a Varargs around a set of 2 or more LuaValues. +
varargsOf(LuaValue, LuaValue, Varargs) - +Static method in class org.luaj.vm2.LuaValue +
Construct a Varargs around a set of 3 or more LuaValues. +
varname - +Variable in class org.luaj.vm2.LocVars +
The local variable name +
+
+

+W

+
+
waitFor() - +Method in class org.luaj.vm2.lib.jse.JseProcess +
Wait for the process to complete, and all pending output to finish. +
WeakTable - Class in org.luaj.vm2
Subclass of LuaTable that provides weak key and weak value semantics.
WeakTable(boolean, boolean) - +Constructor for class org.luaj.vm2.WeakTable +
Construct a table with weak keys, weak values, or both +
WeakTable(boolean, boolean, int, int) - +Constructor for class org.luaj.vm2.WeakTable +
Construct a table with weak keys, weak values, or both, and an initial capacity +
WeakTable(boolean, boolean, LuaTable) - +Constructor for class org.luaj.vm2.WeakTable +
Construct a table with weak keys, weak values, or both, and a source of initial data +
wrapStdin() - +Method in class org.luaj.vm2.lib.IoLib +
Wrap the standard input. +
wrapStdin() - +Method in class org.luaj.vm2.lib.jme.JmeIoLib +
  +
wrapStdin() - +Method in class org.luaj.vm2.lib.jse.JseIoLib +
  +
wrapStdout() - +Method in class org.luaj.vm2.lib.IoLib +
Wrap the standard output. +
wrapStdout() - +Method in class org.luaj.vm2.lib.jme.JmeIoLib +
  +
wrapStdout() - +Method in class org.luaj.vm2.lib.jse.JseIoLib +
  +
write(LuaString) - +Method in class org.luaj.vm2.lib.IoLib.File +
  +
write(DataOutputStream, int, int) - +Method in class org.luaj.vm2.LuaString +
  +
+
+

+Y

+
+
yield(Varargs) - +Static method in class org.luaj.vm2.LuaThread +
Yield the current thread with arguments +
+
+

+Z

+
+
ZERO - +Static variable in class org.luaj.vm2.LuaValue +
LuaValue number constant equal to 0 +
ZeroArgFunction - Class in org.luaj.vm2.lib
Abstract base class for Java function implementations that take no arguments and + return one value.
ZeroArgFunction() - +Constructor for class org.luaj.vm2.lib.ZeroArgFunction +
Default constructor +
ZeroArgFunction(LuaValue) - +Constructor for class org.luaj.vm2.lib.ZeroArgFunction +
Constructor with specific environment +
+
+

+_

+
+
_assert(boolean) - +Static method in class org.luaj.vm2.compiler.LuaC +
  +
_file_close(LuaValue) - +Method in class org.luaj.vm2.lib.IoLib +
  +
_file_flush(LuaValue) - +Method in class org.luaj.vm2.lib.IoLib +
  +
_file_lines(LuaValue) - +Method in class org.luaj.vm2.lib.IoLib +
  +
_file_read(LuaValue, Varargs) - +Method in class org.luaj.vm2.lib.IoLib +
  +
_file_seek(LuaValue, String, int) - +Method in class org.luaj.vm2.lib.IoLib +
  +
_file_setvbuf(LuaValue, String, int) - +Method in class org.luaj.vm2.lib.IoLib +
  +
_file_write(LuaValue, Varargs) - +Method in class org.luaj.vm2.lib.IoLib +
  +
_getinfo(Varargs, LuaValue) - +Static method in class org.luaj.vm2.lib.DebugLib +
  +
_io_close(LuaValue) - +Method in class org.luaj.vm2.lib.IoLib +
  +
_io_flush() - +Method in class org.luaj.vm2.lib.IoLib +
  +
_io_index(LuaValue) - +Method in class org.luaj.vm2.lib.IoLib +
  +
_io_input(LuaValue) - +Method in class org.luaj.vm2.lib.IoLib +
  +
_io_lines(String) - +Method in class org.luaj.vm2.lib.IoLib +
  +
_io_open(String, String) - +Method in class org.luaj.vm2.lib.IoLib +
  +
_io_output(LuaValue) - +Method in class org.luaj.vm2.lib.IoLib +
  +
_io_popen(String, String) - +Method in class org.luaj.vm2.lib.IoLib +
  +
_io_read(Varargs) - +Method in class org.luaj.vm2.lib.IoLib +
  +
_io_tmpfile() - +Method in class org.luaj.vm2.lib.IoLib +
  +
_io_type(LuaValue) - +Method in class org.luaj.vm2.lib.IoLib +
  +
_io_write(Varargs) - +Method in class org.luaj.vm2.lib.IoLib +
  +
_lines_iter(LuaValue) - +Method in class org.luaj.vm2.lib.IoLib +
  +
_VERSION - +Static variable in class org.luaj.vm2.Lua +
version is supplied by ant build task +
+
+A B C D E F G H I J K L M N O P R S T U V W Y Z _ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/index.html b/luaj-2.0.3/docs/api/index.html new file mode 100644 index 0000000000..5e95b45630 --- /dev/null +++ b/luaj-2.0.3/docs/api/index.html @@ -0,0 +1,39 @@ + + + + + + +Luaj API + + + + + + + + + + + +<H2> +Frame Alert</H2> + +<P> +This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. +<BR> +Link to<A HREF="overview-summary.html">Non-frame version.</A> + + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/Buffer.html b/luaj-2.0.3/docs/api/org/luaj/vm2/Buffer.html new file mode 100644 index 0000000000..d288b69959 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/Buffer.html @@ -0,0 +1,602 @@ + + + + + + +Buffer (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class Buffer

+
+java.lang.Object
+  extended by org.luaj.vm2.Buffer
+
+
+
+
public final class Buffer
extends java.lang.Object
+ + +

+String buffer for use in string library methods, optimized for production + of StrValue instances. +

+ The buffer can begin initially as a wrapped LuaValue + and only when concatenation actually occurs are the bytes first copied. +

+ To convert back to a LuaValue again, + the function value() is used. +

+ +

+

+
See Also:
LuaValue, +LuaValue.buffer(), +LuaString
+
+ +

+ + + + + + + + + + + + + + + + + +
+Constructor Summary
Buffer() + +
+          Create buffer with default capacity
Buffer(int initialCapacity) + +
+          Create buffer with specified initial capacity
Buffer(LuaValue value) + +
+          Create buffer with specified initial value
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ Bufferappend(byte b) + +
+          Append a single byte to the buffer.
+ Bufferappend(LuaString str) + +
+          Append a LuaString to the buffer.
+ Bufferappend(LuaValue val) + +
+          Append a LuaValue to the buffer.
+ Bufferappend(java.lang.String str) + +
+          Append a Java String to the buffer.
+ BufferconcatTo(LuaNumber lhs) + +
+          Concatenate this buffer onto a LuaNumber
+ BufferconcatTo(LuaString lhs) + +
+          Concatenate this buffer onto a LuaString
+ BufferconcatTo(LuaValue lhs) + +
+          Concatenate this buffer onto a LuaValue
+ voidmakeroom(int nbefore, + int nafter) + +
+          Ensure there is enough room before and after the bytes.
+ Bufferprepend(LuaString s) + +
+          Concatenate bytes from a LuaString onto the front of this buffer
+ Buffersetvalue(LuaValue value) + +
+          Set buffer contents as a LuaValue
+ java.lang.Stringtojstring() + +
+          Convert the buffer to a Java String
+ LuaStringtostring() + +
+          Convert the buffer to a LuaString
+ java.lang.StringtoString() + +
+          Convert the buffer to a Java String
+ LuaValuevalue() + +
+          Get buffer contents as a LuaValue
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+Buffer

+
+public Buffer()
+
+
Create buffer with default capacity +

+

+
See Also:
DEFAULT_CAPACITY
+
+
+ +

+Buffer

+
+public Buffer(int initialCapacity)
+
+
Create buffer with specified initial capacity +

+

+
Parameters:
initialCapacity - the initial capacity
+
+
+ +

+Buffer

+
+public Buffer(LuaValue value)
+
+
Create buffer with specified initial value +

+

+
Parameters:
value - the initial value
+
+ + + + + + + + +
+Method Detail
+ +

+value

+
+public LuaValue value()
+
+
Get buffer contents as a LuaValue +

+

+ +
Returns:
value as a LuaValue, converting as necessary
+
+
+
+ +

+setvalue

+
+public Buffer setvalue(LuaValue value)
+
+
Set buffer contents as a LuaValue +

+

+
Parameters:
value - value to set
+
+
+
+ +

+tostring

+
+public final LuaString tostring()
+
+
Convert the buffer to a LuaString +

+

+ +
Returns:
the value as a LuaString
+
+
+
+ +

+tojstring

+
+public java.lang.String tojstring()
+
+
Convert the buffer to a Java String +

+

+ +
Returns:
the value as a Java String
+
+
+
+ +

+toString

+
+public java.lang.String toString()
+
+
Convert the buffer to a Java String +

+

+
Overrides:
toString in class java.lang.Object
+
+
+ +
Returns:
the value as a Java String
+
+
+
+ +

+append

+
+public final Buffer append(byte b)
+
+
Append a single byte to the buffer. +

+

+ +
Returns:
this to allow call chaining
+
+
+
+ +

+append

+
+public final Buffer append(LuaValue val)
+
+
Append a LuaValue to the buffer. +

+

+ +
Returns:
this to allow call chaining
+
+
+
+ +

+append

+
+public final Buffer append(LuaString str)
+
+
Append a LuaString to the buffer. +

+

+ +
Returns:
this to allow call chaining
+
+
+
+ +

+append

+
+public final Buffer append(java.lang.String str)
+
+
Append a Java String to the buffer. + The Java string will be converted to bytes using the UTF8 encoding. +

+

+ +
Returns:
this to allow call chaining
See Also:
LuaString.encodeToUtf8(char[], byte[], int)
+
+
+
+ +

+concatTo

+
+public Buffer concatTo(LuaValue lhs)
+
+
Concatenate this buffer onto a LuaValue +

+

+
Parameters:
lhs - the left-hand-side value onto which we are concatenating this +
Returns:
Buffer for use in call chaining.
+
+
+
+ +

+concatTo

+
+public Buffer concatTo(LuaString lhs)
+
+
Concatenate this buffer onto a LuaString +

+

+
Parameters:
lhs - the left-hand-side value onto which we are concatenating this +
Returns:
Buffer for use in call chaining.
+
+
+
+ +

+concatTo

+
+public Buffer concatTo(LuaNumber lhs)
+
+
Concatenate this buffer onto a LuaNumber +

+ The LuaNumber will be converted to a string before concatenating. +

+

+
Parameters:
lhs - the left-hand-side value onto which we are concatenating this +
Returns:
Buffer for use in call chaining.
+
+
+
+ +

+prepend

+
+public Buffer prepend(LuaString s)
+
+
Concatenate bytes from a LuaString onto the front of this buffer +

+

+
Parameters:
s - the left-hand-side value which we will concatenate onto the front of this +
Returns:
Buffer for use in call chaining.
+
+
+
+ +

+makeroom

+
+public final void makeroom(int nbefore,
+                           int nafter)
+
+
Ensure there is enough room before and after the bytes. +

+

+
Parameters:
nbefore - number of unused bytes which must precede the data after this completes
nafter - number of unused bytes which must follow the data after this completes
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/LoadState.LuaCompiler.html b/luaj-2.0.3/docs/api/org/luaj/vm2/LoadState.LuaCompiler.html new file mode 100644 index 0000000000..33ace8345f --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/LoadState.LuaCompiler.html @@ -0,0 +1,230 @@ + + + + + + +LoadState.LuaCompiler (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Interface LoadState.LuaCompiler

+
+
All Known Implementing Classes:
LuaC, LuaJC
+
+
+
Enclosing class:
LoadState
+
+
+
+
public static interface LoadState.LuaCompiler
+ + +

+Interface for the compiler, if it is installed. +

+ See the LuaClosure documentation for examples of how to use the compiler. +

+ +

+

+
See Also:
LuaClosure, +load(InputStream, String, LuaValue)
+
+ +

+ + + + + + + + + + + + +
+Method Summary
+ LuaFunctionload(java.io.InputStream stream, + java.lang.String filename, + LuaValue env) + +
+          Load into a Closure or LuaFunction from a Stream and initializes the environment
+  +

+ + + + + + + + +
+Method Detail
+ +

+load

+
+LuaFunction load(java.io.InputStream stream,
+                 java.lang.String filename,
+                 LuaValue env)
+                 throws java.io.IOException
+
+
Load into a Closure or LuaFunction from a Stream and initializes the environment +

+

+ +
Throws: +
java.io.IOException
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/LoadState.html b/luaj-2.0.3/docs/api/org/luaj/vm2/LoadState.html new file mode 100644 index 0000000000..38f59df027 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/LoadState.html @@ -0,0 +1,821 @@ + + + + + + +LoadState (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class LoadState

+
+java.lang.Object
+  extended by org.luaj.vm2.LoadState
+
+
+
+
public class LoadState
extends java.lang.Object
+ + +

+Class to manage loading of Prototype instances. +

+ The LoadState class exposes one main function, + namely load(InputStream, String, LuaValue), + to be used to load code from a particular input stream. +

+ A simple pattern for loading and executing code is +

 LuaValue _G = JsePlatform.standardGlobals();
+ LoadState.load( new FileInputStream("main.lua"), "main.lua", _G ).call();
+  
+ This should work regardless of which LoadState.LuaCompiler + has been installed. +

+ + Prior to loading code, a compiler should be installed. +

+ By default, when using JsePlatform or + to construct globals, the LuaC compiler is installed. +

+ To override the default compiler with, say, the LuaJC + lua-to-java bytecode compiler, install it before loading, + for example: +

 LuaValue _G = JsePlatform.standardGlobals();
+ LuaJC.install();
+ LoadState.load( new FileInputStream("main.lua"), "main.lua", _G ).call();
+  
+

+ +

+

+
See Also:
LoadState.LuaCompiler, +LuaClosure, +LuaFunction, +compiler, +load(InputStream, String, LuaValue), +LuaC, +LuaJC
+
+ +

+ + + + + + + + + + + +
+Nested Class Summary
+static interfaceLoadState.LuaCompiler + +
+          Interface for the compiler, if it is installed.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Field Summary
+static LoadState.LuaCompilercompiler + +
+          Compiler instance, if installed
+ java.io.DataInputStreamis + +
+          input stream from which we are loading
+static intLUA_TBOOLEAN + +
+           
+static intLUA_TFUNCTION + +
+           
+static intLUA_TINT + +
+           
+static intLUA_TLIGHTUSERDATA + +
+           
+static intLUA_TNIL + +
+           
+static intLUA_TNONE + +
+           
+static intLUA_TNUMBER + +
+           
+static intLUA_TSTRING + +
+           
+static intLUA_TTABLE + +
+           
+static intLUA_TTHREAD + +
+           
+static intLUA_TUSERDATA + +
+           
+static intLUA_TVALUE + +
+           
+static intLUAC_FORMAT + +
+          for header of binary files -- this is the official format
+static intLUAC_HEADERSIZE + +
+          size of header of binary files
+static intLUAC_VERSION + +
+          for header of binary files -- this is Lua 5.1
+static intNUMBER_FORMAT_FLOATS_OR_DOUBLES + +
+          format corresponding to non-number-patched lua, all numbers are floats or doubles
+static intNUMBER_FORMAT_INTS_ONLY + +
+          format corresponding to non-number-patched lua, all numbers are ints
+static intNUMBER_FORMAT_NUM_PATCH_INT32 + +
+          format corresponding to number-patched lua, all numbers are 32-bit (4 byte) ints
+static java.lang.StringSOURCE_BINARY_STRING + +
+          Name for compiled chunks
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+static java.lang.StringgetSourceName(java.lang.String name) + +
+          Construct a source name from a supplied chunk name
+static LuaFunctionload(java.io.InputStream stream, + java.lang.String name, + LuaValue env) + +
+          Load lua in either binary or text form from an input stream.
+static PrototypeloadBinaryChunk(int firstByte, + java.io.InputStream stream, + java.lang.String name) + +
+          Load lua thought to be a binary chunk from its first byte from an input stream.
+ PrototypeloadFunction(LuaString p) + +
+          Load a function prototype from the input stream
+ voidloadHeader() + +
+          Load the lua chunk header values.
+static LuaValuelongBitsToLuaNumber(long bits) + +
+          Convert bits in a long value to a LuaValue.
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+NUMBER_FORMAT_FLOATS_OR_DOUBLES

+
+public static final int NUMBER_FORMAT_FLOATS_OR_DOUBLES
+
+
format corresponding to non-number-patched lua, all numbers are floats or doubles +

+

+
See Also:
Constant Field Values
+
+
+ +

+NUMBER_FORMAT_INTS_ONLY

+
+public static final int NUMBER_FORMAT_INTS_ONLY
+
+
format corresponding to non-number-patched lua, all numbers are ints +

+

+
See Also:
Constant Field Values
+
+
+ +

+NUMBER_FORMAT_NUM_PATCH_INT32

+
+public static final int NUMBER_FORMAT_NUM_PATCH_INT32
+
+
format corresponding to number-patched lua, all numbers are 32-bit (4 byte) ints +

+

+
See Also:
Constant Field Values
+
+
+ +

+LUA_TINT

+
+public static final int LUA_TINT
+
+
+
See Also:
Constant Field Values
+
+
+ +

+LUA_TNONE

+
+public static final int LUA_TNONE
+
+
+
See Also:
Constant Field Values
+
+
+ +

+LUA_TNIL

+
+public static final int LUA_TNIL
+
+
+
See Also:
Constant Field Values
+
+
+ +

+LUA_TBOOLEAN

+
+public static final int LUA_TBOOLEAN
+
+
+
See Also:
Constant Field Values
+
+
+ +

+LUA_TLIGHTUSERDATA

+
+public static final int LUA_TLIGHTUSERDATA
+
+
+
See Also:
Constant Field Values
+
+
+ +

+LUA_TNUMBER

+
+public static final int LUA_TNUMBER
+
+
+
See Also:
Constant Field Values
+
+
+ +

+LUA_TSTRING

+
+public static final int LUA_TSTRING
+
+
+
See Also:
Constant Field Values
+
+
+ +

+LUA_TTABLE

+
+public static final int LUA_TTABLE
+
+
+
See Also:
Constant Field Values
+
+
+ +

+LUA_TFUNCTION

+
+public static final int LUA_TFUNCTION
+
+
+
See Also:
Constant Field Values
+
+
+ +

+LUA_TUSERDATA

+
+public static final int LUA_TUSERDATA
+
+
+
See Also:
Constant Field Values
+
+
+ +

+LUA_TTHREAD

+
+public static final int LUA_TTHREAD
+
+
+
See Also:
Constant Field Values
+
+
+ +

+LUA_TVALUE

+
+public static final int LUA_TVALUE
+
+
+
See Also:
Constant Field Values
+
+
+ +

+compiler

+
+public static LoadState.LuaCompiler compiler
+
+
Compiler instance, if installed +

+

+
+
+
+ +

+SOURCE_BINARY_STRING

+
+public static final java.lang.String SOURCE_BINARY_STRING
+
+
Name for compiled chunks +

+

+
See Also:
Constant Field Values
+
+
+ +

+LUAC_VERSION

+
+public static final int LUAC_VERSION
+
+
for header of binary files -- this is Lua 5.1 +

+

+
See Also:
Constant Field Values
+
+
+ +

+LUAC_FORMAT

+
+public static final int LUAC_FORMAT
+
+
for header of binary files -- this is the official format +

+

+
See Also:
Constant Field Values
+
+
+ +

+LUAC_HEADERSIZE

+
+public static final int LUAC_HEADERSIZE
+
+
size of header of binary files +

+

+
See Also:
Constant Field Values
+
+
+ +

+is

+
+public final java.io.DataInputStream is
+
+
input stream from which we are loading +

+

+
+
+ + + + + + + + +
+Method Detail
+ +

+longBitsToLuaNumber

+
+public static LuaValue longBitsToLuaNumber(long bits)
+
+
Convert bits in a long value to a LuaValue. +

+

+
Parameters:
bits - long value containing the bits +
Returns:
LuaInteger or LuaDouble whose value corresponds to the bits provided.
+
+
+
+ +

+loadFunction

+
+public Prototype loadFunction(LuaString p)
+                       throws java.io.IOException
+
+
Load a function prototype from the input stream +

+

+
Parameters:
p - name of the source +
Returns:
Prototype instance that was loaded +
Throws: +
java.io.IOException
+
+
+
+ +

+loadHeader

+
+public void loadHeader()
+                throws java.io.IOException
+
+
Load the lua chunk header values. +

+

+ +
Throws: +
java.io.IOException - if an i/o exception occurs.
+
+
+
+ +

+load

+
+public static LuaFunction load(java.io.InputStream stream,
+                               java.lang.String name,
+                               LuaValue env)
+                        throws java.io.IOException
+
+
Load lua in either binary or text form from an input stream. +

+

+
Parameters:
firstByte - the first byte of the input stream
stream - InputStream to read, after having read the first byte already
name - Name to apply to the loaded chunk +
Returns:
Prototype that was loaded +
Throws: +
java.lang.IllegalArgumentException - if the signature is bac +
java.io.IOException - if an IOException occurs
+
+
+
+ +

+loadBinaryChunk

+
+public static Prototype loadBinaryChunk(int firstByte,
+                                        java.io.InputStream stream,
+                                        java.lang.String name)
+                                 throws java.io.IOException
+
+
Load lua thought to be a binary chunk from its first byte from an input stream. +

+

+
Parameters:
firstByte - the first byte of the input stream
stream - InputStream to read, after having read the first byte already
name - Name to apply to the loaded chunk +
Returns:
Prototype that was loaded +
Throws: +
java.lang.IllegalArgumentException - if the signature is bac +
java.io.IOException - if an IOException occurs
+
+
+
+ +

+getSourceName

+
+public static java.lang.String getSourceName(java.lang.String name)
+
+
Construct a source name from a supplied chunk name +

+

+
Parameters:
name - String name that appears in the chunk +
Returns:
source file name
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/LocVars.html b/luaj-2.0.3/docs/api/org/luaj/vm2/LocVars.html new file mode 100644 index 0000000000..c018d14dee --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/LocVars.html @@ -0,0 +1,342 @@ + + + + + + +LocVars (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class LocVars

+
+java.lang.Object
+  extended by org.luaj.vm2.LocVars
+
+
+
+
public class LocVars
extends java.lang.Object
+ + +

+Data class to hold debug information relatign to local variables for a Prototype +

+ +

+


+ +

+ + + + + + + + + + + + + + + + + + + +
+Field Summary
+ intendpc + +
+          The instruction offset when the variable goes out of scope
+ intstartpc + +
+          The instruction offset when the variable comes into scope
+ LuaStringvarname + +
+          The local variable name
+  + + + + + + + + + + +
+Constructor Summary
LocVars(LuaString varname, + int startpc, + int endpc) + +
+          Construct a LocVars instance.
+  + + + + + + + + + + + +
+Method Summary
+ java.lang.Stringtojstring() + +
+           
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+varname

+
+public LuaString varname
+
+
The local variable name +

+

+
+
+
+ +

+startpc

+
+public int startpc
+
+
The instruction offset when the variable comes into scope +

+

+
+
+
+ +

+endpc

+
+public int endpc
+
+
The instruction offset when the variable goes out of scope +

+

+
+
+ + + + + + + + +
+Constructor Detail
+ +

+LocVars

+
+public LocVars(LuaString varname,
+               int startpc,
+               int endpc)
+
+
Construct a LocVars instance. +

+

+
Parameters:
varname - The local variable name
startpc - The instruction offset when the variable comes into scope
endpc - The instruction offset when the variable goes out of scope
+
+ + + + + + + + +
+Method Detail
+ +

+tojstring

+
+public java.lang.String tojstring()
+
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/Lua.html b/luaj-2.0.3/docs/api/org/luaj/vm2/Lua.html new file mode 100644 index 0000000000..2f048f1eac --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/Lua.html @@ -0,0 +1,2109 @@ + + + + + + +Lua (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class Lua

+
+java.lang.Object
+  extended by org.luaj.vm2.Lua
+
+
+
Direct Known Subclasses:
LuaC, Print
+
+
+
+
public class Lua
extends java.lang.Object
+ + +

+Constants for lua limits and opcodes. +

+ This is a direct translation of C lua distribution header file constants + for bytecode creation and processing. +

+ +

+


+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Field Summary
+static java.lang.String_VERSION + +
+          version is supplied by ant build task
+static intBITRK + +
+          this bit 1 means constant (0 means register)
+static intiABC + +
+           
+static intiABx + +
+           
+static intiAsBx + +
+           
+static intLFIELDS_PER_FLUSH + +
+           
+static intLUA_MULTRET + +
+          use return values from previous op
+static int[]luaP_opmodes + +
+           
+static intMASK_A + +
+           
+static intMASK_B + +
+           
+static intMASK_Bx + +
+           
+static intMASK_C + +
+           
+static intMASK_NOT_A + +
+           
+static intMASK_NOT_B + +
+           
+static intMASK_NOT_Bx + +
+           
+static intMASK_NOT_C + +
+           
+static intMASK_NOT_OP + +
+           
+static intMASK_OP + +
+           
+static intMAX_OP + +
+           
+static intMAXARG_A + +
+           
+static intMAXARG_B + +
+           
+static intMAXARG_Bx + +
+           
+static intMAXARG_C + +
+           
+static intMAXARG_sBx + +
+           
+static intMAXINDEXRK + +
+           
+static intNO_REG + +
+          invalid register that fits in 8 bits
+static intNUM_OPCODES + +
+           
+static intOP_ADD + +
+           
+static intOP_AND + +
+           
+static intOP_CALL + +
+           
+static intOP_CLOSE + +
+           
+static intOP_CLOSURE + +
+           
+static intOP_CONCAT + +
+           
+static intOP_DIV + +
+           
+static intOP_EQ + +
+           
+static intOP_FORLOOP + +
+           
+static intOP_FORPREP + +
+           
+static intOP_GE + +
+           
+static intOP_GETGLOBAL + +
+           
+static intOP_GETTABLE + +
+           
+static intOP_GETUPVAL + +
+           
+static intOP_GT + +
+           
+static intOP_JMP + +
+           
+static intOP_LE + +
+           
+static intOP_LEN + +
+           
+static intOP_LOADBOOL + +
+           
+static intOP_LOADK + +
+           
+static intOP_LOADNIL + +
+           
+static intOP_LT + +
+           
+static intOP_MOD + +
+           
+static intOP_MOVE + +
+           
+static intOP_MUL + +
+           
+static intOP_NEQ + +
+           
+static intOP_NEWTABLE + +
+           
+static intOP_NOT + +
+           
+static intOP_OR + +
+           
+static intOP_POW + +
+           
+static intOP_RETURN + +
+           
+static intOP_SELF + +
+           
+static intOP_SETGLOBAL + +
+           
+static intOP_SETLIST + +
+           
+static intOP_SETTABLE + +
+           
+static intOP_SETUPVAL + +
+           
+static intOP_SUB + +
+           
+static intOP_TAILCALL + +
+           
+static intOP_TEST + +
+           
+static intOP_TESTSET + +
+           
+static intOP_TFORLOOP + +
+           
+static intOP_UNM + +
+           
+static intOP_VARARG + +
+           
+static intOpArgK + +
+           
+static intOpArgN + +
+           
+static intOpArgR + +
+           
+static intOpArgU + +
+           
+static intPOS_A + +
+           
+static intPOS_B + +
+           
+static intPOS_Bx + +
+           
+static intPOS_C + +
+           
+static intPOS_OP + +
+           
+static intSIZE_A + +
+           
+static intSIZE_B + +
+           
+static intSIZE_Bx + +
+           
+static intSIZE_C + +
+           
+static intSIZE_OP + +
+           
+static intVARARG_HASARG + +
+          masks for new-style vararg
+static intVARARG_ISVARARG + +
+           
+static intVARARG_NEEDSARG + +
+           
+  + + + + + + + + + + +
+Constructor Summary
Lua() + +
+           
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+static intGET_OPCODE(int i) + +
+           
+static intGETARG_A(int i) + +
+           
+static intGETARG_B(int i) + +
+           
+static intGETARG_Bx(int i) + +
+           
+static intGETARG_C(int i) + +
+           
+static intGETARG_sBx(int i) + +
+           
+static intgetBMode(int m) + +
+           
+static intgetCMode(int m) + +
+           
+static intgetOpMode(int m) + +
+           
+static intINDEXK(int r) + +
+          gets the index of the constant
+static booleanISK(int x) + +
+          test whether value is a constant
+static intRKASK(int x) + +
+          code a constant index as a RK value
+static booleantestAMode(int m) + +
+           
+static booleantestTMode(int m) + +
+           
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+_VERSION

+
+public static final java.lang.String _VERSION
+
+
version is supplied by ant build task +

+

+
See Also:
Constant Field Values
+
+
+ +

+LUA_MULTRET

+
+public static final int LUA_MULTRET
+
+
use return values from previous op +

+

+
See Also:
Constant Field Values
+
+
+ +

+VARARG_HASARG

+
+public static final int VARARG_HASARG
+
+
masks for new-style vararg +

+

+
See Also:
Constant Field Values
+
+
+ +

+VARARG_ISVARARG

+
+public static final int VARARG_ISVARARG
+
+
+
See Also:
Constant Field Values
+
+
+ +

+VARARG_NEEDSARG

+
+public static final int VARARG_NEEDSARG
+
+
+
See Also:
Constant Field Values
+
+
+ +

+iABC

+
+public static final int iABC
+
+
+
See Also:
Constant Field Values
+
+
+ +

+iABx

+
+public static final int iABx
+
+
+
See Also:
Constant Field Values
+
+
+ +

+iAsBx

+
+public static final int iAsBx
+
+
+
See Also:
Constant Field Values
+
+
+ +

+SIZE_C

+
+public static final int SIZE_C
+
+
+
See Also:
Constant Field Values
+
+
+ +

+SIZE_B

+
+public static final int SIZE_B
+
+
+
See Also:
Constant Field Values
+
+
+ +

+SIZE_Bx

+
+public static final int SIZE_Bx
+
+
+
See Also:
Constant Field Values
+
+
+ +

+SIZE_A

+
+public static final int SIZE_A
+
+
+
See Also:
Constant Field Values
+
+
+ +

+SIZE_OP

+
+public static final int SIZE_OP
+
+
+
See Also:
Constant Field Values
+
+
+ +

+POS_OP

+
+public static final int POS_OP
+
+
+
See Also:
Constant Field Values
+
+
+ +

+POS_A

+
+public static final int POS_A
+
+
+
See Also:
Constant Field Values
+
+
+ +

+POS_C

+
+public static final int POS_C
+
+
+
See Also:
Constant Field Values
+
+
+ +

+POS_B

+
+public static final int POS_B
+
+
+
See Also:
Constant Field Values
+
+
+ +

+POS_Bx

+
+public static final int POS_Bx
+
+
+
See Also:
Constant Field Values
+
+
+ +

+MAX_OP

+
+public static final int MAX_OP
+
+
+
See Also:
Constant Field Values
+
+
+ +

+MAXARG_A

+
+public static final int MAXARG_A
+
+
+
See Also:
Constant Field Values
+
+
+ +

+MAXARG_B

+
+public static final int MAXARG_B
+
+
+
See Also:
Constant Field Values
+
+
+ +

+MAXARG_C

+
+public static final int MAXARG_C
+
+
+
See Also:
Constant Field Values
+
+
+ +

+MAXARG_Bx

+
+public static final int MAXARG_Bx
+
+
+
See Also:
Constant Field Values
+
+
+ +

+MAXARG_sBx

+
+public static final int MAXARG_sBx
+
+
+
See Also:
Constant Field Values
+
+
+ +

+MASK_OP

+
+public static final int MASK_OP
+
+
+
See Also:
Constant Field Values
+
+
+ +

+MASK_A

+
+public static final int MASK_A
+
+
+
See Also:
Constant Field Values
+
+
+ +

+MASK_B

+
+public static final int MASK_B
+
+
+
See Also:
Constant Field Values
+
+
+ +

+MASK_C

+
+public static final int MASK_C
+
+
+
See Also:
Constant Field Values
+
+
+ +

+MASK_Bx

+
+public static final int MASK_Bx
+
+
+
See Also:
Constant Field Values
+
+
+ +

+MASK_NOT_OP

+
+public static final int MASK_NOT_OP
+
+
+
See Also:
Constant Field Values
+
+
+ +

+MASK_NOT_A

+
+public static final int MASK_NOT_A
+
+
+
See Also:
Constant Field Values
+
+
+ +

+MASK_NOT_B

+
+public static final int MASK_NOT_B
+
+
+
See Also:
Constant Field Values
+
+
+ +

+MASK_NOT_C

+
+public static final int MASK_NOT_C
+
+
+
See Also:
Constant Field Values
+
+
+ +

+MASK_NOT_Bx

+
+public static final int MASK_NOT_Bx
+
+
+
See Also:
Constant Field Values
+
+
+ +

+BITRK

+
+public static final int BITRK
+
+
this bit 1 means constant (0 means register) +

+

+
See Also:
Constant Field Values
+
+
+ +

+MAXINDEXRK

+
+public static final int MAXINDEXRK
+
+
+
See Also:
Constant Field Values
+
+
+ +

+NO_REG

+
+public static final int NO_REG
+
+
invalid register that fits in 8 bits +

+

+
See Also:
Constant Field Values
+
+
+ +

+OP_MOVE

+
+public static final int OP_MOVE
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_LOADK

+
+public static final int OP_LOADK
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_LOADBOOL

+
+public static final int OP_LOADBOOL
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_LOADNIL

+
+public static final int OP_LOADNIL
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_GETUPVAL

+
+public static final int OP_GETUPVAL
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_GETGLOBAL

+
+public static final int OP_GETGLOBAL
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_GETTABLE

+
+public static final int OP_GETTABLE
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_SETGLOBAL

+
+public static final int OP_SETGLOBAL
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_SETUPVAL

+
+public static final int OP_SETUPVAL
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_SETTABLE

+
+public static final int OP_SETTABLE
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_NEWTABLE

+
+public static final int OP_NEWTABLE
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_SELF

+
+public static final int OP_SELF
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_ADD

+
+public static final int OP_ADD
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_SUB

+
+public static final int OP_SUB
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_MUL

+
+public static final int OP_MUL
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_DIV

+
+public static final int OP_DIV
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_MOD

+
+public static final int OP_MOD
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_POW

+
+public static final int OP_POW
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_UNM

+
+public static final int OP_UNM
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_NOT

+
+public static final int OP_NOT
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_LEN

+
+public static final int OP_LEN
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_CONCAT

+
+public static final int OP_CONCAT
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_JMP

+
+public static final int OP_JMP
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_EQ

+
+public static final int OP_EQ
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_LT

+
+public static final int OP_LT
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_LE

+
+public static final int OP_LE
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_TEST

+
+public static final int OP_TEST
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_TESTSET

+
+public static final int OP_TESTSET
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_CALL

+
+public static final int OP_CALL
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_TAILCALL

+
+public static final int OP_TAILCALL
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_RETURN

+
+public static final int OP_RETURN
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_FORLOOP

+
+public static final int OP_FORLOOP
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_FORPREP

+
+public static final int OP_FORPREP
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_TFORLOOP

+
+public static final int OP_TFORLOOP
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_SETLIST

+
+public static final int OP_SETLIST
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_CLOSE

+
+public static final int OP_CLOSE
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_CLOSURE

+
+public static final int OP_CLOSURE
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_VARARG

+
+public static final int OP_VARARG
+
+
+
See Also:
Constant Field Values
+
+
+ +

+NUM_OPCODES

+
+public static final int NUM_OPCODES
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_GT

+
+public static final int OP_GT
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_GE

+
+public static final int OP_GE
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_NEQ

+
+public static final int OP_NEQ
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_AND

+
+public static final int OP_AND
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OP_OR

+
+public static final int OP_OR
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OpArgN

+
+public static final int OpArgN
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OpArgU

+
+public static final int OpArgU
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OpArgR

+
+public static final int OpArgR
+
+
+
See Also:
Constant Field Values
+
+
+ +

+OpArgK

+
+public static final int OpArgK
+
+
+
See Also:
Constant Field Values
+
+
+ +

+luaP_opmodes

+
+public static final int[] luaP_opmodes
+
+
+
+
+
+ +

+LFIELDS_PER_FLUSH

+
+public static final int LFIELDS_PER_FLUSH
+
+
+
See Also:
Constant Field Values
+
+ + + + + + + + +
+Constructor Detail
+ +

+Lua

+
+public Lua()
+
+
+ + + + + + + + +
+Method Detail
+ +

+GET_OPCODE

+
+public static int GET_OPCODE(int i)
+
+
+
+
+
+
+ +

+GETARG_A

+
+public static int GETARG_A(int i)
+
+
+
+
+
+
+ +

+GETARG_B

+
+public static int GETARG_B(int i)
+
+
+
+
+
+
+ +

+GETARG_C

+
+public static int GETARG_C(int i)
+
+
+
+
+
+
+ +

+GETARG_Bx

+
+public static int GETARG_Bx(int i)
+
+
+
+
+
+
+ +

+GETARG_sBx

+
+public static int GETARG_sBx(int i)
+
+
+
+
+
+
+ +

+ISK

+
+public static boolean ISK(int x)
+
+
test whether value is a constant +

+

+
+
+
+
+ +

+INDEXK

+
+public static int INDEXK(int r)
+
+
gets the index of the constant +

+

+
+
+
+
+ +

+RKASK

+
+public static int RKASK(int x)
+
+
code a constant index as a RK value +

+

+
+
+
+
+ +

+getOpMode

+
+public static int getOpMode(int m)
+
+
+
+
+
+
+ +

+getBMode

+
+public static int getBMode(int m)
+
+
+
+
+
+
+ +

+getCMode

+
+public static int getCMode(int m)
+
+
+
+
+
+
+ +

+testAMode

+
+public static boolean testAMode(int m)
+
+
+
+
+
+
+ +

+testTMode

+
+public static boolean testTMode(int m)
+
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/LuaBoolean.html b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaBoolean.html new file mode 100644 index 0000000000..cbb6dbdd83 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaBoolean.html @@ -0,0 +1,601 @@ + + + + + + +LuaBoolean (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class LuaBoolean

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaBoolean
+
+
+
+
public final class LuaBoolean
extends LuaValue
+ + +

+Extension of LuaValue which can hold a Java boolean as its value. +

+ These instance are not instantiated directly by clients. + Instead, there are exactly twon instances of this class, + LuaValue.TRUE and LuaValue.FALSE + representing the lua values true and false. + The function LuaValue.valueOf(boolean) will always + return one of these two values. +

+ Any LuaValue can be converted to its equivalent + boolean representation using LuaValue.toboolean() +

+

+ +

+

+
See Also:
LuaValue, +LuaValue.valueOf(boolean), +LuaValue.TRUE, +LuaValue.FALSE
+
+ +

+ + + + + + + + + + + + + + + +
+Field Summary
+static LuaValues_metatable + +
+          Shared static metatable for boolean values represented in lua.
+ booleanv + +
+          The value of the boolean
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ booleanbooleanValue() + +
+          Return the boolean value for this boolean
+ booleancheckboolean() + +
+          Check that the value is a LuaBoolean, + or throw LuaError if not
+ LuaValuegetmetatable() + +
+          Get the metatable for this LuaValue
+ booleanisboolean() + +
+          Check if this is a boolean
+ LuaValuenot() + +
+          Unary not: return inverse boolean value (~this) as defined by lua not operator
+ booleanoptboolean(boolean defval) + +
+          Check that optional argument is a boolean and return its boolean value
+ booleantoboolean() + +
+          Convert to boolean false if LuaValue.NIL or FALSE, true if anything else
+ java.lang.Stringtojstring() + +
+          Convert to human readable String for any type.
+ inttype() + +
+          Get the enumeration value for the type of this value.
+ java.lang.Stringtypename() + +
+          Get the String name of the type of this value.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, call, call, call, call, callmt, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getfenv, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isclosure, isfunction, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, onInvoke, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setfenv, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+s_metatable

+
+public static LuaValue s_metatable
+
+
Shared static metatable for boolean values represented in lua. +

+

+
+
+
+ +

+v

+
+public final boolean v
+
+
The value of the boolean +

+

+
+
+ + + + + + + + +
+Method Detail
+ +

+type

+
+public int type()
+
+
Description copied from class: LuaValue
+
Get the enumeration value for the type of this value. +

+

+
Specified by:
type in class LuaValue
+
+
+ +
Returns:
value for this type, one of + TNIL, + TBOOLEAN, + TNUMBER, + TSTRING, + TTABLE, + TFUNCTION, + TUSERDATA, + TTHREAD
See Also:
LuaValue.typename()
+
+
+
+ +

+typename

+
+public java.lang.String typename()
+
+
Description copied from class: LuaValue
+
Get the String name of the type of this value. +

+

+

+
Specified by:
typename in class LuaValue
+
+
+ +
Returns:
name from type name list LuaValue.TYPE_NAMES + corresponding to the type of this value: + "nil", "boolean", "number", "string", + "table", "function", "userdata", "thread"
See Also:
LuaValue.type()
+
+
+
+ +

+isboolean

+
+public boolean isboolean()
+
+
Description copied from class: LuaValue
+
Check if this is a boolean +

+

+
Overrides:
isboolean in class LuaValue
+
+
+ +
Returns:
true if this is a boolean, otherwise false
See Also:
LuaValue.isboolean(), +LuaValue.toboolean(), +LuaValue.checkboolean(), +LuaValue.optboolean(boolean), +#TOBOLEAN
+
+
+
+ +

+not

+
+public LuaValue not()
+
+
Description copied from class: LuaValue
+
Unary not: return inverse boolean value (~this) as defined by lua not operator +

+

+
Overrides:
not in class LuaValue
+
+
+ +
Returns:
TRUE if NIL or FALSE, otherwise FALSE
+
+
+
+ +

+booleanValue

+
+public boolean booleanValue()
+
+
Return the boolean value for this boolean +

+

+ +
Returns:
value as a Java boolean
+
+
+
+ +

+toboolean

+
+public boolean toboolean()
+
+
Description copied from class: LuaValue
+
Convert to boolean false if LuaValue.NIL or FALSE, true if anything else +

+

+
Overrides:
toboolean in class LuaValue
+
+
+ +
Returns:
Value cast to byte if number or string convertible to number, otherwise 0
See Also:
LuaValue.optboolean(boolean), +LuaValue.checkboolean(), +LuaValue.isboolean(), +TBOOLEAN
+
+
+
+ +

+tojstring

+
+public java.lang.String tojstring()
+
+
Description copied from class: LuaValue
+
Convert to human readable String for any type. +

+

+
Overrides:
tojstring in class LuaValue
+
+
+ +
Returns:
String for use by human readers based on type.
See Also:
LuaValue.tostring(), +LuaValue.optjstring(String), +LuaValue.checkjstring(), +LuaValue.isstring(), +TSTRING
+
+
+
+ +

+optboolean

+
+public boolean optboolean(boolean defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a boolean and return its boolean value +

+

+
Overrides:
optboolean in class LuaValue
+
+
+
Parameters:
defval - boolean value to return if this is nil or none +
Returns:
this cast to boolean if a , + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.checkboolean(), +LuaValue.isboolean(), +LuaValue.TBOOLEAN
+
+
+
+ +

+checkboolean

+
+public boolean checkboolean()
+
+
Description copied from class: LuaValue
+
Check that the value is a LuaBoolean, + or throw LuaError if not +

+

+
Overrides:
checkboolean in class LuaValue
+
+
+ +
Returns:
boolean value for this if it is a LuaBoolean
See Also:
LuaValue.optboolean(boolean), +LuaValue.TBOOLEAN
+
+
+
+ +

+getmetatable

+
+public LuaValue getmetatable()
+
+
Description copied from class: LuaValue
+
Get the metatable for this LuaValue +

+ For LuaTable and LuaUserdata instances, + the metatable returned is this instance metatable. + For all other types, the class metatable value will be returned. +

+

+
Overrides:
getmetatable in class LuaValue
+
+
+ +
Returns:
metatable, or null if it there is none
See Also:
s_metatable, +LuaNumber.s_metatable, +LuaNil.s_metatable, +LuaFunction.s_metatable, +LuaThread.s_metatable
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/LuaClosure.html b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaClosure.html new file mode 100644 index 0000000000..6331e3fe1f --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaClosure.html @@ -0,0 +1,857 @@ + + + + + + +LuaClosure (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class LuaClosure

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.LuaClosure
+
+
+
+
public class LuaClosure
extends LuaFunction
+ + +

+Extension of LuaFunction which executes lua bytecode. +

+ A LuaClosure is a combination of a Prototype + and a LuaValue to use as an environment for execution. +

+ There are three main ways LuaClosure instances are created: +

+

+ To construct it directly, the Prototype is typically created via a compiler such as LuaC: +

 InputStream is = new ByteArrayInputStream("print('hello,world').getBytes());
+ Prototype p = LuaC.instance.compile(is, "script");
+ LuaValue _G = JsePlatform.standardGlobals()
+ LuaClosure f = new LuaClosure(p, _G);
+ 
+

+ To construct it indirectly, the LuaC compiler may be used, + which implements the LoadState.LuaCompiler interface: +

 LuaFunction f = LuaC.instance.load(is, "script", _G);
+ 
+

+ Typically, a closure that has just been loaded needs to be initialized by executing it, + and its return value can be saved if needed: +

 LuaValue r = f.call();
+ _G.set( "mypkg", r ) 
+ 
+

+ In the preceding, the loaded value is typed as LuaFunction + to allow for the possibility of other compilers such as LuaJC + producing LuaFunction directly without + creating a Prototype or LuaClosure. +

+ Since a LuaClosure is a LuaFunction which is a LuaValue, + all the value operations can be used directly such as: +

+

+ +

+

+
See Also:
LuaValue, +LuaFunction, +LuaValue.isclosure(), +LuaValue.checkclosure(), +LuaValue.optclosure(LuaClosure), +LoadState, +LoadState.compiler
+
+ +

+ + + + + + + + + + + + + + + +
+Field Summary
+ Prototypep + +
+           
+ UpValue[]upValues + +
+           
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + + + + + + +
+Constructor Summary
+protected LuaClosure(int nupvalues, + LuaValue env) + +
+           
+ LuaClosure(Prototype p, + LuaValue env) + +
+          Supply the initial environment
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ LuaValuecall() + +
+          Call this with 0 arguments, including metatag processing, + and return only the first return value.
+ LuaValuecall(LuaValue arg) + +
+          Call this with 1 argument, including metatag processing, + and return only the first return value.
+ LuaValuecall(LuaValue arg1, + LuaValue arg2) + +
+          Call this with 2 arguments, including metatag processing, + and return only the first return value.
+ LuaValuecall(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+          Call this with 3 arguments, including metatag processing, + and return only the first return value.
+ LuaClosurecheckclosure() + +
+          Check that the value is a LuaClosure , + or throw LuaError if not
+protected  Varargsexecute(LuaValue[] stack, + Varargs varargs) + +
+           
+ LuaValuegetmetatable() + +
+          Get the metatable for this LuaValue
+protected  LuaValuegetUpvalue(int i) + +
+           
+ Varargsinvoke(Varargs varargs) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ booleanisclosure() + +
+          Check if this is a function that is a closure, + meaning interprets lua bytecode for its execution
+ VarargsonInvoke(Varargs varargs) + +
+          Callback used during tail call processing to invoke the function once.
+ LuaClosureoptclosure(LuaClosure defval) + +
+          Check that optional argument is a closure and return as LuaClosure
+protected  voidsetUpvalue(int i, + LuaValue v) + +
+           
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, optboolean, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+p

+
+public final Prototype p
+
+
+
+
+
+ +

+upValues

+
+public final UpValue[] upValues
+
+
+
+
+ + + + + + + + +
+Constructor Detail
+ +

+LuaClosure

+
+public LuaClosure(Prototype p,
+                  LuaValue env)
+
+
Supply the initial environment +

+

+
+ +

+LuaClosure

+
+protected LuaClosure(int nupvalues,
+                     LuaValue env)
+
+
+ + + + + + + + +
+Method Detail
+ +

+isclosure

+
+public boolean isclosure()
+
+
Description copied from class: LuaValue
+
Check if this is a function that is a closure, + meaning interprets lua bytecode for its execution +

+

+
Overrides:
isclosure in class LuaValue
+
+
+ +
Returns:
true if this is a closure, otherwise false
See Also:
LuaValue.isfunction(), +LuaValue.checkclosure(), +LuaValue.optclosure(LuaClosure), +LuaValue.TFUNCTION
+
+
+
+ +

+optclosure

+
+public LuaClosure optclosure(LuaClosure defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a closure and return as LuaClosure +

+ A LuaClosure is a that executes lua byteccode. +

+

+
Overrides:
optclosure in class LuaValue
+
+
+
Parameters:
defval - LuaClosure to return if this is nil or none +
Returns:
this cast to LuaClosure if a function, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.checkclosure(), +LuaValue.isclosure(), +LuaValue.TFUNCTION
+
+
+
+ +

+checkclosure

+
+public LuaClosure checkclosure()
+
+
Description copied from class: LuaValue
+
Check that the value is a LuaClosure , + or throw LuaError if not +

+ LuaClosure is a subclass of that interprets lua bytecode. +

+

+
Overrides:
checkclosure in class LuaValue
+
+
+ +
Returns:
this cast as LuaClosure
See Also:
LuaValue.checkfunction(), +LuaValue.optclosure(LuaClosure), +LuaValue.isclosure(), +LuaValue.TFUNCTION
+
+
+
+ +

+getmetatable

+
+public LuaValue getmetatable()
+
+
Description copied from class: LuaValue
+
Get the metatable for this LuaValue +

+ For LuaTable and LuaUserdata instances, + the metatable returned is this instance metatable. + For all other types, the class metatable value will be returned. +

+

+
Overrides:
getmetatable in class LuaFunction
+
+
+ +
Returns:
metatable, or null if it there is none
See Also:
LuaBoolean.s_metatable, +LuaNumber.s_metatable, +LuaNil.s_metatable, +LuaFunction.s_metatable, +LuaThread.s_metatable
+
+
+
+ +

+call

+
+public final LuaValue call()
+
+
Description copied from class: LuaValue
+
Call this with 0 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+ +
Returns:
First return value (this()), or NIL if there were none.
See Also:
LuaValue.call(LuaValue), +LuaValue.call(LuaValue,LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +LuaValue.invoke(), +LuaValue.method(String), +LuaValue.method(LuaValue)
+
+
+
+ +

+call

+
+public final LuaValue call(LuaValue arg)
+
+
Description copied from class: LuaValue
+
Call this with 1 argument, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+
Parameters:
arg - First argument to supply to the called function +
Returns:
First return value (this(arg)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue,LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue), +LuaValue.method(String,LuaValue), +LuaValue.method(LuaValue,LuaValue)
+
+
+
+ +

+call

+
+public final LuaValue call(LuaValue arg1,
+                           LuaValue arg2)
+
+
Description copied from class: LuaValue
+
Call this with 2 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+
Parameters:
arg1 - First argument to supply to the called function
arg2 - Second argument to supply to the called function +
Returns:
First return value (this(arg1,arg2)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue,LuaValue), +LuaValue.method(String,LuaValue,LuaValue), +LuaValue.method(LuaValue,LuaValue,LuaValue)
+
+
+
+ +

+call

+
+public final LuaValue call(LuaValue arg1,
+                           LuaValue arg2,
+                           LuaValue arg3)
+
+
Description copied from class: LuaValue
+
Call this with 3 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+
Parameters:
arg1 - First argument to supply to the called function
arg2 - Second argument to supply to the called function
arg3 - Second argument to supply to the called function +
Returns:
First return value (this(arg1,arg2,arg3)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue), +LuaValue.call(LuaValue, LuaValue), +#invoke(LuaValue,LuaValue, LuaValue), +LuaValue.invokemethod(String,Varargs), +LuaValue.invokemethod(LuaValue,Varargs)
+
+
+
+ +

+invoke

+
+public final Varargs invoke(Varargs varargs)
+
+
Description copied from class: LuaValue
+
Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs. +

+ If this is a LuaFunction, call it, and return all values. + Otherwise, look for the CALL metatag and call that. +

+ To get a particular return value, us Varargs.arg(int) +

+ To call this as a method call, use LuaValue.invokemethod(LuaValue) instead. +

+

+
Overrides:
invoke in class LuaValue
+
+
+
Parameters:
varargs - Varargs containing the arguments to supply to the called function +
Returns:
All return values as a Varargs instance.
See Also:
LuaValue.varargsOf(LuaValue[]), +LuaValue.call(LuaValue), +LuaValue.invoke(), +LuaValue.invoke(LuaValue,Varargs), +LuaValue.invokemethod(String,Varargs), +LuaValue.invokemethod(LuaValue,Varargs)
+
+
+
+ +

+onInvoke

+
+public Varargs onInvoke(Varargs varargs)
+
+
Description copied from class: LuaValue
+
Callback used during tail call processing to invoke the function once. +

+ This may return a TailcallVarargs to be evaluated by the client. +

+ This should not be called directly, instead use on of the call invocation functions. +

+

+
Overrides:
onInvoke in class LuaValue
+
+
+
Parameters:
varargs - the arguments to the call invocation. +
Returns:
Varargs the return values, possible a TailcallVarargs.
See Also:
LuaValue.call(), +LuaValue.invoke(), +LuaValue.method(LuaValue), +LuaValue.invokemethod(LuaValue)
+
+
+
+ +

+execute

+
+protected Varargs execute(LuaValue[] stack,
+                          Varargs varargs)
+
+
+
+
+
+
+ +

+getUpvalue

+
+protected LuaValue getUpvalue(int i)
+
+
+
+
+
+
+ +

+setUpvalue

+
+protected void setUpvalue(int i,
+                          LuaValue v)
+
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/LuaDouble.html b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaDouble.html new file mode 100644 index 0000000000..11a9f134b0 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaDouble.html @@ -0,0 +1,3317 @@ + + + + + + +LuaDouble (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class LuaDouble

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaNumber
+              extended by org.luaj.vm2.LuaDouble
+
+
+
+
public class LuaDouble
extends LuaNumber
+ + +

+Extension of LuaNumber which can hold a Java double as its value. +

+ These instance are not instantiated directly by clients, but indirectly + via the static functions LuaValue.valueOf(int) or LuaValue.valueOf(double) + functions. This ensures that values which can be represented as int + are wrapped in LuaInteger instead of LuaDouble. +

+ Almost all API's implemented in LuaDouble are defined and documented in LuaValue. +

+ However the constants NAN, POSINF, NEGINF, + JSTR_NAN, JSTR_POSINF, and JSTR_NEGINF may be useful + when dealing with Nan or Infinite values. +

+ LuaDouble also defines functions for handling the unique math rules of lua devision and modulo in +

+

+

+ +

+

+
See Also:
LuaValue, +LuaNumber, +LuaInteger, +LuaValue.valueOf(int), +LuaValue.valueOf(double)
+
+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Field Summary
+static java.lang.StringJSTR_NAN + +
+          Constant String representation for NaN (not a number), "nan"
+static java.lang.StringJSTR_NEGINF + +
+          Constant String representation for negative infinity, "-inf"
+static java.lang.StringJSTR_POSINF + +
+          Constant String representation for positive infinity, "inf"
+static LuaDoubleNAN + +
+          Constant LuaDouble representing NaN (not a number)
+static LuaDoubleNEGINF + +
+          Constant LuaDouble representing negative infinity
+static LuaDoublePOSINF + +
+          Constant LuaDouble representing positive infinity
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaNumber
s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ LuaValueadd(double lhs) + +
+          Add: Perform numeric add operation with another value + of double type with metatag processing
+ LuaValueadd(LuaValue rhs) + +
+          Add: Perform numeric add operation with another value + including metatag processing.
+ doublecheckdouble() + +
+          Check that the value is numeric and return the value as a double, + or throw LuaError if not numeric
+ intcheckint() + +
+          Check that the value is numeric, and convert and cast value to int, or throw LuaError if not numeric
+ LuaIntegercheckinteger() + +
+          Check that the value is numeric, and convert and cast value to int, or throw LuaError if not numeric
+ java.lang.Stringcheckjstring() + +
+          Convert this value to a Java String.
+ longchecklong() + +
+          Check that the value is numeric, and convert and cast value to long, or throw LuaError if not numeric
+ LuaNumberchecknumber() + +
+          Check that the value is numeric, and return as a LuaNumber if so, or throw LuaError
+ LuaStringcheckstring() + +
+          Check that this is a lua string, or throw LuaError if it is not.
+ LuaValuecheckvalidkey() + +
+          Check that this is a valid key in a table index operation, or throw LuaError if not
+static doubleddiv_d(double lhs, + double rhs) + +
+          Divide two double numbers according to lua math, and return a double result.
+static LuaValueddiv(double lhs, + double rhs) + +
+          Divide two double numbers according to lua math, and return a LuaValue result.
+ LuaValuediv(double rhs) + +
+          Divide: Perform numeric divide operation by another value + of double type without metatag processing
+ LuaValuediv(int rhs) + +
+          Divide: Perform numeric divide operation by another value + of int type without metatag processing
+ LuaValuediv(LuaValue rhs) + +
+          Divide: Perform numeric divide operation by another value + of unknown type, + including metatag processing.
+ LuaValuedivInto(double lhs) + +
+          Reverse-divide: Perform numeric divide operation into another value + with metatag processing
+static doubledmod_d(double lhs, + double rhs) + +
+          Take modulo for double numbers according to lua math, and return a double result.
+static LuaValuedmod(double lhs, + double rhs) + +
+          Take modulo double numbers according to lua math, and return a LuaValue result.
+ booleaneq_b(LuaValue val) + +
+          Equals: Perform equality comparison with another value + including metatag processing using EQ, + and return java boolean
+ LuaValueeq(LuaValue val) + +
+          Equals: Perform equality comparison with another value + including metatag processing using EQ.
+ booleanequals(java.lang.Object o) + +
+           
+ booleangt_b(double rhs) + +
+          Greater than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ booleangt_b(int rhs) + +
+          Greater than: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean.
+ booleangt_b(LuaValue rhs) + +
+          Greater than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ LuaValuegt(double rhs) + +
+          Greater than: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue.
+ LuaValuegt(int rhs) + +
+          Greater than: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue.
+ LuaValuegt(LuaValue rhs) + +
+          Greater than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ booleangteq_b(double rhs) + +
+          Greater than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, + and returning java boolean.
+ booleangteq_b(int rhs) + +
+          Greater than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean.
+ booleangteq_b(LuaValue rhs) + +
+          Greater than or equals: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ LuaValuegteq(double rhs) + +
+          Greater than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue.
+ LuaValuegteq(int rhs) + +
+          Greater than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue.
+ LuaValuegteq(LuaValue rhs) + +
+          Greater than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ inthashCode() + +
+           
+ booleanislong() + +
+          Check if this is a number and is representable by java long + without rounding or truncation
+ booleanisnumber() + +
+          Check if this is a number
+ booleanisstring() + +
+          Check if this is a string
+ booleanlt_b(double rhs) + +
+          Less than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ booleanlt_b(int rhs) + +
+          Less than: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean.
+ booleanlt_b(LuaValue rhs) + +
+          Less than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ LuaValuelt(double rhs) + +
+          Less than: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue.
+ LuaValuelt(int rhs) + +
+          Less than: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue.
+ LuaValuelt(LuaValue rhs) + +
+          Less than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ booleanlteq_b(double rhs) + +
+          Less than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, + and returning java boolean.
+ booleanlteq_b(int rhs) + +
+          Less than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean.
+ booleanlteq_b(LuaValue rhs) + +
+          Less than or equals: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ LuaValuelteq(double rhs) + +
+          Less than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue.
+ LuaValuelteq(int rhs) + +
+          Less than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue.
+ LuaValuelteq(LuaValue rhs) + +
+          Less than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ LuaValuemod(double rhs) + +
+          Modulo: Perform numeric modulo operation with another value + of double type without metatag processing
+ LuaValuemod(int rhs) + +
+          Modulo: Perform numeric modulo operation with another value + of int type without metatag processing
+ LuaValuemod(LuaValue rhs) + +
+          Modulo: Perform numeric modulo operation with another value + of unknown type, + including metatag processing.
+ LuaValuemodFrom(double lhs) + +
+          Reverse-modulo: Perform numeric modulo operation from another value + with metatag processing
+ LuaValuemul(double lhs) + +
+          Multiply: Perform numeric multiply operation with another value + of double type with metatag processing
+ LuaValuemul(int lhs) + +
+          Multiply: Perform numeric multiply operation with another value + of int type with metatag processing
+ LuaValuemul(LuaValue rhs) + +
+          Multiply: Perform numeric multiply operation with another value + of unknown type, + including metatag processing.
+ LuaValueneg() + +
+          Unary minus: return negative value (-this) as defined by lua unary minus operator
+ doubleoptdouble(double defval) + +
+          Check that optional argument is a number or string convertible to number and return as double
+ intoptint(int defval) + +
+          Check that optional argument is a number or string convertible to number and return as int
+ LuaIntegeroptinteger(LuaInteger defval) + +
+          Check that optional argument is a number or string convertible to number and return as LuaInteger
+ java.lang.Stringoptjstring(java.lang.String defval) + +
+          Check that optional argument is a string or number and return as Java String
+ longoptlong(long defval) + +
+          Check that optional argument is a number or string convertible to number and return as long
+ LuaNumberoptnumber(LuaNumber defval) + +
+          Check that optional argument is a number or string convertible to number and return as LuaNumber
+ LuaStringoptstring(LuaString defval) + +
+          Check that optional argument is a string or number and return as LuaString
+ LuaValuepow(double rhs) + +
+          Raise to power: Raise this value to a power + of double type with metatag processing
+ LuaValuepow(int rhs) + +
+          Raise to power: Raise this value to a power + of int type with metatag processing
+ LuaValuepow(LuaValue rhs) + +
+          Raise to power: Raise this value to a power + including metatag processing.
+ LuaValuepowWith(double lhs) + +
+          Reverse-raise to power: Raise another value of double type to this power + with metatag processing
+ LuaValuepowWith(int lhs) + +
+          Reverse-raise to power: Raise another value of double type to this power + with metatag processing
+ booleanraweq(double val) + +
+          Equals: Perform direct equality comparison with a double value + without metatag processing.
+ booleanraweq(int val) + +
+          Equals: Perform direct equality comparison with a int value + without metatag processing.
+ booleanraweq(LuaValue val) + +
+          Equals: Perform direct equality comparison with another value + without metatag processing.
+ intstrcmp(LuaString rhs) + +
+          Perform string comparison with another value + known to be a LuaString + using string comparison based on byte values.
+ LuaStringstrvalue() + +
+          Convert this value to a string if it is a LuaString or LuaNumber, + or throw a LuaError if it is not
+ LuaValuesub(double rhs) + +
+          Subtract: Perform numeric subtract operation with another value + of double type with metatag processing
+ LuaValuesub(int rhs) + +
+          Subtract: Perform numeric subtract operation with another value + of int type with metatag processing
+ LuaValuesub(LuaValue rhs) + +
+          Subtract: Perform numeric subtract operation with another value + of unknown type, + including metatag processing.
+ LuaValuesubFrom(double lhs) + +
+          Reverse-subtract: Perform numeric subtract operation from an int value + with metatag processing
+ bytetobyte() + +
+          Convert to byte if numeric, or 0 if not.
+ chartochar() + +
+          Convert to char if numeric, or 0 if not.
+ doubletodouble() + +
+          Convert to double if numeric, or 0 if not.
+ floattofloat() + +
+          Convert to float if numeric, or 0 if not.
+ inttoint() + +
+          Convert to int if numeric, or 0 if not.
+ java.lang.Stringtojstring() + +
+          Convert to human readable String for any type.
+ longtolong() + +
+          Convert to long if numeric, or 0 if not.
+ LuaValuetonumber() + +
+          Conditionally convert to lua number without throwing errors.
+ shorttoshort() + +
+          Convert to short if numeric, or 0 if not.
+ LuaValuetostring() + +
+          Conditionally convert to lua string without throwing errors.
+static LuaNumbervalueOf(double d) + +
+           
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaNumber
checknumber, concat, concat, concatTo, concatTo, getmetatable, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, call, call, call, call, callmt, checkboolean, checkclosure, checkfunction, checkmetatag, checknotnil, checktable, checkthread, checkuserdata, checkuserdata, compareerror, compareerror, comparemt, concatmt, concatTo, eqmtcall, error, get, get, get, getfenv, getn, gettable, illegal, inext, invoke, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isfunction, isint, isinttype, isnil, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, metatag, method, method, method, method, method, method, narg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optfunction, opttable, optthread, optuserdata, optuserdata, optvalue, or, presize, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setfenv, setmetatable, settable, strcmp, strongkey, strongvalue, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+NAN

+
+public static final LuaDouble NAN
+
+
Constant LuaDouble representing NaN (not a number) +

+

+
+
+
+ +

+POSINF

+
+public static final LuaDouble POSINF
+
+
Constant LuaDouble representing positive infinity +

+

+
+
+
+ +

+NEGINF

+
+public static final LuaDouble NEGINF
+
+
Constant LuaDouble representing negative infinity +

+

+
+
+
+ +

+JSTR_NAN

+
+public static final java.lang.String JSTR_NAN
+
+
Constant String representation for NaN (not a number), "nan" +

+

+
See Also:
Constant Field Values
+
+
+ +

+JSTR_POSINF

+
+public static final java.lang.String JSTR_POSINF
+
+
Constant String representation for positive infinity, "inf" +

+

+
See Also:
Constant Field Values
+
+
+ +

+JSTR_NEGINF

+
+public static final java.lang.String JSTR_NEGINF
+
+
Constant String representation for negative infinity, "-inf" +

+

+
See Also:
Constant Field Values
+
+ + + + + + + + +
+Method Detail
+ +

+valueOf

+
+public static LuaNumber valueOf(double d)
+
+
+
+
+
+
+ +

+hashCode

+
+public int hashCode()
+
+
+
Overrides:
hashCode in class java.lang.Object
+
+
+
+
+
+
+ +

+islong

+
+public boolean islong()
+
+
Description copied from class: LuaValue
+
Check if this is a number and is representable by java long + without rounding or truncation +

+

+
Overrides:
islong in class LuaValue
+
+
+ +
Returns:
true if this is a number + meaning derives from LuaNumber + or derives from LuaString and is convertible to a number, + and can be represented by long, + otherwise false
See Also:
LuaValue.tonumber(), +LuaValue.checklong(), +LuaValue.optlong(long), +LuaValue.TNUMBER
+
+
+
+ +

+tobyte

+
+public byte tobyte()
+
+
Description copied from class: LuaValue
+
Convert to byte if numeric, or 0 if not. +

+

+
Overrides:
tobyte in class LuaValue
+
+
+ +
Returns:
Value cast to byte if number or string convertible to number, otherwise 0
See Also:
LuaValue.toint(), +LuaValue.todouble(), +#optbyte(byte), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+tochar

+
+public char tochar()
+
+
Description copied from class: LuaValue
+
Convert to char if numeric, or 0 if not. +

+

+
Overrides:
tochar in class LuaValue
+
+
+ +
Returns:
Value cast to char if number or string convertible to number, otherwise 0
See Also:
LuaValue.toint(), +LuaValue.todouble(), +#optchar(char), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+todouble

+
+public double todouble()
+
+
Description copied from class: LuaValue
+
Convert to double if numeric, or 0 if not. +

+

+
Overrides:
todouble in class LuaValue
+
+
+ +
Returns:
Value cast to double if number or string convertible to number, otherwise 0
See Also:
LuaValue.toint(), +LuaValue.tobyte(), +LuaValue.tochar(), +LuaValue.toshort(), +LuaValue.tolong(), +LuaValue.tofloat(), +LuaValue.optdouble(double), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+tofloat

+
+public float tofloat()
+
+
Description copied from class: LuaValue
+
Convert to float if numeric, or 0 if not. +

+

+
Overrides:
tofloat in class LuaValue
+
+
+ +
Returns:
Value cast to float if number or string convertible to number, otherwise 0
See Also:
LuaValue.toint(), +LuaValue.todouble(), +#optfloat(float), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+toint

+
+public int toint()
+
+
Description copied from class: LuaValue
+
Convert to int if numeric, or 0 if not. +

+

+
Overrides:
toint in class LuaValue
+
+
+ +
Returns:
Value cast to int if number or string convertible to number, otherwise 0
See Also:
LuaValue.tobyte(), +LuaValue.tochar(), +LuaValue.toshort(), +LuaValue.tolong(), +LuaValue.tofloat(), +LuaValue.todouble(), +LuaValue.optint(int), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+tolong

+
+public long tolong()
+
+
Description copied from class: LuaValue
+
Convert to long if numeric, or 0 if not. +

+

+
Overrides:
tolong in class LuaValue
+
+
+ +
Returns:
Value cast to long if number or string convertible to number, otherwise 0
See Also:
LuaValue.isint(), +LuaValue.isinttype(), +LuaValue.toint(), +LuaValue.todouble(), +LuaValue.optlong(long), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+toshort

+
+public short toshort()
+
+
Description copied from class: LuaValue
+
Convert to short if numeric, or 0 if not. +

+

+
Overrides:
toshort in class LuaValue
+
+
+ +
Returns:
Value cast to short if number or string convertible to number, otherwise 0
See Also:
LuaValue.toint(), +LuaValue.todouble(), +#optshort(short), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+optdouble

+
+public double optdouble(double defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a number or string convertible to number and return as double +

+

+
Overrides:
optdouble in class LuaValue
+
+
+
Parameters:
defval - double to return if this is nil or none +
Returns:
this cast to double if numeric, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.optint(int), +LuaValue.optinteger(LuaInteger), +LuaValue.checkdouble(), +LuaValue.todouble(), +LuaValue.tonumber(), +LuaValue.isnumber(), +LuaValue.TNUMBER
+
+
+
+ +

+optint

+
+public int optint(int defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a number or string convertible to number and return as int +

+

+
Overrides:
optint in class LuaValue
+
+
+
Parameters:
defval - int to return if this is nil or none +
Returns:
this cast to int if numeric, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.optdouble(double), +LuaValue.optlong(long), +LuaValue.optinteger(LuaInteger), +LuaValue.checkint(), +LuaValue.toint(), +LuaValue.tonumber(), +LuaValue.isnumber(), +LuaValue.TNUMBER
+
+
+
+ +

+optinteger

+
+public LuaInteger optinteger(LuaInteger defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a number or string convertible to number and return as LuaInteger +

+

+
Overrides:
optinteger in class LuaValue
+
+
+
Parameters:
defval - LuaInteger to return if this is nil or none +
Returns:
this converted and wrapped in LuaInteger if numeric, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.optdouble(double), +LuaValue.optint(int), +LuaValue.checkint(), +LuaValue.toint(), +LuaValue.tonumber(), +LuaValue.isnumber(), +LuaValue.TNUMBER
+
+
+
+ +

+optlong

+
+public long optlong(long defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a number or string convertible to number and return as long +

+

+
Overrides:
optlong in class LuaValue
+
+
+
Parameters:
defval - long to return if this is nil or none +
Returns:
this cast to long if numeric, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.optdouble(double), +LuaValue.optint(int), +LuaValue.checkint(), +LuaValue.toint(), +LuaValue.tonumber(), +LuaValue.isnumber(), +LuaValue.TNUMBER
+
+
+
+ +

+checkinteger

+
+public LuaInteger checkinteger()
+
+
Description copied from class: LuaValue
+
Check that the value is numeric, and convert and cast value to int, or throw LuaError if not numeric +

+ Values that are LuaNumber will be cast to int and may lose precision. + Values that are LuaString that can be converted to a number will be converted, + then cast to int, so may also lose precision. +

+

+
Overrides:
checkinteger in class LuaValue
+
+
+ +
Returns:
value cast to a int and wrapped in LuaInteger if numeric
See Also:
LuaValue.checkint(), +LuaValue.checklong(), +LuaValue.checkdouble(), +LuaValue.optinteger(LuaInteger), +LuaValue.TNUMBER
+
+
+
+ +

+neg

+
+public LuaValue neg()
+
+
Description copied from class: LuaValue
+
Unary minus: return negative value (-this) as defined by lua unary minus operator +

+

+
Overrides:
neg in class LuaValue
+
+
+ +
Returns:
boolean inverse as LuaBoolean if boolean or nil, + numeric inverse as if numeric, + or metatag processing result if UNM metatag is defined
+
+
+
+ +

+equals

+
+public boolean equals(java.lang.Object o)
+
+
+
Overrides:
equals in class LuaValue
+
+
+
+
+
+
+ +

+eq

+
+public LuaValue eq(LuaValue val)
+
+
Description copied from class: LuaValue
+
Equals: Perform equality comparison with another value + including metatag processing using EQ. +

+

+
Overrides:
eq in class LuaValue
+
+
+
Parameters:
val - The value to compare with. +
Returns:
TRUE if values are comparable and (this == rhs), + FALSE if comparable but not equal, + LuaValue if metatag processing occurs.
See Also:
LuaValue.eq_b(LuaValue), +LuaValue.raweq(LuaValue), +LuaValue.neq(LuaValue), +LuaValue.eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue), +LuaValue.EQ
+
+
+
+ +

+eq_b

+
+public boolean eq_b(LuaValue val)
+
+
Description copied from class: LuaValue
+
Equals: Perform equality comparison with another value + including metatag processing using EQ, + and return java boolean +

+

+
Overrides:
eq_b in class LuaValue
+
+
+
Parameters:
val - The value to compare with. +
Returns:
true if values are comparable and (this == rhs), + false if comparable but not equal, + result converted to java boolean if metatag processing occurs.
See Also:
LuaValue.eq(LuaValue), +LuaValue.raweq(LuaValue), +LuaValue.neq_b(LuaValue), +LuaValue.eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue), +LuaValue.EQ
+
+
+
+ +

+raweq

+
+public boolean raweq(LuaValue val)
+
+
Description copied from class: LuaValue
+
Equals: Perform direct equality comparison with another value + without metatag processing. +

+

+
Overrides:
raweq in class LuaValue
+
+
+
Parameters:
val - The value to compare with. +
Returns:
true if (this == rhs), false otherwise
See Also:
LuaValue.eq(LuaValue), +LuaValue.raweq(LuaUserdata), +LuaValue.raweq(LuaString), +LuaValue.raweq(double), +LuaValue.raweq(int), +LuaValue.EQ
+
+
+
+ +

+raweq

+
+public boolean raweq(double val)
+
+
Description copied from class: LuaValue
+
Equals: Perform direct equality comparison with a double value + without metatag processing. +

+

+
Overrides:
raweq in class LuaValue
+
+
+
Parameters:
val - The double value to compare with. +
Returns:
true if this is a LuaNumber + whose value equals val, + otherwise false
+
+
+
+ +

+raweq

+
+public boolean raweq(int val)
+
+
Description copied from class: LuaValue
+
Equals: Perform direct equality comparison with a int value + without metatag processing. +

+

+
Overrides:
raweq in class LuaValue
+
+
+
Parameters:
val - The double value to compare with. +
Returns:
true if this is a LuaNumber + whose value equals val, + otherwise false
+
+
+
+ +

+add

+
+public LuaValue add(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Add: Perform numeric add operation with another value + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
add in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the add with +
Returns:
value of (this + rhs) if both are numeric, + or LuaValue if metatag processing occurs
See Also:
LuaValue.arithmt(LuaValue, LuaValue)
+
+
+
+ +

+add

+
+public LuaValue add(double lhs)
+
+
Description copied from class: LuaValue
+
Add: Perform numeric add operation with another value + of double type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
add in class LuaValue
+
+
+
Parameters:
lhs - The right-hand-side value to perform the add with +
Returns:
value of (this + rhs) if this is numeric
See Also:
LuaValue.add(LuaValue)
+
+
+
+ +

+sub

+
+public LuaValue sub(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Subtract: Perform numeric subtract operation with another value + of unknown type, + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
sub in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the subtract with +
Returns:
value of (this - rhs) if both are numeric, + or LuaValue if metatag processing occurs
See Also:
LuaValue.arithmt(LuaValue, LuaValue)
+
+
+
+ +

+sub

+
+public LuaValue sub(double rhs)
+
+
Description copied from class: LuaValue
+
Subtract: Perform numeric subtract operation with another value + of double type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
sub in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the subtract with +
Returns:
value of (this - rhs) if this is numeric
See Also:
LuaValue.sub(LuaValue)
+
+
+
+ +

+sub

+
+public LuaValue sub(int rhs)
+
+
Description copied from class: LuaValue
+
Subtract: Perform numeric subtract operation with another value + of int type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
sub in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the subtract with +
Returns:
value of (this - rhs) if this is numeric
See Also:
LuaValue.sub(LuaValue)
+
+
+
+ +

+subFrom

+
+public LuaValue subFrom(double lhs)
+
+
Description copied from class: LuaValue
+
Reverse-subtract: Perform numeric subtract operation from an int value + with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
subFrom in class LuaValue
+
+
+
Parameters:
lhs - The left-hand-side value from which to perform the subtraction +
Returns:
value of (lhs - this) if this is numeric
See Also:
LuaValue.sub(LuaValue), +LuaValue.sub(double), +LuaValue.sub(int)
+
+
+
+ +

+mul

+
+public LuaValue mul(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Multiply: Perform numeric multiply operation with another value + of unknown type, + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
mul in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the multiply with +
Returns:
value of (this * rhs) if both are numeric, + or LuaValue if metatag processing occurs
See Also:
LuaValue.arithmt(LuaValue, LuaValue)
+
+
+
+ +

+mul

+
+public LuaValue mul(double lhs)
+
+
Description copied from class: LuaValue
+
Multiply: Perform numeric multiply operation with another value + of double type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
mul in class LuaValue
+
+
+
Parameters:
lhs - The right-hand-side value to perform the multiply with +
Returns:
value of (this * rhs) if this is numeric
See Also:
LuaValue.mul(LuaValue)
+
+
+
+ +

+mul

+
+public LuaValue mul(int lhs)
+
+
Description copied from class: LuaValue
+
Multiply: Perform numeric multiply operation with another value + of int type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
mul in class LuaValue
+
+
+
Parameters:
lhs - The right-hand-side value to perform the multiply with +
Returns:
value of (this * rhs) if this is numeric
See Also:
LuaValue.mul(LuaValue)
+
+
+
+ +

+pow

+
+public LuaValue pow(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Raise to power: Raise this value to a power + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
pow in class LuaValue
+
+
+
Parameters:
rhs - The power to raise this value to +
Returns:
value of (this ^ rhs) if both are numeric, + or LuaValue if metatag processing occurs
See Also:
LuaValue.arithmt(LuaValue, LuaValue)
+
+
+
+ +

+pow

+
+public LuaValue pow(double rhs)
+
+
Description copied from class: LuaValue
+
Raise to power: Raise this value to a power + of double type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
pow in class LuaValue
+
+
+
Parameters:
rhs - The power to raise this value to +
Returns:
value of (this ^ rhs) if this is numeric
See Also:
LuaValue.pow(LuaValue)
+
+
+
+ +

+pow

+
+public LuaValue pow(int rhs)
+
+
Description copied from class: LuaValue
+
Raise to power: Raise this value to a power + of int type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
pow in class LuaValue
+
+
+
Parameters:
rhs - The power to raise this value to +
Returns:
value of (this ^ rhs) if this is numeric
See Also:
LuaValue.pow(LuaValue)
+
+
+
+ +

+powWith

+
+public LuaValue powWith(double lhs)
+
+
Description copied from class: LuaValue
+
Reverse-raise to power: Raise another value of double type to this power + with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
powWith in class LuaValue
+
+
+
Parameters:
lhs - The left-hand-side value which will be raised to this power +
Returns:
value of (lhs ^ this) if this is numeric
See Also:
LuaValue.pow(LuaValue), +LuaValue.pow(double), +LuaValue.pow(int)
+
+
+
+ +

+powWith

+
+public LuaValue powWith(int lhs)
+
+
Description copied from class: LuaValue
+
Reverse-raise to power: Raise another value of double type to this power + with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
powWith in class LuaValue
+
+
+
Parameters:
lhs - The left-hand-side value which will be raised to this power +
Returns:
value of (lhs ^ this) if this is numeric
See Also:
LuaValue.pow(LuaValue), +LuaValue.pow(double), +LuaValue.pow(int)
+
+
+
+ +

+div

+
+public LuaValue div(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Divide: Perform numeric divide operation by another value + of unknown type, + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
div in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the divulo with +
Returns:
value of (this / rhs) if both are numeric, + or LuaValue if metatag processing occurs
See Also:
LuaValue.arithmt(LuaValue, LuaValue)
+
+
+
+ +

+div

+
+public LuaValue div(double rhs)
+
+
Description copied from class: LuaValue
+
Divide: Perform numeric divide operation by another value + of double type without metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+ For metatag processing LuaValue.div(LuaValue) must be used +

+

+
Overrides:
div in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the divulo with +
Returns:
value of (this / rhs) if this is numeric
See Also:
LuaValue.div(LuaValue)
+
+
+
+ +

+div

+
+public LuaValue div(int rhs)
+
+
Description copied from class: LuaValue
+
Divide: Perform numeric divide operation by another value + of int type without metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+ For metatag processing LuaValue.div(LuaValue) must be used +

+

+
Overrides:
div in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the divulo with +
Returns:
value of (this / rhs) if this is numeric
See Also:
LuaValue.div(LuaValue)
+
+
+
+ +

+divInto

+
+public LuaValue divInto(double lhs)
+
+
Description copied from class: LuaValue
+
Reverse-divide: Perform numeric divide operation into another value + with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
divInto in class LuaValue
+
+
+
Parameters:
lhs - The left-hand-side value which will be divided by this +
Returns:
value of (lhs / this) if this is numeric
See Also:
LuaValue.div(LuaValue), +LuaValue.div(double), +LuaValue.div(int)
+
+
+
+ +

+mod

+
+public LuaValue mod(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Modulo: Perform numeric modulo operation with another value + of unknown type, + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
mod in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the modulo with +
Returns:
value of (this % rhs) if both are numeric, + or LuaValue if metatag processing occurs
See Also:
LuaValue.arithmt(LuaValue, LuaValue)
+
+
+
+ +

+mod

+
+public LuaValue mod(double rhs)
+
+
Description copied from class: LuaValue
+
Modulo: Perform numeric modulo operation with another value + of double type without metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+ For metatag processing LuaValue.mod(LuaValue) must be used +

+

+
Overrides:
mod in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the modulo with +
Returns:
value of (this % rhs) if this is numeric
See Also:
LuaValue.mod(LuaValue)
+
+
+
+ +

+mod

+
+public LuaValue mod(int rhs)
+
+
Description copied from class: LuaValue
+
Modulo: Perform numeric modulo operation with another value + of int type without metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+ For metatag processing LuaValue.mod(LuaValue) must be used +

+

+
Overrides:
mod in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the modulo with +
Returns:
value of (this % rhs) if this is numeric
See Also:
LuaValue.mod(LuaValue)
+
+
+
+ +

+modFrom

+
+public LuaValue modFrom(double lhs)
+
+
Description copied from class: LuaValue
+
Reverse-modulo: Perform numeric modulo operation from another value + with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
modFrom in class LuaValue
+
+
+
Parameters:
lhs - The left-hand-side value which will be modulo'ed by this +
Returns:
value of (lhs % this) if this is numeric
See Also:
LuaValue.mod(LuaValue), +LuaValue.mod(double), +LuaValue.mod(int)
+
+
+
+ +

+ddiv

+
+public static LuaValue ddiv(double lhs,
+                            double rhs)
+
+
Divide two double numbers according to lua math, and return a LuaValue result. +

+

+
Parameters:
lhs - Left-hand-side of the division.
rhs - Right-hand-side of the division. +
Returns:
LuaValue for the result of the division, + taking into account positive and negiative infinity, and Nan
See Also:
ddiv_d(double, double)
+
+
+
+ +

+ddiv_d

+
+public static double ddiv_d(double lhs,
+                            double rhs)
+
+
Divide two double numbers according to lua math, and return a double result. +

+

+
Parameters:
lhs - Left-hand-side of the division.
rhs - Right-hand-side of the division. +
Returns:
Value of the division, taking into account positive and negative infinity, and Nan
See Also:
ddiv(double, double)
+
+
+
+ +

+dmod

+
+public static LuaValue dmod(double lhs,
+                            double rhs)
+
+
Take modulo double numbers according to lua math, and return a LuaValue result. +

+

+
Parameters:
lhs - Left-hand-side of the modulo.
rhs - Right-hand-side of the modulo. +
Returns:
LuaValue for the result of the modulo, + using lua's rules for modulo
See Also:
dmod_d(double, double)
+
+
+
+ +

+dmod_d

+
+public static double dmod_d(double lhs,
+                            double rhs)
+
+
Take modulo for double numbers according to lua math, and return a double result. +

+

+
Parameters:
lhs - Left-hand-side of the modulo.
rhs - Right-hand-side of the modulo. +
Returns:
double value for the result of the modulo, + using lua's rules for modulo
See Also:
dmod(double, double)
+
+
+
+ +

+lt

+
+public LuaValue lt(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Less than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
lt in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this < rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lt

+
+public LuaValue lt(double rhs)
+
+
Description copied from class: LuaValue
+
Less than: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
lt in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this < rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(double), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lt

+
+public LuaValue lt(int rhs)
+
+
Description copied from class: LuaValue
+
Less than: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
lt in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this < rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(int), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lt_b

+
+public boolean lt_b(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Less than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
lt_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this < rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lt_b

+
+public boolean lt_b(int rhs)
+
+
Description copied from class: LuaValue
+
Less than: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
lt_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this < rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(int), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lt_b

+
+public boolean lt_b(double rhs)
+
+
Description copied from class: LuaValue
+
Less than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
lt_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this < rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq

+
+public LuaValue lteq(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Less than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
lteq in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this <= rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq

+
+public LuaValue lteq(double rhs)
+
+
Description copied from class: LuaValue
+
Less than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
lteq in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this <= rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(double), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq

+
+public LuaValue lteq(int rhs)
+
+
Description copied from class: LuaValue
+
Less than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
lteq in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this <= rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(int), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq_b

+
+public boolean lteq_b(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Less than or equals: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
lteq_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this <= rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq_b

+
+public boolean lteq_b(int rhs)
+
+
Description copied from class: LuaValue
+
Less than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
lteq_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this <= rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(int), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq_b

+
+public boolean lteq_b(double rhs)
+
+
Description copied from class: LuaValue
+
Less than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
lteq_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this <= rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(double), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt

+
+public LuaValue gt(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Greater than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
gt in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this > rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt

+
+public LuaValue gt(double rhs)
+
+
Description copied from class: LuaValue
+
Greater than: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
gt in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this > rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(double), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt

+
+public LuaValue gt(int rhs)
+
+
Description copied from class: LuaValue
+
Greater than: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
gt in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this > rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(int), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt_b

+
+public boolean gt_b(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Greater than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
gt_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this > rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt_b

+
+public boolean gt_b(int rhs)
+
+
Description copied from class: LuaValue
+
Greater than: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
gt_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this > rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(int), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt_b

+
+public boolean gt_b(double rhs)
+
+
Description copied from class: LuaValue
+
Greater than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
gt_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this > rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq

+
+public LuaValue gteq(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Greater than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
gteq in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this >= rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq

+
+public LuaValue gteq(double rhs)
+
+
Description copied from class: LuaValue
+
Greater than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
gteq in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this >= rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(double), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq

+
+public LuaValue gteq(int rhs)
+
+
Description copied from class: LuaValue
+
Greater than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
gteq in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this >= rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(int), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq_b

+
+public boolean gteq_b(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Greater than or equals: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
gteq_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this >= rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq_b

+
+public boolean gteq_b(int rhs)
+
+
Description copied from class: LuaValue
+
Greater than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
gteq_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this >= rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(int), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq_b

+
+public boolean gteq_b(double rhs)
+
+
Description copied from class: LuaValue
+
Greater than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
gteq_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this >= rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(double), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+strcmp

+
+public int strcmp(LuaString rhs)
+
+
Description copied from class: LuaValue
+
Perform string comparison with another value + known to be a LuaString + using string comparison based on byte values. +

+ Only strings can be compared, meaning + each operand must derive from LuaString. +

+

+
Overrides:
strcmp in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with
+
+
+
+ +

+tojstring

+
+public java.lang.String tojstring()
+
+
Description copied from class: LuaValue
+
Convert to human readable String for any type. +

+

+
Overrides:
tojstring in class LuaValue
+
+
+ +
Returns:
String for use by human readers based on type.
See Also:
LuaValue.tostring(), +LuaValue.optjstring(String), +LuaValue.checkjstring(), +LuaValue.isstring(), +TSTRING
+
+
+
+ +

+strvalue

+
+public LuaString strvalue()
+
+
Description copied from class: LuaValue
+
Convert this value to a string if it is a LuaString or LuaNumber, + or throw a LuaError if it is not +

+

+
Overrides:
strvalue in class LuaValue
+
+
+ +
Returns:
LuaString corresponding to the value if a string or number
+
+
+
+ +

+optstring

+
+public LuaString optstring(LuaString defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a string or number and return as LuaString +

+

+
Overrides:
optstring in class LuaValue
+
+
+
Parameters:
defval - LuaString to return if this is nil or none +
Returns:
this converted to LuaString if a string or number, + defval if nil or none, + throws LuaError if some other type
See Also:
LuaValue.tojstring(), +LuaValue.optjstring(String), +LuaValue.checkstring(), +LuaValue.toString(), +LuaValue.TSTRING
+
+
+
+ +

+tostring

+
+public LuaValue tostring()
+
+
Description copied from class: LuaValue
+
Conditionally convert to lua string without throwing errors. +

+ In lua all numbers are strings, so this function will return + the LuaValue this if it is a string or number, + and NIL for all other cases. +

+ This allows values to be tested for their "string-ness" without + the penalty of throwing exceptions. +

+

+
Overrides:
tostring in class LuaValue
+
+
+ +
Returns:
this if it is a LuaString or LuaNumber, + otherwise NIL
See Also:
LuaValue.tonumber(), +LuaValue.tojstring(), +LuaValue.optstring(LuaString), +LuaValue.checkstring(), +LuaValue.toString()
+
+
+
+ +

+optjstring

+
+public java.lang.String optjstring(java.lang.String defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a string or number and return as Java String +

+

+
Overrides:
optjstring in class LuaValue
+
+
+
Parameters:
defval - LuaString to return if this is nil or none +
Returns:
this converted to String if a string or number, + defval if nil or none, + throws LuaError if some other type
See Also:
LuaValue.tojstring(), +LuaValue.optstring(LuaString), +LuaValue.checkjstring(), +LuaValue.toString(), +LuaValue.TSTRING
+
+
+
+ +

+optnumber

+
+public LuaNumber optnumber(LuaNumber defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a number or string convertible to number and return as LuaNumber +

+

+
Overrides:
optnumber in class LuaNumber
+
+
+
Parameters:
defval - LuaNumber to return if this is nil or none +
Returns:
this cast to LuaNumber if numeric, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.optdouble(double), +LuaValue.optlong(long), +LuaValue.optint(int), +LuaValue.checkint(), +LuaValue.toint(), +LuaValue.tonumber(), +LuaValue.isnumber(), +LuaValue.TNUMBER
+
+
+
+ +

+isnumber

+
+public boolean isnumber()
+
+
Description copied from class: LuaValue
+
Check if this is a number +

+

+
Overrides:
isnumber in class LuaNumber
+
+
+ +
Returns:
true if this is a number, + meaning derives from LuaNumber + or derives from LuaString and is convertible to a number, + otherwise false
See Also:
LuaValue.tonumber(), +LuaValue.checknumber(), +LuaValue.optnumber(LuaNumber), +LuaValue.TNUMBER
+
+
+
+ +

+isstring

+
+public boolean isstring()
+
+
Description copied from class: LuaValue
+
Check if this is a string +

+

+
Overrides:
isstring in class LuaNumber
+
+
+ +
Returns:
true if this is a string, + meaning derives from LuaString or LuaNumber, + otherwise false
See Also:
LuaValue.tostring(), +LuaValue.checkstring(), +LuaValue.optstring(LuaString), +LuaValue.TSTRING
+
+
+
+ +

+tonumber

+
+public LuaValue tonumber()
+
+
Description copied from class: LuaValue
+
Conditionally convert to lua number without throwing errors. +

+ In lua all numbers are strings, but not all strings are numbers. + This function will return + the LuaValue this if it is a number + or a string convertible to a number, + and NIL for all other cases. +

+ This allows values to be tested for their "numeric-ness" without + the penalty of throwing exceptions, + nor the cost of converting the type and creating storage for it. +

+

+
Overrides:
tonumber in class LuaNumber
+
+
+ +
Returns:
this if it is a LuaNumber + or LuaString that can be converted to a number, + otherwise LuaValue.NIL
See Also:
LuaValue.tostring(), +LuaValue.optnumber(LuaNumber), +LuaValue.checknumber(), +LuaValue.toint(), +LuaValue.todouble()
+
+
+
+ +

+checkint

+
+public int checkint()
+
+
Description copied from class: LuaValue
+
Check that the value is numeric, and convert and cast value to int, or throw LuaError if not numeric +

+ Values that are LuaNumber will be cast to int and may lose precision. + Values that are LuaString that can be converted to a number will be converted, + then cast to int, so may also lose precision. +

+

+
Overrides:
checkint in class LuaValue
+
+
+ +
Returns:
value cast to a int if numeric
See Also:
LuaValue.checkinteger(), +LuaValue.checklong(), +LuaValue.checkdouble(), +LuaValue.optint(int), +LuaValue.TNUMBER
+
+
+
+ +

+checklong

+
+public long checklong()
+
+
Description copied from class: LuaValue
+
Check that the value is numeric, and convert and cast value to long, or throw LuaError if not numeric +

+ Values that are LuaNumber will be cast to long and may lose precision. + Values that are LuaString that can be converted to a number will be converted, + then cast to long, so may also lose precision. +

+

+
Overrides:
checklong in class LuaValue
+
+
+ +
Returns:
value cast to a long if numeric
See Also:
LuaValue.checkint(), +LuaValue.checkinteger(), +LuaValue.checkdouble(), +LuaValue.optlong(long), +LuaValue.TNUMBER
+
+
+
+ +

+checknumber

+
+public LuaNumber checknumber()
+
+
Description copied from class: LuaValue
+
Check that the value is numeric, and return as a LuaNumber if so, or throw LuaError +

+ Values that are LuaString that can be converted to a number will be converted and returned. +

+

+
Overrides:
checknumber in class LuaNumber
+
+
+ +
Returns:
value as a LuaNumber if numeric
See Also:
LuaValue.checkint(), +LuaValue.checkinteger(), +LuaValue.checkdouble(), +LuaValue.checklong(), +LuaValue.optnumber(LuaNumber), +LuaValue.TNUMBER
+
+
+
+ +

+checkdouble

+
+public double checkdouble()
+
+
Description copied from class: LuaValue
+
Check that the value is numeric and return the value as a double, + or throw LuaError if not numeric +

+ Values that are LuaNumber and values that are LuaString + that can be converted to a number will be converted to double. +

+

+
Overrides:
checkdouble in class LuaValue
+
+
+ +
Returns:
value cast to a double if numeric
See Also:
LuaValue.checkint(), +LuaValue.checkinteger(), +LuaValue.checklong(), +LuaValue.optdouble(double), +LuaValue.TNUMBER
+
+
+
+ +

+checkjstring

+
+public java.lang.String checkjstring()
+
+
Description copied from class: LuaValue
+
Convert this value to a Java String. +

+ The string representations here will roughly match what is produced by the + C lua distribution, however hash codes have no relationship, + and there may be differences in number formatting. +

+

+
Overrides:
checkjstring in class LuaValue
+
+
+ +
Returns:
String representation of the value
See Also:
LuaValue.checkstring(), +LuaValue.optjstring(String), +LuaValue.tojstring(), +LuaValue.isstring(), +LuaValue.TSTRING
+
+
+
+ +

+checkstring

+
+public LuaString checkstring()
+
+
Description copied from class: LuaValue
+
Check that this is a lua string, or throw LuaError if it is not. +

+ In lua all numbers are strings, so this will succeed for + anything that derives from LuaString or LuaNumber. + Numbers will be converted to LuaString. +

+

+
Overrides:
checkstring in class LuaValue
+
+
+ +
Returns:
LuaString representation of the value if it is a LuaString or LuaNumber
See Also:
LuaValue.checkjstring(), +LuaValue.optstring(LuaString), +LuaValue.tostring(), +LuaValue.isstring(), +LuaValue.TSTRING
+
+
+
+ +

+checkvalidkey

+
+public LuaValue checkvalidkey()
+
+
Description copied from class: LuaValue
+
Check that this is a valid key in a table index operation, or throw LuaError if not +

+

+
Overrides:
checkvalidkey in class LuaValue
+
+
+ +
Returns:
this if valid as a table key
See Also:
LuaValue.isnil(), +LuaValue.isinttype()
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/LuaError.html b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaError.html new file mode 100644 index 0000000000..44c731c633 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaError.html @@ -0,0 +1,355 @@ + + + + + + +LuaError (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class LuaError

+
+java.lang.Object
+  extended by java.lang.Throwable
+      extended by java.lang.Exception
+          extended by java.lang.RuntimeException
+              extended by org.luaj.vm2.LuaError
+
+
+
All Implemented Interfaces:
java.io.Serializable
+
+
+
+
public class LuaError
extends java.lang.RuntimeException
+ + +

+RuntimeException that is thrown and caught in response to a lua error. +

+ LuaError is used wherever a lua call to error() + would be used within a script. +

+ Since it is an unchecked exception inheriting from RuntimeException, + Java method signatures do notdeclare this exception, althoug it can + be thrown on almost any luaj Java operation. + This is analagous to the fact that any lua script can throw a lua error at any time. +

+

+ +

+

+
See Also:
Serialized Form
+
+ +

+ + + + + + + + + + + + + + + + + +
+Constructor Summary
LuaError(java.lang.String message) + +
+          Construct a LuaError with a specific message.
LuaError(java.lang.String message, + int level) + +
+          Construct a LuaError with a message, and level to draw line number information from.
LuaError(java.lang.Throwable cause) + +
+          Construct LuaError when a program exception occurs.
+  + + + + + + + + + + + + + + + +
+Method Summary
+ java.lang.ThrowablegetCause() + +
+          Get the cause, if any.
+ voidprintStackTrace() + +
+          Print the message and stack trace
+ + + + + + + +
Methods inherited from class java.lang.Throwable
fillInStackTrace, getLocalizedMessage, getMessage, getStackTrace, initCause, printStackTrace, printStackTrace, setStackTrace, toString
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+LuaError

+
+public LuaError(java.lang.Throwable cause)
+
+
Construct LuaError when a program exception occurs. +

+ All errors generated from lua code should throw LuaError(String) instead. +

+

+
Parameters:
cause - the Throwable that caused the error, if known.
+
+
+ +

+LuaError

+
+public LuaError(java.lang.String message)
+
+
Construct a LuaError with a specific message. +

+

+
Parameters:
message - message to supply
+
+
+ +

+LuaError

+
+public LuaError(java.lang.String message,
+                int level)
+
+
Construct a LuaError with a message, and level to draw line number information from. +

+

+
Parameters:
message - message to supply
level - where to supply line info from in call stack
+
+ + + + + + + + +
+Method Detail
+ +

+printStackTrace

+
+public void printStackTrace()
+
+
Print the message and stack trace +

+

+
Overrides:
printStackTrace in class java.lang.Throwable
+
+
+
+
+
+
+ +

+getCause

+
+public java.lang.Throwable getCause()
+
+
Get the cause, if any. +

+

+
Overrides:
getCause in class java.lang.Throwable
+
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/LuaFunction.html b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaFunction.html new file mode 100644 index 0000000000..878143d4b4 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaFunction.html @@ -0,0 +1,598 @@ + + + + + + +LuaFunction (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class LuaFunction

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+
+
+
Direct Known Subclasses:
LibFunction, LuaClosure
+
+
+
+
public abstract class LuaFunction
extends LuaValue
+ + +

+Base class for functions implemented in Java. +

+ Direct subclass include LibFunction which is the base class for + all built-in library functions coded in Java, + and LuaClosure, which represents a lua closure + whose bytecode is interpreted when the function is invoked. +

+ +

+

+
See Also:
LuaValue, +LibFunction, +LuaClosure
+
+ +

+ + + + + + + + + + + + + + + +
+Field Summary
+protected  LuaValueenv + +
+           
+static LuaValues_metatable + +
+          Shared static metatable for all functions and closures.
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + + + + +
+Constructor Summary
LuaFunction() + +
+           
LuaFunction(LuaValue env) + +
+           
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ LuaValuecheckfunction() + +
+          Check that the value is a function , or throw LuaError if not
+ LuaValuegetfenv() + +
+          Get the environemnt for an instance.
+ LuaValuegetmetatable() + +
+          Get the metatable for this LuaValue
+ booleanisfunction() + +
+          Check if this is a function
+ LuaFunctionoptfunction(LuaFunction defval) + +
+          Check that optional argument is a function and return as LuaFunction
+ voidsetfenv(LuaValue env) + +
+          Set the environment on an object.
+ inttype() + +
+          Get the enumeration value for the type of this value.
+ java.lang.Stringtypename() + +
+          Get the String name of the type of this value.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, call, call, call, call, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+s_metatable

+
+public static LuaValue s_metatable
+
+
Shared static metatable for all functions and closures. +

+

+
+
+
+ +

+env

+
+protected LuaValue env
+
+
+
+
+ + + + + + + + +
+Constructor Detail
+ +

+LuaFunction

+
+public LuaFunction()
+
+
+
+ +

+LuaFunction

+
+public LuaFunction(LuaValue env)
+
+
+ + + + + + + + +
+Method Detail
+ +

+type

+
+public int type()
+
+
Description copied from class: LuaValue
+
Get the enumeration value for the type of this value. +

+

+
Specified by:
type in class LuaValue
+
+
+ +
Returns:
value for this type, one of + TNIL, + TBOOLEAN, + TNUMBER, + TSTRING, + TTABLE, + TFUNCTION, + TUSERDATA, + TTHREAD
See Also:
LuaValue.typename()
+
+
+
+ +

+typename

+
+public java.lang.String typename()
+
+
Description copied from class: LuaValue
+
Get the String name of the type of this value. +

+

+

+
Specified by:
typename in class LuaValue
+
+
+ +
Returns:
name from type name list LuaValue.TYPE_NAMES + corresponding to the type of this value: + "nil", "boolean", "number", "string", + "table", "function", "userdata", "thread"
See Also:
LuaValue.type()
+
+
+
+ +

+isfunction

+
+public boolean isfunction()
+
+
Description copied from class: LuaValue
+
Check if this is a function +

+

+
Overrides:
isfunction in class LuaValue
+
+
+ +
Returns:
true if this is a function, otherwise false
See Also:
LuaValue.isclosure(), +LuaValue.checkfunction(), +#optfunciton(LuaFunction), +LuaValue.TFUNCTION
+
+
+
+ +

+checkfunction

+
+public LuaValue checkfunction()
+
+
Description copied from class: LuaValue
+
Check that the value is a function , or throw LuaError if not +

+ A function is considered anything whose LuaValue.type() returns TFUNCTION. + In practice it will be either a built-in Java function, typically deriving from + LuaFunction or a LuaClosure which represents lua source compiled + into lua bytecode. +

+

+
Overrides:
checkfunction in class LuaValue
+
+
+ +
Returns:
this if if a lua function or closure
See Also:
LuaValue.checkclosure()
+
+
+
+ +

+optfunction

+
+public LuaFunction optfunction(LuaFunction defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a function and return as LuaFunction +

+ A LuaFunction may either be a Java function that implements + functionality directly in Java, + or a LuaClosure + which is a LuaFunction that executes lua bytecode. +

+

+
Overrides:
optfunction in class LuaValue
+
+
+
Parameters:
defval - LuaFunction to return if this is nil or none +
Returns:
this cast to LuaFunction if a function, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.checkfunction(), +LuaValue.isfunction(), +LuaValue.TFUNCTION
+
+
+
+ +

+getmetatable

+
+public LuaValue getmetatable()
+
+
Description copied from class: LuaValue
+
Get the metatable for this LuaValue +

+ For LuaTable and LuaUserdata instances, + the metatable returned is this instance metatable. + For all other types, the class metatable value will be returned. +

+

+
Overrides:
getmetatable in class LuaValue
+
+
+ +
Returns:
metatable, or null if it there is none
See Also:
LuaBoolean.s_metatable, +LuaNumber.s_metatable, +LuaNil.s_metatable, +s_metatable, +LuaThread.s_metatable
+
+
+
+ +

+getfenv

+
+public LuaValue getfenv()
+
+
Description copied from class: LuaValue
+
Get the environemnt for an instance. +

+

+
Overrides:
getfenv in class LuaValue
+
+
+ +
Returns:
LuaValue currently set as the instances environent.
+
+
+
+ +

+setfenv

+
+public void setfenv(LuaValue env)
+
+
Description copied from class: LuaValue
+
Set the environment on an object. +

+ Typically the environment is created once per application via a platform + helper method such as JsePlatform.standardGlobals() + However, any object can serve as an environment if it contains suitable metatag + values to implement LuaValue.get(LuaValue) to provide the environment values. +

+

+
Overrides:
setfenv in class LuaValue
+
+
+
Parameters:
env - LuaValue (typically a LuaTable) containing the environment.
See Also:
JmePlatform, +JsePlatform
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/LuaInteger.html b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaInteger.html new file mode 100644 index 0000000000..c2f9d5b7a1 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaInteger.html @@ -0,0 +1,3095 @@ + + + + + + +LuaInteger (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class LuaInteger

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaNumber
+              extended by org.luaj.vm2.LuaInteger
+
+
+
+
public class LuaInteger
extends LuaNumber
+ + +

+Extension of LuaNumber which can hold a Java int as its value. +

+ These instance are not instantiated directly by clients, but indirectly + via the static functions LuaValue.valueOf(int) or LuaValue.valueOf(double) + functions. This ensures that policies regarding pooling of instances are + encapsulated. +

+ There are no API's specific to LuaInteger that are useful beyond what is already + exposed in LuaValue. +

+ +

+

+
See Also:
LuaValue, +LuaNumber, +LuaDouble, +LuaValue.valueOf(int), +LuaValue.valueOf(double)
+
+ +

+ + + + + + + + + + + +
+Field Summary
+ intv + +
+          The value being held by this instance.
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaNumber
s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ LuaValueadd(double lhs) + +
+          Add: Perform numeric add operation with another value + of double type with metatag processing
+ LuaValueadd(int lhs) + +
+          Add: Perform numeric add operation with another value + of int type with metatag processing
+ LuaValueadd(LuaValue rhs) + +
+          Add: Perform numeric add operation with another value + including metatag processing.
+ doublecheckdouble() + +
+          Check that the value is numeric and return the value as a double, + or throw LuaError if not numeric
+ intcheckint() + +
+          Check that the value is numeric, and convert and cast value to int, or throw LuaError if not numeric
+ LuaIntegercheckinteger() + +
+          Check that the value is numeric, and convert and cast value to int, or throw LuaError if not numeric
+ java.lang.Stringcheckjstring() + +
+          Convert this value to a Java String.
+ longchecklong() + +
+          Check that the value is numeric, and convert and cast value to long, or throw LuaError if not numeric
+ LuaStringcheckstring() + +
+          Check that this is a lua string, or throw LuaError if it is not.
+ LuaValuediv(double rhs) + +
+          Divide: Perform numeric divide operation by another value + of double type without metatag processing
+ LuaValuediv(int rhs) + +
+          Divide: Perform numeric divide operation by another value + of int type without metatag processing
+ LuaValuediv(LuaValue rhs) + +
+          Divide: Perform numeric divide operation by another value + of unknown type, + including metatag processing.
+ LuaValuedivInto(double lhs) + +
+          Reverse-divide: Perform numeric divide operation into another value + with metatag processing
+ booleaneq_b(LuaValue val) + +
+          Equals: Perform equality comparison with another value + including metatag processing using EQ, + and return java boolean
+ LuaValueeq(LuaValue val) + +
+          Equals: Perform equality comparison with another value + including metatag processing using EQ.
+ booleanequals(java.lang.Object o) + +
+           
+ booleangt_b(double rhs) + +
+          Greater than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ booleangt_b(int rhs) + +
+          Greater than: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean.
+ booleangt_b(LuaValue rhs) + +
+          Greater than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ LuaValuegt(double rhs) + +
+          Greater than: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue.
+ LuaValuegt(int rhs) + +
+          Greater than: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue.
+ LuaValuegt(LuaValue rhs) + +
+          Greater than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ booleangteq_b(double rhs) + +
+          Greater than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, + and returning java boolean.
+ booleangteq_b(int rhs) + +
+          Greater than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean.
+ booleangteq_b(LuaValue rhs) + +
+          Greater than or equals: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ LuaValuegteq(double rhs) + +
+          Greater than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue.
+ LuaValuegteq(int rhs) + +
+          Greater than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue.
+ LuaValuegteq(LuaValue rhs) + +
+          Greater than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ inthashCode() + +
+           
+ booleanisint() + +
+          Check if this is a number and is representable by java int + without rounding or truncation
+ booleanisinttype() + +
+          Check if this is a LuaInteger
+ booleanislong() + +
+          Check if this is a number and is representable by java long + without rounding or truncation
+ booleanisstring() + +
+          Check if this is a string
+ booleanlt_b(double rhs) + +
+          Less than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ booleanlt_b(int rhs) + +
+          Less than: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean.
+ booleanlt_b(LuaValue rhs) + +
+          Less than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ LuaValuelt(double rhs) + +
+          Less than: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue.
+ LuaValuelt(int rhs) + +
+          Less than: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue.
+ LuaValuelt(LuaValue rhs) + +
+          Less than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ booleanlteq_b(double rhs) + +
+          Less than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, + and returning java boolean.
+ booleanlteq_b(int rhs) + +
+          Less than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean.
+ booleanlteq_b(LuaValue rhs) + +
+          Less than or equals: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ LuaValuelteq(double rhs) + +
+          Less than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue.
+ LuaValuelteq(int rhs) + +
+          Less than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue.
+ LuaValuelteq(LuaValue rhs) + +
+          Less than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ LuaValuemod(double rhs) + +
+          Modulo: Perform numeric modulo operation with another value + of double type without metatag processing
+ LuaValuemod(int rhs) + +
+          Modulo: Perform numeric modulo operation with another value + of int type without metatag processing
+ LuaValuemod(LuaValue rhs) + +
+          Modulo: Perform numeric modulo operation with another value + of unknown type, + including metatag processing.
+ LuaValuemodFrom(double lhs) + +
+          Reverse-modulo: Perform numeric modulo operation from another value + with metatag processing
+ LuaValuemul(double lhs) + +
+          Multiply: Perform numeric multiply operation with another value + of double type with metatag processing
+ LuaValuemul(int lhs) + +
+          Multiply: Perform numeric multiply operation with another value + of int type with metatag processing
+ LuaValuemul(LuaValue rhs) + +
+          Multiply: Perform numeric multiply operation with another value + of unknown type, + including metatag processing.
+ LuaValueneg() + +
+          Unary minus: return negative value (-this) as defined by lua unary minus operator
+ doubleoptdouble(double defval) + +
+          Check that optional argument is a number or string convertible to number and return as double
+ intoptint(int defval) + +
+          Check that optional argument is a number or string convertible to number and return as int
+ LuaIntegeroptinteger(LuaInteger defval) + +
+          Check that optional argument is a number or string convertible to number and return as LuaInteger
+ java.lang.Stringoptjstring(java.lang.String defval) + +
+          Check that optional argument is a string or number and return as Java String
+ longoptlong(long defval) + +
+          Check that optional argument is a number or string convertible to number and return as long
+ LuaStringoptstring(LuaString defval) + +
+          Check that optional argument is a string or number and return as LuaString
+ LuaValuepow(double rhs) + +
+          Raise to power: Raise this value to a power + of double type with metatag processing
+ LuaValuepow(int rhs) + +
+          Raise to power: Raise this value to a power + of int type with metatag processing
+ LuaValuepow(LuaValue rhs) + +
+          Raise to power: Raise this value to a power + including metatag processing.
+ LuaValuepowWith(double lhs) + +
+          Reverse-raise to power: Raise another value of double type to this power + with metatag processing
+ LuaValuepowWith(int lhs) + +
+          Reverse-raise to power: Raise another value of double type to this power + with metatag processing
+ booleanraweq(double val) + +
+          Equals: Perform direct equality comparison with a double value + without metatag processing.
+ booleanraweq(int val) + +
+          Equals: Perform direct equality comparison with a int value + without metatag processing.
+ booleanraweq(LuaValue val) + +
+          Equals: Perform direct equality comparison with another value + without metatag processing.
+ intstrcmp(LuaString rhs) + +
+          Perform string comparison with another value + known to be a LuaString + using string comparison based on byte values.
+ LuaStringstrvalue() + +
+          Convert this value to a string if it is a LuaString or LuaNumber, + or throw a LuaError if it is not
+ LuaValuesub(double rhs) + +
+          Subtract: Perform numeric subtract operation with another value + of double type with metatag processing
+ LuaValuesub(int rhs) + +
+          Subtract: Perform numeric subtract operation with another value + of int type with metatag processing
+ LuaValuesub(LuaValue rhs) + +
+          Subtract: Perform numeric subtract operation with another value + of unknown type, + including metatag processing.
+ LuaValuesubFrom(double lhs) + +
+          Reverse-subtract: Perform numeric subtract operation from an int value + with metatag processing
+ LuaValuesubFrom(int lhs) + +
+          Reverse-subtract: Perform numeric subtract operation from a double value + without metatag processing
+ bytetobyte() + +
+          Convert to byte if numeric, or 0 if not.
+ chartochar() + +
+          Convert to char if numeric, or 0 if not.
+ doubletodouble() + +
+          Convert to double if numeric, or 0 if not.
+ floattofloat() + +
+          Convert to float if numeric, or 0 if not.
+ inttoint() + +
+          Convert to int if numeric, or 0 if not.
+ java.lang.Stringtojstring() + +
+          Convert to human readable String for any type.
+ longtolong() + +
+          Convert to long if numeric, or 0 if not.
+ shorttoshort() + +
+          Convert to short if numeric, or 0 if not.
+ LuaValuetostring() + +
+          Conditionally convert to lua string without throwing errors.
+static LuaIntegervalueOf(int i) + +
+           
+static LuaNumbervalueOf(long l) + +
+          Return a LuaNumber that represents the value provided
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaNumber
checknumber, checknumber, concat, concat, concatTo, concatTo, getmetatable, isnumber, optnumber, tonumber, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, call, call, call, call, callmt, checkboolean, checkclosure, checkfunction, checkmetatag, checknotnil, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concatmt, concatTo, eqmtcall, error, get, get, get, getfenv, getn, gettable, illegal, inext, invoke, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isfunction, isnil, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, metatag, method, method, method, method, method, method, narg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optfunction, opttable, optthread, optuserdata, optuserdata, optvalue, or, presize, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setfenv, setmetatable, settable, strcmp, strongkey, strongvalue, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+v

+
+public final int v
+
+
The value being held by this instance. +

+

+
+
+ + + + + + + + +
+Method Detail
+ +

+valueOf

+
+public static LuaInteger valueOf(int i)
+
+
+
+
+
+
+ +

+valueOf

+
+public static LuaNumber valueOf(long l)
+
+
Return a LuaNumber that represents the value provided +

+

+
Parameters:
l - long value to represent. +
Returns:
LuaNumber that is eithe LuaInteger or LuaDouble representing l
See Also:
LuaValue.valueOf(int), +LuaValue.valueOf(double)
+
+
+
+ +

+isint

+
+public boolean isint()
+
+
Description copied from class: LuaValue
+
Check if this is a number and is representable by java int + without rounding or truncation +

+

+
Overrides:
isint in class LuaValue
+
+
+ +
Returns:
true if this is a number + meaning derives from LuaNumber + or derives from LuaString and is convertible to a number, + and can be represented by int, + otherwise false
See Also:
LuaValue.isinttype(), +LuaValue.islong(), +LuaValue.tonumber(), +LuaValue.checkint(), +LuaValue.optint(int), +LuaValue.TNUMBER
+
+
+
+ +

+isinttype

+
+public boolean isinttype()
+
+
Description copied from class: LuaValue
+
Check if this is a LuaInteger +

+ No attempt to convert from string will be made by this call. +

+

+
Overrides:
isinttype in class LuaValue
+
+
+ +
Returns:
true if this is a LuaInteger, + otherwise false
See Also:
LuaValue.isint(), +LuaValue.isnumber(), +LuaValue.tonumber(), +LuaValue.TNUMBER
+
+
+
+ +

+islong

+
+public boolean islong()
+
+
Description copied from class: LuaValue
+
Check if this is a number and is representable by java long + without rounding or truncation +

+

+
Overrides:
islong in class LuaValue
+
+
+ +
Returns:
true if this is a number + meaning derives from LuaNumber + or derives from LuaString and is convertible to a number, + and can be represented by long, + otherwise false
See Also:
LuaValue.tonumber(), +LuaValue.checklong(), +LuaValue.optlong(long), +LuaValue.TNUMBER
+
+
+
+ +

+tobyte

+
+public byte tobyte()
+
+
Description copied from class: LuaValue
+
Convert to byte if numeric, or 0 if not. +

+

+
Overrides:
tobyte in class LuaValue
+
+
+ +
Returns:
Value cast to byte if number or string convertible to number, otherwise 0
See Also:
LuaValue.toint(), +LuaValue.todouble(), +#optbyte(byte), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+tochar

+
+public char tochar()
+
+
Description copied from class: LuaValue
+
Convert to char if numeric, or 0 if not. +

+

+
Overrides:
tochar in class LuaValue
+
+
+ +
Returns:
Value cast to char if number or string convertible to number, otherwise 0
See Also:
LuaValue.toint(), +LuaValue.todouble(), +#optchar(char), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+todouble

+
+public double todouble()
+
+
Description copied from class: LuaValue
+
Convert to double if numeric, or 0 if not. +

+

+
Overrides:
todouble in class LuaValue
+
+
+ +
Returns:
Value cast to double if number or string convertible to number, otherwise 0
See Also:
LuaValue.toint(), +LuaValue.tobyte(), +LuaValue.tochar(), +LuaValue.toshort(), +LuaValue.tolong(), +LuaValue.tofloat(), +LuaValue.optdouble(double), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+tofloat

+
+public float tofloat()
+
+
Description copied from class: LuaValue
+
Convert to float if numeric, or 0 if not. +

+

+
Overrides:
tofloat in class LuaValue
+
+
+ +
Returns:
Value cast to float if number or string convertible to number, otherwise 0
See Also:
LuaValue.toint(), +LuaValue.todouble(), +#optfloat(float), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+toint

+
+public int toint()
+
+
Description copied from class: LuaValue
+
Convert to int if numeric, or 0 if not. +

+

+
Overrides:
toint in class LuaValue
+
+
+ +
Returns:
Value cast to int if number or string convertible to number, otherwise 0
See Also:
LuaValue.tobyte(), +LuaValue.tochar(), +LuaValue.toshort(), +LuaValue.tolong(), +LuaValue.tofloat(), +LuaValue.todouble(), +LuaValue.optint(int), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+tolong

+
+public long tolong()
+
+
Description copied from class: LuaValue
+
Convert to long if numeric, or 0 if not. +

+

+
Overrides:
tolong in class LuaValue
+
+
+ +
Returns:
Value cast to long if number or string convertible to number, otherwise 0
See Also:
LuaValue.isint(), +LuaValue.isinttype(), +LuaValue.toint(), +LuaValue.todouble(), +LuaValue.optlong(long), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+toshort

+
+public short toshort()
+
+
Description copied from class: LuaValue
+
Convert to short if numeric, or 0 if not. +

+

+
Overrides:
toshort in class LuaValue
+
+
+ +
Returns:
Value cast to short if number or string convertible to number, otherwise 0
See Also:
LuaValue.toint(), +LuaValue.todouble(), +#optshort(short), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+optdouble

+
+public double optdouble(double defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a number or string convertible to number and return as double +

+

+
Overrides:
optdouble in class LuaValue
+
+
+
Parameters:
defval - double to return if this is nil or none +
Returns:
this cast to double if numeric, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.optint(int), +LuaValue.optinteger(LuaInteger), +LuaValue.checkdouble(), +LuaValue.todouble(), +LuaValue.tonumber(), +LuaValue.isnumber(), +LuaValue.TNUMBER
+
+
+
+ +

+optint

+
+public int optint(int defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a number or string convertible to number and return as int +

+

+
Overrides:
optint in class LuaValue
+
+
+
Parameters:
defval - int to return if this is nil or none +
Returns:
this cast to int if numeric, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.optdouble(double), +LuaValue.optlong(long), +LuaValue.optinteger(LuaInteger), +LuaValue.checkint(), +LuaValue.toint(), +LuaValue.tonumber(), +LuaValue.isnumber(), +LuaValue.TNUMBER
+
+
+
+ +

+optinteger

+
+public LuaInteger optinteger(LuaInteger defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a number or string convertible to number and return as LuaInteger +

+

+
Overrides:
optinteger in class LuaValue
+
+
+
Parameters:
defval - LuaInteger to return if this is nil or none +
Returns:
this converted and wrapped in LuaInteger if numeric, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.optdouble(double), +LuaValue.optint(int), +LuaValue.checkint(), +LuaValue.toint(), +LuaValue.tonumber(), +LuaValue.isnumber(), +LuaValue.TNUMBER
+
+
+
+ +

+optlong

+
+public long optlong(long defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a number or string convertible to number and return as long +

+

+
Overrides:
optlong in class LuaValue
+
+
+
Parameters:
defval - long to return if this is nil or none +
Returns:
this cast to long if numeric, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.optdouble(double), +LuaValue.optint(int), +LuaValue.checkint(), +LuaValue.toint(), +LuaValue.tonumber(), +LuaValue.isnumber(), +LuaValue.TNUMBER
+
+
+
+ +

+tojstring

+
+public java.lang.String tojstring()
+
+
Description copied from class: LuaValue
+
Convert to human readable String for any type. +

+

+
Overrides:
tojstring in class LuaValue
+
+
+ +
Returns:
String for use by human readers based on type.
See Also:
LuaValue.tostring(), +LuaValue.optjstring(String), +LuaValue.checkjstring(), +LuaValue.isstring(), +TSTRING
+
+
+
+ +

+strvalue

+
+public LuaString strvalue()
+
+
Description copied from class: LuaValue
+
Convert this value to a string if it is a LuaString or LuaNumber, + or throw a LuaError if it is not +

+

+
Overrides:
strvalue in class LuaValue
+
+
+ +
Returns:
LuaString corresponding to the value if a string or number
+
+
+
+ +

+optstring

+
+public LuaString optstring(LuaString defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a string or number and return as LuaString +

+

+
Overrides:
optstring in class LuaValue
+
+
+
Parameters:
defval - LuaString to return if this is nil or none +
Returns:
this converted to LuaString if a string or number, + defval if nil or none, + throws LuaError if some other type
See Also:
LuaValue.tojstring(), +LuaValue.optjstring(String), +LuaValue.checkstring(), +LuaValue.toString(), +LuaValue.TSTRING
+
+
+
+ +

+tostring

+
+public LuaValue tostring()
+
+
Description copied from class: LuaValue
+
Conditionally convert to lua string without throwing errors. +

+ In lua all numbers are strings, so this function will return + the LuaValue this if it is a string or number, + and NIL for all other cases. +

+ This allows values to be tested for their "string-ness" without + the penalty of throwing exceptions. +

+

+
Overrides:
tostring in class LuaValue
+
+
+ +
Returns:
this if it is a LuaString or LuaNumber, + otherwise NIL
See Also:
LuaValue.tonumber(), +LuaValue.tojstring(), +LuaValue.optstring(LuaString), +LuaValue.checkstring(), +LuaValue.toString()
+
+
+
+ +

+optjstring

+
+public java.lang.String optjstring(java.lang.String defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a string or number and return as Java String +

+

+
Overrides:
optjstring in class LuaValue
+
+
+
Parameters:
defval - LuaString to return if this is nil or none +
Returns:
this converted to String if a string or number, + defval if nil or none, + throws LuaError if some other type
See Also:
LuaValue.tojstring(), +LuaValue.optstring(LuaString), +LuaValue.checkjstring(), +LuaValue.toString(), +LuaValue.TSTRING
+
+
+
+ +

+checkinteger

+
+public LuaInteger checkinteger()
+
+
Description copied from class: LuaValue
+
Check that the value is numeric, and convert and cast value to int, or throw LuaError if not numeric +

+ Values that are LuaNumber will be cast to int and may lose precision. + Values that are LuaString that can be converted to a number will be converted, + then cast to int, so may also lose precision. +

+

+
Overrides:
checkinteger in class LuaValue
+
+
+ +
Returns:
value cast to a int and wrapped in LuaInteger if numeric
See Also:
LuaValue.checkint(), +LuaValue.checklong(), +LuaValue.checkdouble(), +LuaValue.optinteger(LuaInteger), +LuaValue.TNUMBER
+
+
+
+ +

+isstring

+
+public boolean isstring()
+
+
Description copied from class: LuaValue
+
Check if this is a string +

+

+
Overrides:
isstring in class LuaNumber
+
+
+ +
Returns:
true if this is a string, + meaning derives from LuaString or LuaNumber, + otherwise false
See Also:
LuaValue.tostring(), +LuaValue.checkstring(), +LuaValue.optstring(LuaString), +LuaValue.TSTRING
+
+
+
+ +

+hashCode

+
+public int hashCode()
+
+
+
Overrides:
hashCode in class java.lang.Object
+
+
+
+
+
+
+ +

+neg

+
+public LuaValue neg()
+
+
Description copied from class: LuaValue
+
Unary minus: return negative value (-this) as defined by lua unary minus operator +

+

+
Overrides:
neg in class LuaValue
+
+
+ +
Returns:
boolean inverse as LuaBoolean if boolean or nil, + numeric inverse as if numeric, + or metatag processing result if UNM metatag is defined
+
+
+
+ +

+equals

+
+public boolean equals(java.lang.Object o)
+
+
+
Overrides:
equals in class LuaValue
+
+
+
+
+
+
+ +

+eq

+
+public LuaValue eq(LuaValue val)
+
+
Description copied from class: LuaValue
+
Equals: Perform equality comparison with another value + including metatag processing using EQ. +

+

+
Overrides:
eq in class LuaValue
+
+
+
Parameters:
val - The value to compare with. +
Returns:
TRUE if values are comparable and (this == rhs), + FALSE if comparable but not equal, + LuaValue if metatag processing occurs.
See Also:
LuaValue.eq_b(LuaValue), +LuaValue.raweq(LuaValue), +LuaValue.neq(LuaValue), +LuaValue.eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue), +LuaValue.EQ
+
+
+
+ +

+eq_b

+
+public boolean eq_b(LuaValue val)
+
+
Description copied from class: LuaValue
+
Equals: Perform equality comparison with another value + including metatag processing using EQ, + and return java boolean +

+

+
Overrides:
eq_b in class LuaValue
+
+
+
Parameters:
val - The value to compare with. +
Returns:
true if values are comparable and (this == rhs), + false if comparable but not equal, + result converted to java boolean if metatag processing occurs.
See Also:
LuaValue.eq(LuaValue), +LuaValue.raweq(LuaValue), +LuaValue.neq_b(LuaValue), +LuaValue.eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue), +LuaValue.EQ
+
+
+
+ +

+raweq

+
+public boolean raweq(LuaValue val)
+
+
Description copied from class: LuaValue
+
Equals: Perform direct equality comparison with another value + without metatag processing. +

+

+
Overrides:
raweq in class LuaValue
+
+
+
Parameters:
val - The value to compare with. +
Returns:
true if (this == rhs), false otherwise
See Also:
LuaValue.eq(LuaValue), +LuaValue.raweq(LuaUserdata), +LuaValue.raweq(LuaString), +LuaValue.raweq(double), +LuaValue.raweq(int), +LuaValue.EQ
+
+
+
+ +

+raweq

+
+public boolean raweq(double val)
+
+
Description copied from class: LuaValue
+
Equals: Perform direct equality comparison with a double value + without metatag processing. +

+

+
Overrides:
raweq in class LuaValue
+
+
+
Parameters:
val - The double value to compare with. +
Returns:
true if this is a LuaNumber + whose value equals val, + otherwise false
+
+
+
+ +

+raweq

+
+public boolean raweq(int val)
+
+
Description copied from class: LuaValue
+
Equals: Perform direct equality comparison with a int value + without metatag processing. +

+

+
Overrides:
raweq in class LuaValue
+
+
+
Parameters:
val - The double value to compare with. +
Returns:
true if this is a LuaNumber + whose value equals val, + otherwise false
+
+
+
+ +

+add

+
+public LuaValue add(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Add: Perform numeric add operation with another value + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
add in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the add with +
Returns:
value of (this + rhs) if both are numeric, + or LuaValue if metatag processing occurs
See Also:
LuaValue.arithmt(LuaValue, LuaValue)
+
+
+
+ +

+add

+
+public LuaValue add(double lhs)
+
+
Description copied from class: LuaValue
+
Add: Perform numeric add operation with another value + of double type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
add in class LuaValue
+
+
+
Parameters:
lhs - The right-hand-side value to perform the add with +
Returns:
value of (this + rhs) if this is numeric
See Also:
LuaValue.add(LuaValue)
+
+
+
+ +

+add

+
+public LuaValue add(int lhs)
+
+
Description copied from class: LuaValue
+
Add: Perform numeric add operation with another value + of int type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
add in class LuaValue
+
+
+
Parameters:
lhs - The right-hand-side value to perform the add with +
Returns:
value of (this + rhs) if this is numeric
See Also:
LuaValue.add(LuaValue)
+
+
+
+ +

+sub

+
+public LuaValue sub(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Subtract: Perform numeric subtract operation with another value + of unknown type, + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
sub in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the subtract with +
Returns:
value of (this - rhs) if both are numeric, + or LuaValue if metatag processing occurs
See Also:
LuaValue.arithmt(LuaValue, LuaValue)
+
+
+
+ +

+sub

+
+public LuaValue sub(double rhs)
+
+
Description copied from class: LuaValue
+
Subtract: Perform numeric subtract operation with another value + of double type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
sub in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the subtract with +
Returns:
value of (this - rhs) if this is numeric
See Also:
LuaValue.sub(LuaValue)
+
+
+
+ +

+sub

+
+public LuaValue sub(int rhs)
+
+
Description copied from class: LuaValue
+
Subtract: Perform numeric subtract operation with another value + of int type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
sub in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the subtract with +
Returns:
value of (this - rhs) if this is numeric
See Also:
LuaValue.sub(LuaValue)
+
+
+
+ +

+subFrom

+
+public LuaValue subFrom(double lhs)
+
+
Description copied from class: LuaValue
+
Reverse-subtract: Perform numeric subtract operation from an int value + with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
subFrom in class LuaValue
+
+
+
Parameters:
lhs - The left-hand-side value from which to perform the subtraction +
Returns:
value of (lhs - this) if this is numeric
See Also:
LuaValue.sub(LuaValue), +LuaValue.sub(double), +LuaValue.sub(int)
+
+
+
+ +

+subFrom

+
+public LuaValue subFrom(int lhs)
+
+
Description copied from class: LuaValue
+
Reverse-subtract: Perform numeric subtract operation from a double value + without metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+ For metatag processing LuaValue.sub(LuaValue) must be used +

+

+
Overrides:
subFrom in class LuaValue
+
+
+
Parameters:
lhs - The left-hand-side value from which to perform the subtraction +
Returns:
value of (lhs - this) if this is numeric
See Also:
LuaValue.sub(LuaValue), +LuaValue.sub(double), +LuaValue.sub(int)
+
+
+
+ +

+mul

+
+public LuaValue mul(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Multiply: Perform numeric multiply operation with another value + of unknown type, + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
mul in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the multiply with +
Returns:
value of (this * rhs) if both are numeric, + or LuaValue if metatag processing occurs
See Also:
LuaValue.arithmt(LuaValue, LuaValue)
+
+
+
+ +

+mul

+
+public LuaValue mul(double lhs)
+
+
Description copied from class: LuaValue
+
Multiply: Perform numeric multiply operation with another value + of double type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
mul in class LuaValue
+
+
+
Parameters:
lhs - The right-hand-side value to perform the multiply with +
Returns:
value of (this * rhs) if this is numeric
See Also:
LuaValue.mul(LuaValue)
+
+
+
+ +

+mul

+
+public LuaValue mul(int lhs)
+
+
Description copied from class: LuaValue
+
Multiply: Perform numeric multiply operation with another value + of int type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
mul in class LuaValue
+
+
+
Parameters:
lhs - The right-hand-side value to perform the multiply with +
Returns:
value of (this * rhs) if this is numeric
See Also:
LuaValue.mul(LuaValue)
+
+
+
+ +

+pow

+
+public LuaValue pow(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Raise to power: Raise this value to a power + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
pow in class LuaValue
+
+
+
Parameters:
rhs - The power to raise this value to +
Returns:
value of (this ^ rhs) if both are numeric, + or LuaValue if metatag processing occurs
See Also:
LuaValue.arithmt(LuaValue, LuaValue)
+
+
+
+ +

+pow

+
+public LuaValue pow(double rhs)
+
+
Description copied from class: LuaValue
+
Raise to power: Raise this value to a power + of double type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
pow in class LuaValue
+
+
+
Parameters:
rhs - The power to raise this value to +
Returns:
value of (this ^ rhs) if this is numeric
See Also:
LuaValue.pow(LuaValue)
+
+
+
+ +

+pow

+
+public LuaValue pow(int rhs)
+
+
Description copied from class: LuaValue
+
Raise to power: Raise this value to a power + of int type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
pow in class LuaValue
+
+
+
Parameters:
rhs - The power to raise this value to +
Returns:
value of (this ^ rhs) if this is numeric
See Also:
LuaValue.pow(LuaValue)
+
+
+
+ +

+powWith

+
+public LuaValue powWith(double lhs)
+
+
Description copied from class: LuaValue
+
Reverse-raise to power: Raise another value of double type to this power + with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
powWith in class LuaValue
+
+
+
Parameters:
lhs - The left-hand-side value which will be raised to this power +
Returns:
value of (lhs ^ this) if this is numeric
See Also:
LuaValue.pow(LuaValue), +LuaValue.pow(double), +LuaValue.pow(int)
+
+
+
+ +

+powWith

+
+public LuaValue powWith(int lhs)
+
+
Description copied from class: LuaValue
+
Reverse-raise to power: Raise another value of double type to this power + with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
powWith in class LuaValue
+
+
+
Parameters:
lhs - The left-hand-side value which will be raised to this power +
Returns:
value of (lhs ^ this) if this is numeric
See Also:
LuaValue.pow(LuaValue), +LuaValue.pow(double), +LuaValue.pow(int)
+
+
+
+ +

+div

+
+public LuaValue div(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Divide: Perform numeric divide operation by another value + of unknown type, + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
div in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the divulo with +
Returns:
value of (this / rhs) if both are numeric, + or LuaValue if metatag processing occurs
See Also:
LuaValue.arithmt(LuaValue, LuaValue)
+
+
+
+ +

+div

+
+public LuaValue div(double rhs)
+
+
Description copied from class: LuaValue
+
Divide: Perform numeric divide operation by another value + of double type without metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+ For metatag processing LuaValue.div(LuaValue) must be used +

+

+
Overrides:
div in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the divulo with +
Returns:
value of (this / rhs) if this is numeric
See Also:
LuaValue.div(LuaValue)
+
+
+
+ +

+div

+
+public LuaValue div(int rhs)
+
+
Description copied from class: LuaValue
+
Divide: Perform numeric divide operation by another value + of int type without metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+ For metatag processing LuaValue.div(LuaValue) must be used +

+

+
Overrides:
div in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the divulo with +
Returns:
value of (this / rhs) if this is numeric
See Also:
LuaValue.div(LuaValue)
+
+
+
+ +

+divInto

+
+public LuaValue divInto(double lhs)
+
+
Description copied from class: LuaValue
+
Reverse-divide: Perform numeric divide operation into another value + with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
divInto in class LuaValue
+
+
+
Parameters:
lhs - The left-hand-side value which will be divided by this +
Returns:
value of (lhs / this) if this is numeric
See Also:
LuaValue.div(LuaValue), +LuaValue.div(double), +LuaValue.div(int)
+
+
+
+ +

+mod

+
+public LuaValue mod(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Modulo: Perform numeric modulo operation with another value + of unknown type, + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
mod in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the modulo with +
Returns:
value of (this % rhs) if both are numeric, + or LuaValue if metatag processing occurs
See Also:
LuaValue.arithmt(LuaValue, LuaValue)
+
+
+
+ +

+mod

+
+public LuaValue mod(double rhs)
+
+
Description copied from class: LuaValue
+
Modulo: Perform numeric modulo operation with another value + of double type without metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+ For metatag processing LuaValue.mod(LuaValue) must be used +

+

+
Overrides:
mod in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the modulo with +
Returns:
value of (this % rhs) if this is numeric
See Also:
LuaValue.mod(LuaValue)
+
+
+
+ +

+mod

+
+public LuaValue mod(int rhs)
+
+
Description copied from class: LuaValue
+
Modulo: Perform numeric modulo operation with another value + of int type without metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+ For metatag processing LuaValue.mod(LuaValue) must be used +

+

+
Overrides:
mod in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the modulo with +
Returns:
value of (this % rhs) if this is numeric
See Also:
LuaValue.mod(LuaValue)
+
+
+
+ +

+modFrom

+
+public LuaValue modFrom(double lhs)
+
+
Description copied from class: LuaValue
+
Reverse-modulo: Perform numeric modulo operation from another value + with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
modFrom in class LuaValue
+
+
+
Parameters:
lhs - The left-hand-side value which will be modulo'ed by this +
Returns:
value of (lhs % this) if this is numeric
See Also:
LuaValue.mod(LuaValue), +LuaValue.mod(double), +LuaValue.mod(int)
+
+
+
+ +

+lt

+
+public LuaValue lt(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Less than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
lt in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this < rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lt

+
+public LuaValue lt(double rhs)
+
+
Description copied from class: LuaValue
+
Less than: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
lt in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this < rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(double), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lt

+
+public LuaValue lt(int rhs)
+
+
Description copied from class: LuaValue
+
Less than: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
lt in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this < rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(int), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lt_b

+
+public boolean lt_b(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Less than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
lt_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this < rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lt_b

+
+public boolean lt_b(int rhs)
+
+
Description copied from class: LuaValue
+
Less than: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
lt_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this < rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(int), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lt_b

+
+public boolean lt_b(double rhs)
+
+
Description copied from class: LuaValue
+
Less than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
lt_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this < rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq

+
+public LuaValue lteq(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Less than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
lteq in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this <= rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq

+
+public LuaValue lteq(double rhs)
+
+
Description copied from class: LuaValue
+
Less than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
lteq in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this <= rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(double), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq

+
+public LuaValue lteq(int rhs)
+
+
Description copied from class: LuaValue
+
Less than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
lteq in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this <= rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(int), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq_b

+
+public boolean lteq_b(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Less than or equals: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
lteq_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this <= rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq_b

+
+public boolean lteq_b(int rhs)
+
+
Description copied from class: LuaValue
+
Less than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
lteq_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this <= rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(int), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq_b

+
+public boolean lteq_b(double rhs)
+
+
Description copied from class: LuaValue
+
Less than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
lteq_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this <= rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(double), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt

+
+public LuaValue gt(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Greater than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
gt in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this > rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt

+
+public LuaValue gt(double rhs)
+
+
Description copied from class: LuaValue
+
Greater than: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
gt in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this > rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(double), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt

+
+public LuaValue gt(int rhs)
+
+
Description copied from class: LuaValue
+
Greater than: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
gt in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this > rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(int), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt_b

+
+public boolean gt_b(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Greater than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
gt_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this > rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt_b

+
+public boolean gt_b(int rhs)
+
+
Description copied from class: LuaValue
+
Greater than: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
gt_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this > rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(int), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt_b

+
+public boolean gt_b(double rhs)
+
+
Description copied from class: LuaValue
+
Greater than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
gt_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this > rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq

+
+public LuaValue gteq(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Greater than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
gteq in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this >= rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq

+
+public LuaValue gteq(double rhs)
+
+
Description copied from class: LuaValue
+
Greater than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
gteq in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this >= rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(double), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq

+
+public LuaValue gteq(int rhs)
+
+
Description copied from class: LuaValue
+
Greater than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
gteq in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this >= rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(int), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq_b

+
+public boolean gteq_b(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Greater than or equals: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
gteq_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this >= rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq_b

+
+public boolean gteq_b(int rhs)
+
+
Description copied from class: LuaValue
+
Greater than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
gteq_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this >= rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(int), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq_b

+
+public boolean gteq_b(double rhs)
+
+
Description copied from class: LuaValue
+
Greater than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
gteq_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this >= rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(double), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+strcmp

+
+public int strcmp(LuaString rhs)
+
+
Description copied from class: LuaValue
+
Perform string comparison with another value + known to be a LuaString + using string comparison based on byte values. +

+ Only strings can be compared, meaning + each operand must derive from LuaString. +

+

+
Overrides:
strcmp in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with
+
+
+
+ +

+checkint

+
+public int checkint()
+
+
Description copied from class: LuaValue
+
Check that the value is numeric, and convert and cast value to int, or throw LuaError if not numeric +

+ Values that are LuaNumber will be cast to int and may lose precision. + Values that are LuaString that can be converted to a number will be converted, + then cast to int, so may also lose precision. +

+

+
Overrides:
checkint in class LuaValue
+
+
+ +
Returns:
value cast to a int if numeric
See Also:
LuaValue.checkinteger(), +LuaValue.checklong(), +LuaValue.checkdouble(), +LuaValue.optint(int), +LuaValue.TNUMBER
+
+
+
+ +

+checklong

+
+public long checklong()
+
+
Description copied from class: LuaValue
+
Check that the value is numeric, and convert and cast value to long, or throw LuaError if not numeric +

+ Values that are LuaNumber will be cast to long and may lose precision. + Values that are LuaString that can be converted to a number will be converted, + then cast to long, so may also lose precision. +

+

+
Overrides:
checklong in class LuaValue
+
+
+ +
Returns:
value cast to a long if numeric
See Also:
LuaValue.checkint(), +LuaValue.checkinteger(), +LuaValue.checkdouble(), +LuaValue.optlong(long), +LuaValue.TNUMBER
+
+
+
+ +

+checkdouble

+
+public double checkdouble()
+
+
Description copied from class: LuaValue
+
Check that the value is numeric and return the value as a double, + or throw LuaError if not numeric +

+ Values that are LuaNumber and values that are LuaString + that can be converted to a number will be converted to double. +

+

+
Overrides:
checkdouble in class LuaValue
+
+
+ +
Returns:
value cast to a double if numeric
See Also:
LuaValue.checkint(), +LuaValue.checkinteger(), +LuaValue.checklong(), +LuaValue.optdouble(double), +LuaValue.TNUMBER
+
+
+
+ +

+checkjstring

+
+public java.lang.String checkjstring()
+
+
Description copied from class: LuaValue
+
Convert this value to a Java String. +

+ The string representations here will roughly match what is produced by the + C lua distribution, however hash codes have no relationship, + and there may be differences in number formatting. +

+

+
Overrides:
checkjstring in class LuaValue
+
+
+ +
Returns:
String representation of the value
See Also:
LuaValue.checkstring(), +LuaValue.optjstring(String), +LuaValue.tojstring(), +LuaValue.isstring(), +LuaValue.TSTRING
+
+
+
+ +

+checkstring

+
+public LuaString checkstring()
+
+
Description copied from class: LuaValue
+
Check that this is a lua string, or throw LuaError if it is not. +

+ In lua all numbers are strings, so this will succeed for + anything that derives from LuaString or LuaNumber. + Numbers will be converted to LuaString. +

+

+
Overrides:
checkstring in class LuaValue
+
+
+ +
Returns:
LuaString representation of the value if it is a LuaString or LuaNumber
See Also:
LuaValue.checkjstring(), +LuaValue.optstring(LuaString), +LuaValue.tostring(), +LuaValue.isstring(), +LuaValue.TSTRING
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/LuaNil.html b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaNil.html new file mode 100644 index 0000000000..1c045ac679 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaNil.html @@ -0,0 +1,1063 @@ + + + + + + +LuaNil (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class LuaNil

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaNil
+
+
+
+
public class LuaNil
extends LuaValue
+ + +

+Class to encapsulate behavior of the singleton instance nil +

+ There will be one instance of this class, LuaValue.NIL, + per Java virtual machine. + However, the Varargs instance LuaValue.NONE + which is the empty list, + is also considered treated as a nil value by default. +

+ Although it is possible to test for nil using Java == operator, + the recommended approach is to use the method LuaValue.isnil() + instead. By using that any ambiguities between + LuaValue.NIL and LuaValue.NONE are avoided. +

+ +

+

+
See Also:
LuaValue, +LuaValue.NIL
+
+ +

+ + + + + + + + + + + +
+Field Summary
+static LuaValues_metatable + +
+           
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ LuaValuechecknotnil() + +
+          Check that this is not the value NIL, or throw LuaError if it is
+ LuaValuecheckvalidkey() + +
+          Check that this is a valid key in a table index operation, or throw LuaError if not
+ booleanequals(java.lang.Object o) + +
+           
+ LuaValuegetmetatable() + +
+          Get the metatable for this LuaValue
+ booleanisnil() + +
+          Check if this is nil
+ LuaValuenot() + +
+          Unary not: return inverse boolean value (~this) as defined by lua not operator
+ booleanoptboolean(boolean defval) + +
+          Check that optional argument is a boolean and return its boolean value
+ LuaClosureoptclosure(LuaClosure defval) + +
+          Check that optional argument is a closure and return as LuaClosure
+ doubleoptdouble(double defval) + +
+          Check that optional argument is a number or string convertible to number and return as double
+ LuaFunctionoptfunction(LuaFunction defval) + +
+          Check that optional argument is a function and return as LuaFunction
+ intoptint(int defval) + +
+          Check that optional argument is a number or string convertible to number and return as int
+ LuaIntegeroptinteger(LuaInteger defval) + +
+          Check that optional argument is a number or string convertible to number and return as LuaInteger
+ java.lang.Stringoptjstring(java.lang.String defval) + +
+          Check that optional argument is a string or number and return as Java String
+ longoptlong(long defval) + +
+          Check that optional argument is a number or string convertible to number and return as long
+ LuaNumberoptnumber(LuaNumber defval) + +
+          Check that optional argument is a number or string convertible to number and return as LuaNumber
+ LuaStringoptstring(LuaString defval) + +
+          Check that optional argument is a string or number and return as LuaString
+ LuaTableopttable(LuaTable defval) + +
+          Check that optional argument is a table and return as LuaTable
+ LuaThreadoptthread(LuaThread defval) + +
+          Check that optional argument is a thread and return as LuaThread
+ java.lang.Objectoptuserdata(java.lang.Class c, + java.lang.Object defval) + +
+          Check that optional argument is a userdata whose instance is of a type + and return the Object instance
+ java.lang.Objectoptuserdata(java.lang.Object defval) + +
+          Check that optional argument is a userdata and return the Object instance
+ LuaValueoptvalue(LuaValue defval) + +
+          Perform argument check that this is not nil or none.
+ booleantoboolean() + +
+          Convert to boolean false if LuaValue.NIL or FALSE, true if anything else
+ java.lang.Stringtojstring() + +
+          Convert to human readable String for any type.
+ inttype() + +
+          Get the enumeration value for the type of this value.
+ java.lang.Stringtypename() + +
+          Get the String name of the type of this value.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, call, call, call, call, callmt, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, error, get, get, get, getfenv, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isfunction, isint, isinttype, islong, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, onInvoke, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setfenv, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+s_metatable

+
+public static LuaValue s_metatable
+
+
+
+
+ + + + + + + + +
+Method Detail
+ +

+type

+
+public int type()
+
+
Description copied from class: LuaValue
+
Get the enumeration value for the type of this value. +

+

+
Specified by:
type in class LuaValue
+
+
+ +
Returns:
value for this type, one of + TNIL, + TBOOLEAN, + TNUMBER, + TSTRING, + TTABLE, + TFUNCTION, + TUSERDATA, + TTHREAD
See Also:
LuaValue.typename()
+
+
+
+ +

+typename

+
+public java.lang.String typename()
+
+
Description copied from class: LuaValue
+
Get the String name of the type of this value. +

+

+

+
Specified by:
typename in class LuaValue
+
+
+ +
Returns:
name from type name list LuaValue.TYPE_NAMES + corresponding to the type of this value: + "nil", "boolean", "number", "string", + "table", "function", "userdata", "thread"
See Also:
LuaValue.type()
+
+
+
+ +

+tojstring

+
+public java.lang.String tojstring()
+
+
Description copied from class: LuaValue
+
Convert to human readable String for any type. +

+

+
Overrides:
tojstring in class LuaValue
+
+
+ +
Returns:
String for use by human readers based on type.
See Also:
LuaValue.tostring(), +LuaValue.optjstring(String), +LuaValue.checkjstring(), +LuaValue.isstring(), +TSTRING
+
+
+
+ +

+not

+
+public LuaValue not()
+
+
Description copied from class: LuaValue
+
Unary not: return inverse boolean value (~this) as defined by lua not operator +

+

+
Overrides:
not in class LuaValue
+
+
+ +
Returns:
TRUE if NIL or FALSE, otherwise FALSE
+
+
+
+ +

+toboolean

+
+public boolean toboolean()
+
+
Description copied from class: LuaValue
+
Convert to boolean false if LuaValue.NIL or FALSE, true if anything else +

+

+
Overrides:
toboolean in class LuaValue
+
+
+ +
Returns:
Value cast to byte if number or string convertible to number, otherwise 0
See Also:
LuaValue.optboolean(boolean), +LuaValue.checkboolean(), +LuaValue.isboolean(), +TBOOLEAN
+
+
+
+ +

+isnil

+
+public boolean isnil()
+
+
Description copied from class: LuaValue
+
Check if this is nil +

+

+
Overrides:
isnil in class LuaValue
+
+
+ +
Returns:
true if this is nil, otherwise false
See Also:
LuaValue.NIL, +LuaValue.NONE, +LuaValue.checknotnil(), +LuaValue.optvalue(LuaValue), +Varargs.isnoneornil(int), +LuaValue.TNIL, +LuaValue.TNONE
+
+
+
+ +

+getmetatable

+
+public LuaValue getmetatable()
+
+
Description copied from class: LuaValue
+
Get the metatable for this LuaValue +

+ For LuaTable and LuaUserdata instances, + the metatable returned is this instance metatable. + For all other types, the class metatable value will be returned. +

+

+
Overrides:
getmetatable in class LuaValue
+
+
+ +
Returns:
metatable, or null if it there is none
See Also:
LuaBoolean.s_metatable, +LuaNumber.s_metatable, +s_metatable, +LuaFunction.s_metatable, +LuaThread.s_metatable
+
+
+
+ +

+equals

+
+public boolean equals(java.lang.Object o)
+
+
+
Overrides:
equals in class LuaValue
+
+
+
+
+
+
+ +

+checknotnil

+
+public LuaValue checknotnil()
+
+
Description copied from class: LuaValue
+
Check that this is not the value NIL, or throw LuaError if it is +

+

+
Overrides:
checknotnil in class LuaValue
+
+
+ +
Returns:
this if it is not NIL
See Also:
LuaValue.optvalue(LuaValue)
+
+
+
+ +

+checkvalidkey

+
+public LuaValue checkvalidkey()
+
+
Description copied from class: LuaValue
+
Check that this is a valid key in a table index operation, or throw LuaError if not +

+

+
Overrides:
checkvalidkey in class LuaValue
+
+
+ +
Returns:
this if valid as a table key
See Also:
LuaValue.isnil(), +LuaValue.isinttype()
+
+
+
+ +

+optboolean

+
+public boolean optboolean(boolean defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a boolean and return its boolean value +

+

+
Overrides:
optboolean in class LuaValue
+
+
+
Parameters:
defval - boolean value to return if this is nil or none +
Returns:
this cast to boolean if a , + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.checkboolean(), +LuaValue.isboolean(), +LuaValue.TBOOLEAN
+
+
+
+ +

+optclosure

+
+public LuaClosure optclosure(LuaClosure defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a closure and return as LuaClosure +

+ A LuaClosure is a that executes lua byteccode. +

+

+
Overrides:
optclosure in class LuaValue
+
+
+
Parameters:
defval - LuaClosure to return if this is nil or none +
Returns:
this cast to LuaClosure if a function, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.checkclosure(), +LuaValue.isclosure(), +LuaValue.TFUNCTION
+
+
+
+ +

+optdouble

+
+public double optdouble(double defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a number or string convertible to number and return as double +

+

+
Overrides:
optdouble in class LuaValue
+
+
+
Parameters:
defval - double to return if this is nil or none +
Returns:
this cast to double if numeric, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.optint(int), +LuaValue.optinteger(LuaInteger), +LuaValue.checkdouble(), +LuaValue.todouble(), +LuaValue.tonumber(), +LuaValue.isnumber(), +LuaValue.TNUMBER
+
+
+
+ +

+optfunction

+
+public LuaFunction optfunction(LuaFunction defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a function and return as LuaFunction +

+ A LuaFunction may either be a Java function that implements + functionality directly in Java, + or a LuaClosure + which is a LuaFunction that executes lua bytecode. +

+

+
Overrides:
optfunction in class LuaValue
+
+
+
Parameters:
defval - LuaFunction to return if this is nil or none +
Returns:
this cast to LuaFunction if a function, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.checkfunction(), +LuaValue.isfunction(), +LuaValue.TFUNCTION
+
+
+
+ +

+optint

+
+public int optint(int defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a number or string convertible to number and return as int +

+

+
Overrides:
optint in class LuaValue
+
+
+
Parameters:
defval - int to return if this is nil or none +
Returns:
this cast to int if numeric, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.optdouble(double), +LuaValue.optlong(long), +LuaValue.optinteger(LuaInteger), +LuaValue.checkint(), +LuaValue.toint(), +LuaValue.tonumber(), +LuaValue.isnumber(), +LuaValue.TNUMBER
+
+
+
+ +

+optinteger

+
+public LuaInteger optinteger(LuaInteger defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a number or string convertible to number and return as LuaInteger +

+

+
Overrides:
optinteger in class LuaValue
+
+
+
Parameters:
defval - LuaInteger to return if this is nil or none +
Returns:
this converted and wrapped in LuaInteger if numeric, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.optdouble(double), +LuaValue.optint(int), +LuaValue.checkint(), +LuaValue.toint(), +LuaValue.tonumber(), +LuaValue.isnumber(), +LuaValue.TNUMBER
+
+
+
+ +

+optlong

+
+public long optlong(long defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a number or string convertible to number and return as long +

+

+
Overrides:
optlong in class LuaValue
+
+
+
Parameters:
defval - long to return if this is nil or none +
Returns:
this cast to long if numeric, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.optdouble(double), +LuaValue.optint(int), +LuaValue.checkint(), +LuaValue.toint(), +LuaValue.tonumber(), +LuaValue.isnumber(), +LuaValue.TNUMBER
+
+
+
+ +

+optnumber

+
+public LuaNumber optnumber(LuaNumber defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a number or string convertible to number and return as LuaNumber +

+

+
Overrides:
optnumber in class LuaValue
+
+
+
Parameters:
defval - LuaNumber to return if this is nil or none +
Returns:
this cast to LuaNumber if numeric, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.optdouble(double), +LuaValue.optlong(long), +LuaValue.optint(int), +LuaValue.checkint(), +LuaValue.toint(), +LuaValue.tonumber(), +LuaValue.isnumber(), +LuaValue.TNUMBER
+
+
+
+ +

+opttable

+
+public LuaTable opttable(LuaTable defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a table and return as LuaTable +

+

+
Overrides:
opttable in class LuaValue
+
+
+
Parameters:
defval - LuaTable to return if this is nil or none +
Returns:
this cast to LuaTable if a table, + defval if nil or none, + throws LuaError if some other type
See Also:
LuaValue.checktable(), +LuaValue.istable(), +LuaValue.TTABLE
+
+
+
+ +

+optthread

+
+public LuaThread optthread(LuaThread defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a thread and return as LuaThread +

+

+
Overrides:
optthread in class LuaValue
+
+
+
Parameters:
defval - LuaThread to return if this is nil or none +
Returns:
this cast to LuaTable if a thread, + defval if nil or none, + throws LuaError if some other type
See Also:
LuaValue.checkthread(), +LuaValue.isthread(), +LuaValue.TTHREAD
+
+
+
+ +

+optjstring

+
+public java.lang.String optjstring(java.lang.String defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a string or number and return as Java String +

+

+
Overrides:
optjstring in class LuaValue
+
+
+
Parameters:
defval - LuaString to return if this is nil or none +
Returns:
this converted to String if a string or number, + defval if nil or none, + throws LuaError if some other type
See Also:
LuaValue.tojstring(), +LuaValue.optstring(LuaString), +LuaValue.checkjstring(), +LuaValue.toString(), +LuaValue.TSTRING
+
+
+
+ +

+optstring

+
+public LuaString optstring(LuaString defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a string or number and return as LuaString +

+

+
Overrides:
optstring in class LuaValue
+
+
+
Parameters:
defval - LuaString to return if this is nil or none +
Returns:
this converted to LuaString if a string or number, + defval if nil or none, + throws LuaError if some other type
See Also:
LuaValue.tojstring(), +LuaValue.optjstring(String), +LuaValue.checkstring(), +LuaValue.toString(), +LuaValue.TSTRING
+
+
+
+ +

+optuserdata

+
+public java.lang.Object optuserdata(java.lang.Object defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a userdata and return the Object instance +

+

+
Overrides:
optuserdata in class LuaValue
+
+
+
Parameters:
defval - Object to return if this is nil or none +
Returns:
Object instance of the userdata if a LuaUserdata, + defval if nil or none, + throws LuaError if some other type
See Also:
LuaValue.checkuserdata(), +LuaValue.isuserdata(), +LuaValue.optuserdata(Class, Object), +LuaValue.TUSERDATA
+
+
+
+ +

+optuserdata

+
+public java.lang.Object optuserdata(java.lang.Class c,
+                                    java.lang.Object defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a userdata whose instance is of a type + and return the Object instance +

+

+
Overrides:
optuserdata in class LuaValue
+
+
+
Parameters:
c - Class to test userdata instance against
defval - Object to return if this is nil or none +
Returns:
Object instance of the userdata if a LuaUserdata and instance is assignable to c, + defval if nil or none, + throws LuaError if some other type
See Also:
LuaValue.checkuserdata(Class), +LuaValue.isuserdata(Class), +LuaValue.optuserdata(Object), +LuaValue.TUSERDATA
+
+
+
+ +

+optvalue

+
+public LuaValue optvalue(LuaValue defval)
+
+
Description copied from class: LuaValue
+
Perform argument check that this is not nil or none. +

+

+
Overrides:
optvalue in class LuaValue
+
+
+
Parameters:
defval - LuaValue to return if this is nil or none +
Returns:
this if not nil or none, else defval
See Also:
LuaValue.NIL, +LuaValue.NONE, +LuaValue.isnil(), +Varargs.isnoneornil(int), +LuaValue.TNIL, +LuaValue.TNONE
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/LuaNumber.html b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaNumber.html new file mode 100644 index 0000000000..9f2e5f34bf --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaNumber.html @@ -0,0 +1,747 @@ + + + + + + +LuaNumber (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class LuaNumber

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaNumber
+
+
+
Direct Known Subclasses:
LuaDouble, LuaInteger
+
+
+
+
public abstract class LuaNumber
extends LuaValue
+ + +

+Base class for representing numbers as lua values directly. +

+ The main subclasses are LuaInteger which holds values that fit in a java int, + and LuaDouble which holds all other number values. +

+ +

+

+
See Also:
LuaInteger, +LuaDouble, +LuaValue
+
+ +

+ + + + + + + + + + + +
+Field Summary
+static LuaValues_metatable + +
+          Shared static metatable for all number values represented in lua.
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + +
+Constructor Summary
LuaNumber() + +
+           
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ LuaNumberchecknumber() + +
+          Check that the value is numeric, and return as a LuaNumber if so, or throw LuaError
+ LuaNumberchecknumber(java.lang.String errmsg) + +
+          Check that the value is numeric, and return as a LuaNumber if so, or throw LuaError
+ Bufferconcat(Buffer rhs) + +
+          Concatenate a Buffer onto this value and return the result + using rules of lua string concatenation including metatag processing.
+ LuaValueconcat(LuaValue rhs) + +
+          Concatenate another value onto this value and return the result + using rules of lua string concatenation including metatag processing.
+ LuaValueconcatTo(LuaNumber lhs) + +
+          Reverse-concatenation: concatenate this value onto another value + known to be a LuaNumber + and return the result using rules of lua string concatenation including + metatag processing.
+ LuaValueconcatTo(LuaString lhs) + +
+          Reverse-concatenation: concatenate this value onto another value + known to be a LuaString + and return the result using rules of lua string concatenation including + metatag processing.
+ LuaValuegetmetatable() + +
+          Get the metatable for this LuaValue
+ booleanisnumber() + +
+          Check if this is a number
+ booleanisstring() + +
+          Check if this is a string
+ LuaNumberoptnumber(LuaNumber defval) + +
+          Check that optional argument is a number or string convertible to number and return as LuaNumber
+ LuaValuetonumber() + +
+          Conditionally convert to lua number without throwing errors.
+ inttype() + +
+          Get the enumeration value for the type of this value.
+ java.lang.Stringtypename() + +
+          Get the String name of the type of this value.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, call, call, call, call, callmt, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concatmt, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getfenv, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isfunction, isint, isinttype, islong, isnil, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setfenv, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+s_metatable

+
+public static LuaValue s_metatable
+
+
Shared static metatable for all number values represented in lua. +

+

+
+
+ + + + + + + + +
+Constructor Detail
+ +

+LuaNumber

+
+public LuaNumber()
+
+
+ + + + + + + + +
+Method Detail
+ +

+type

+
+public int type()
+
+
Description copied from class: LuaValue
+
Get the enumeration value for the type of this value. +

+

+
Specified by:
type in class LuaValue
+
+
+ +
Returns:
value for this type, one of + TNIL, + TBOOLEAN, + TNUMBER, + TSTRING, + TTABLE, + TFUNCTION, + TUSERDATA, + TTHREAD
See Also:
LuaValue.typename()
+
+
+
+ +

+typename

+
+public java.lang.String typename()
+
+
Description copied from class: LuaValue
+
Get the String name of the type of this value. +

+

+

+
Specified by:
typename in class LuaValue
+
+
+ +
Returns:
name from type name list LuaValue.TYPE_NAMES + corresponding to the type of this value: + "nil", "boolean", "number", "string", + "table", "function", "userdata", "thread"
See Also:
LuaValue.type()
+
+
+
+ +

+checknumber

+
+public LuaNumber checknumber()
+
+
Description copied from class: LuaValue
+
Check that the value is numeric, and return as a LuaNumber if so, or throw LuaError +

+ Values that are LuaString that can be converted to a number will be converted and returned. +

+

+
Overrides:
checknumber in class LuaValue
+
+
+ +
Returns:
value as a LuaNumber if numeric
See Also:
LuaValue.checkint(), +LuaValue.checkinteger(), +LuaValue.checkdouble(), +LuaValue.checklong(), +LuaValue.optnumber(LuaNumber), +LuaValue.TNUMBER
+
+
+
+ +

+checknumber

+
+public LuaNumber checknumber(java.lang.String errmsg)
+
+
Description copied from class: LuaValue
+
Check that the value is numeric, and return as a LuaNumber if so, or throw LuaError +

+ Values that are LuaString that can be converted to a number will be converted and returned. +

+

+
Overrides:
checknumber in class LuaValue
+
+
+
Parameters:
errmsg - String message to supply if conversion fails +
Returns:
value as a LuaNumber if numeric
See Also:
LuaValue.checkint(), +LuaValue.checkinteger(), +LuaValue.checkdouble(), +LuaValue.checklong(), +LuaValue.optnumber(LuaNumber), +LuaValue.TNUMBER
+
+
+
+ +

+optnumber

+
+public LuaNumber optnumber(LuaNumber defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a number or string convertible to number and return as LuaNumber +

+

+
Overrides:
optnumber in class LuaValue
+
+
+
Parameters:
defval - LuaNumber to return if this is nil or none +
Returns:
this cast to LuaNumber if numeric, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.optdouble(double), +LuaValue.optlong(long), +LuaValue.optint(int), +LuaValue.checkint(), +LuaValue.toint(), +LuaValue.tonumber(), +LuaValue.isnumber(), +LuaValue.TNUMBER
+
+
+
+ +

+tonumber

+
+public LuaValue tonumber()
+
+
Description copied from class: LuaValue
+
Conditionally convert to lua number without throwing errors. +

+ In lua all numbers are strings, but not all strings are numbers. + This function will return + the LuaValue this if it is a number + or a string convertible to a number, + and NIL for all other cases. +

+ This allows values to be tested for their "numeric-ness" without + the penalty of throwing exceptions, + nor the cost of converting the type and creating storage for it. +

+

+
Overrides:
tonumber in class LuaValue
+
+
+ +
Returns:
this if it is a LuaNumber + or LuaString that can be converted to a number, + otherwise LuaValue.NIL
See Also:
LuaValue.tostring(), +LuaValue.optnumber(LuaNumber), +LuaValue.checknumber(), +LuaValue.toint(), +LuaValue.todouble()
+
+
+
+ +

+isnumber

+
+public boolean isnumber()
+
+
Description copied from class: LuaValue
+
Check if this is a number +

+

+
Overrides:
isnumber in class LuaValue
+
+
+ +
Returns:
true if this is a number, + meaning derives from LuaNumber + or derives from LuaString and is convertible to a number, + otherwise false
See Also:
LuaValue.tonumber(), +LuaValue.checknumber(), +LuaValue.optnumber(LuaNumber), +LuaValue.TNUMBER
+
+
+
+ +

+isstring

+
+public boolean isstring()
+
+
Description copied from class: LuaValue
+
Check if this is a string +

+

+
Overrides:
isstring in class LuaValue
+
+
+ +
Returns:
true if this is a string, + meaning derives from LuaString or LuaNumber, + otherwise false
See Also:
LuaValue.tostring(), +LuaValue.checkstring(), +LuaValue.optstring(LuaString), +LuaValue.TSTRING
+
+
+
+ +

+getmetatable

+
+public LuaValue getmetatable()
+
+
Description copied from class: LuaValue
+
Get the metatable for this LuaValue +

+ For LuaTable and LuaUserdata instances, + the metatable returned is this instance metatable. + For all other types, the class metatable value will be returned. +

+

+
Overrides:
getmetatable in class LuaValue
+
+
+ +
Returns:
metatable, or null if it there is none
See Also:
LuaBoolean.s_metatable, +s_metatable, +LuaNil.s_metatable, +LuaFunction.s_metatable, +LuaThread.s_metatable
+
+
+
+ +

+concat

+
+public LuaValue concat(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Concatenate another value onto this value and return the result + using rules of lua string concatenation including metatag processing. +

+ Only strings and numbers as represented can be concatenated, meaning + each operand must derive from LuaString or LuaNumber. +

+

+
Overrides:
concat in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the operation with
+
+
+
+ +

+concat

+
+public Buffer concat(Buffer rhs)
+
+
Description copied from class: LuaValue
+
Concatenate a Buffer onto this value and return the result + using rules of lua string concatenation including metatag processing. +

+ Only strings and numbers as represented can be concatenated, meaning + each operand must derive from LuaString or LuaNumber. +

+

+
Overrides:
concat in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side Buffer to perform the operation with +
Returns:
LuaString resulting from concatenation of (this .. rhs)
+
+
+
+ +

+concatTo

+
+public LuaValue concatTo(LuaNumber lhs)
+
+
Description copied from class: LuaValue
+
Reverse-concatenation: concatenate this value onto another value + known to be a LuaNumber + and return the result using rules of lua string concatenation including + metatag processing. +

+ Only strings and numbers as represented can be concatenated, meaning + each operand must derive from LuaString or LuaNumber. +

+

+
Overrides:
concatTo in class LuaValue
+
+
+
Parameters:
lhs - The left-hand-side value onto which this will be concatenated
See Also:
LuaValue.concat(LuaValue)
+
+
+
+ +

+concatTo

+
+public LuaValue concatTo(LuaString lhs)
+
+
Description copied from class: LuaValue
+
Reverse-concatenation: concatenate this value onto another value + known to be a LuaString + and return the result using rules of lua string concatenation including + metatag processing. +

+ Only strings and numbers as represented can be concatenated, meaning + each operand must derive from LuaString or LuaNumber. +

+

+
Overrides:
concatTo in class LuaValue
+
+
+
Parameters:
lhs - The left-hand-side value onto which this will be concatenated
See Also:
LuaValue.concat(LuaValue)
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/LuaString.html b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaString.html new file mode 100644 index 0000000000..3bf0a1a7cb --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaString.html @@ -0,0 +1,3786 @@ + + + + + + +LuaString (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class LuaString

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaString
+
+
+
+
public class LuaString
extends LuaValue
+ + +

+Subclass of LuaValue for representing lua strings. +

+ Because lua string values are more nearly sequences of bytes than + sequences of characters or unicode code points, the LuaString + implementation holds the string value in an internal byte array. +

+ LuaString values are generally not mutable once constructed, + so multiple LuaString values can chare a single byte array. +

+ Currently LuaStrings are pooled via a centrally managed weak table. + To ensure that as many string values as possible take advantage of this, + Constructors are not exposed directly. As with number, booleans, and nil, + instance construction should be via LuaValue.valueOf(byte[]) or similar API. +

+ When Java Strings are used to initialize LuaString data, the UTF8 encoding is assumed. + The functions + LuaString#lengthAsUtf8(char[]), + {@link LuaString#encodeToUtf8(char[], byte[], int)}, and + {@link LuaString#decodeAsUtf8(byte[], int, int) + are used to convert back and forth between UTF8 byte arrays and character arrays. +

+ +

+

+
See Also:
LuaValue, +LuaValue.valueOf(String), +LuaValue.valueOf(byte[])
+
+ +

+ + + + + + + + + + + + + + + + + + + + + + + +
+Field Summary
+ byte[]m_bytes + +
+          The bytes for the string
+ intm_length + +
+          The number of bytes that comprise this string
+ intm_offset + +
+          The offset into the byte array, 0 means start at the first byte
+static LuaValues_metatable + +
+          The singleton instance representing lua true
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ LuaValueadd(double rhs) + +
+          Add: Perform numeric add operation with another value + of double type with metatag processing
+ LuaValueadd(int rhs) + +
+          Add: Perform numeric add operation with another value + of int type with metatag processing
+ LuaValueadd(LuaValue rhs) + +
+          Add: Perform numeric add operation with another value + including metatag processing.
+ intcharAt(int index) + +
+           
+ doublecheckdouble() + +
+          Check that the value is numeric and return the value as a double, + or throw LuaError if not numeric
+ intcheckint() + +
+          Check that the value is numeric, and convert and cast value to int, or throw LuaError if not numeric
+ LuaIntegercheckinteger() + +
+          Check that the value is numeric, and convert and cast value to int, or throw LuaError if not numeric
+ java.lang.Stringcheckjstring() + +
+          Convert this value to a Java String.
+ longchecklong() + +
+          Check that the value is numeric, and convert and cast value to long, or throw LuaError if not numeric
+ LuaNumberchecknumber() + +
+          Check that the value is numeric, and return as a LuaNumber if so, or throw LuaError
+ LuaNumberchecknumber(java.lang.String msg) + +
+          Check that the value is numeric, and return as a LuaNumber if so, or throw LuaError
+ LuaStringcheckstring() + +
+          Check that this is a lua string, or throw LuaError if it is not.
+ Bufferconcat(Buffer rhs) + +
+          Concatenate a Buffer onto this value and return the result + using rules of lua string concatenation including metatag processing.
+ LuaValueconcat(LuaValue rhs) + +
+          Concatenate another value onto this value and return the result + using rules of lua string concatenation including metatag processing.
+ LuaValueconcatTo(LuaNumber lhs) + +
+          Reverse-concatenation: concatenate this value onto another value + known to be a LuaNumber + and return the result using rules of lua string concatenation including + metatag processing.
+ LuaValueconcatTo(LuaString lhs) + +
+          Reverse-concatenation: concatenate this value onto another value + known to be a LuaString + and return the result using rules of lua string concatenation including + metatag processing.
+ voidcopyInto(int strOffset, + byte[] bytes, + int arrayOffset, + int len) + +
+          Copy the bytes of the string into the given byte array.
+static java.lang.StringdecodeAsUtf8(byte[] bytes, + int offset, + int length) + +
+          Convert to Java String interpreting as utf8 characters.
+ LuaValuediv(double rhs) + +
+          Divide: Perform numeric divide operation by another value + of double type without metatag processing
+ LuaValuediv(int rhs) + +
+          Divide: Perform numeric divide operation by another value + of int type without metatag processing
+ LuaValuediv(LuaValue rhs) + +
+          Divide: Perform numeric divide operation by another value + of unknown type, + including metatag processing.
+ LuaValuedivInto(double lhs) + +
+          Reverse-divide: Perform numeric divide operation into another value + with metatag processing
+static voidencodeToUtf8(char[] chars, + byte[] bytes, + int off) + +
+          Encode the given Java string as UTF-8 bytes, writing the result to bytes + starting at offset.
+ booleaneq_b(LuaValue val) + +
+          Equals: Perform equality comparison with another value + including metatag processing using EQ, + and return java boolean
+ LuaValueeq(LuaValue val) + +
+          Equals: Perform equality comparison with another value + including metatag processing using EQ.
+static booleanequals(byte[] a, + int i, + byte[] b, + int j, + int n) + +
+           
+static booleanequals(LuaString a, + int i, + LuaString b, + int j, + int n) + +
+           
+ booleanequals(java.lang.Object o) + +
+           
+ LuaValueget(LuaValue key) + +
+          Get a value in a table including metatag processing using INDEX.
+ LuaValuegetmetatable() + +
+          Get the metatable for this LuaValue
+ booleangt_b(double rhs) + +
+          Greater than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ booleangt_b(int rhs) + +
+          Greater than: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean.
+ booleangt_b(LuaValue rhs) + +
+          Greater than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ LuaValuegt(LuaValue rhs) + +
+          Greater than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ booleangteq_b(double rhs) + +
+          Greater than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, + and returning java boolean.
+ booleangteq_b(int rhs) + +
+          Greater than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean.
+ booleangteq_b(LuaValue rhs) + +
+          Greater than or equals: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ LuaValuegteq(LuaValue rhs) + +
+          Greater than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ inthashCode() + +
+           
+ intindexOf(byte b, + int start) + +
+          Find the index of a byte starting at a point in this string
+ intindexOf(LuaString s, + int start) + +
+          Find the index of a string starting at a point in this string
+ intindexOfAny(LuaString accept) + +
+          Java version of strpbrk - find index of any byte that in an accept string.
+ booleanisint() + +
+          Check if this is a number and is representable by java int + without rounding or truncation
+ booleanislong() + +
+          Check if this is a number and is representable by java long + without rounding or truncation
+ booleanisnumber() + +
+          Check if this is a number
+ booleanisstring() + +
+          Check if this is a string
+ booleanisValidUtf8() + +
+          Check that a byte sequence is valid UTF-8
+ intlastIndexOf(LuaString s) + +
+          Find the last index of a string in this string
+ LuaValuelen() + +
+          Length operator: return lua length of object (#this) including metatag processing as java int
+ intlength() + +
+          Length operator: return lua length of object (#this) including metatag processing as java int
+static intlengthAsUtf8(char[] chars) + +
+          Count the number of bytes required to encode the string as UTF-8.
+ booleanlt_b(double rhs) + +
+          Less than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ booleanlt_b(int rhs) + +
+          Less than: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean.
+ booleanlt_b(LuaValue rhs) + +
+          Less than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ LuaValuelt(LuaValue rhs) + +
+          Less than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ booleanlteq_b(double rhs) + +
+          Less than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, + and returning java boolean.
+ booleanlteq_b(int rhs) + +
+          Less than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean.
+ booleanlteq_b(LuaValue rhs) + +
+          Less than or equals: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ LuaValuelteq(LuaValue rhs) + +
+          Less than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ intluaByte(int index) + +
+           
+ LuaValuemod(double rhs) + +
+          Modulo: Perform numeric modulo operation with another value + of double type without metatag processing
+ LuaValuemod(int rhs) + +
+          Modulo: Perform numeric modulo operation with another value + of int type without metatag processing
+ LuaValuemod(LuaValue rhs) + +
+          Modulo: Perform numeric modulo operation with another value + of unknown type, + including metatag processing.
+ LuaValuemodFrom(double lhs) + +
+          Reverse-modulo: Perform numeric modulo operation from another value + with metatag processing
+ LuaValuemul(double rhs) + +
+          Multiply: Perform numeric multiply operation with another value + of double type with metatag processing
+ LuaValuemul(int rhs) + +
+          Multiply: Perform numeric multiply operation with another value + of int type with metatag processing
+ LuaValuemul(LuaValue rhs) + +
+          Multiply: Perform numeric multiply operation with another value + of unknown type, + including metatag processing.
+ LuaValueneg() + +
+          Unary minus: return negative value (-this) as defined by lua unary minus operator
+ doubleoptdouble(double defval) + +
+          Check that optional argument is a number or string convertible to number and return as double
+ intoptint(int defval) + +
+          Check that optional argument is a number or string convertible to number and return as int
+ LuaIntegeroptinteger(LuaInteger defval) + +
+          Check that optional argument is a number or string convertible to number and return as LuaInteger
+ java.lang.Stringoptjstring(java.lang.String defval) + +
+          Check that optional argument is a string or number and return as Java String
+ longoptlong(long defval) + +
+          Check that optional argument is a number or string convertible to number and return as long
+ LuaNumberoptnumber(LuaNumber defval) + +
+          Check that optional argument is a number or string convertible to number and return as LuaNumber
+ LuaStringoptstring(LuaString defval) + +
+          Check that optional argument is a string or number and return as LuaString
+ LuaValuepow(double rhs) + +
+          Raise to power: Raise this value to a power + of double type with metatag processing
+ LuaValuepow(int rhs) + +
+          Raise to power: Raise this value to a power + of int type with metatag processing
+ LuaValuepow(LuaValue rhs) + +
+          Raise to power: Raise this value to a power + including metatag processing.
+ LuaValuepowWith(double lhs) + +
+          Reverse-raise to power: Raise another value of double type to this power + with metatag processing
+ LuaValuepowWith(int lhs) + +
+          Reverse-raise to power: Raise another value of double type to this power + with metatag processing
+ booleanraweq(LuaString s) + +
+          Equals: Perform direct equality comparison with a LuaString value + without metatag processing.
+ booleanraweq(LuaValue val) + +
+          Equals: Perform direct equality comparison with another value + without metatag processing.
+ doublescannumber(int base) + +
+          Convert to a number in a base, or return Double.NaN if not a number.
+ intstrcmp(LuaString rhs) + +
+          Perform string comparison with another value + known to be a LuaString + using string comparison based on byte values.
+ intstrcmp(LuaValue lhs) + +
+          Perform string comparison with another value + of any type + using string comparison based on byte values.
+ LuaStringstrvalue() + +
+          Convert this value to a string if it is a LuaString or LuaNumber, + or throw a LuaError if it is not
+ LuaValuesub(double rhs) + +
+          Subtract: Perform numeric subtract operation with another value + of double type with metatag processing
+ LuaValuesub(int rhs) + +
+          Subtract: Perform numeric subtract operation with another value + of int type with metatag processing
+ LuaValuesub(LuaValue rhs) + +
+          Subtract: Perform numeric subtract operation with another value + of unknown type, + including metatag processing.
+ LuaValuesubFrom(double lhs) + +
+          Reverse-subtract: Perform numeric subtract operation from an int value + with metatag processing
+ LuaStringsubstring(int beginIndex, + int endIndex) + +
+           
+ bytetobyte() + +
+          Convert to byte if numeric, or 0 if not.
+ chartochar() + +
+          Convert to char if numeric, or 0 if not.
+ doubletodouble() + +
+          Convert to double if numeric, or 0 if not.
+ floattofloat() + +
+          Convert to float if numeric, or 0 if not.
+ java.io.InputStreamtoInputStream() + +
+          Convert value to an input stream.
+ inttoint() + +
+          Convert to int if numeric, or 0 if not.
+ java.lang.Stringtojstring() + +
+          Convert to human readable String for any type.
+ longtolong() + +
+          Convert to long if numeric, or 0 if not.
+ LuaValuetonumber() + +
+          Conditionally convert to lua number without throwing errors.
+ LuaValuetonumber(int base) + +
+          convert to a number using a supplied base, or NIL if it can't be converted
+ shorttoshort() + +
+          Convert to short if numeric, or 0 if not.
+ LuaValuetostring() + +
+          Conditionally convert to lua string without throwing errors.
+ inttype() + +
+          Get the enumeration value for the type of this value.
+ java.lang.Stringtypename() + +
+          Get the String name of the type of this value.
+static LuaStringvalueOf(byte[] bytes) + +
+          Construct a LuaString around a byte array without copying the contents.
+static LuaStringvalueOf(byte[] bytes, + int off, + int len) + +
+          Construct a LuaString around a byte array without copying the contents.
+static LuaStringvalueOf(char[] bytes) + +
+          Construct a LuaString using the supplied characters as byte values.
+static LuaStringvalueOf(java.lang.String string) + +
+          Get a LuaString instance whose bytes match + the supplied Java String using the UTF8 encoding.
+ voidwrite(java.io.DataOutputStream writer, + int i, + int len) + +
+           
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, call, call, call, call, callmt, checkboolean, checkclosure, checkfunction, checkmetatag, checknotnil, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concatmt, concatTo, eqmtcall, error, get, get, getfenv, getn, gettable, gt, gt, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isfunction, isinttype, isnil, istable, isthread, isuserdata, isuserdata, isweaknil, lenerror, listOf, listOf, load, lt, lt, lteq, lteq, metatag, method, method, method, method, method, method, narg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optfunction, opttable, optthread, optuserdata, optuserdata, optvalue, or, presize, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setfenv, setmetatable, settable, strongkey, strongvalue, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+s_metatable

+
+public static LuaValue s_metatable
+
+
The singleton instance representing lua true +

+

+
+
+
+ +

+m_bytes

+
+public final byte[] m_bytes
+
+
The bytes for the string +

+

+
+
+
+ +

+m_offset

+
+public final int m_offset
+
+
The offset into the byte array, 0 means start at the first byte +

+

+
+
+
+ +

+m_length

+
+public final int m_length
+
+
The number of bytes that comprise this string +

+

+
+
+ + + + + + + + +
+Method Detail
+ +

+valueOf

+
+public static LuaString valueOf(java.lang.String string)
+
+
Get a LuaString instance whose bytes match + the supplied Java String using the UTF8 encoding. +

+

+
Parameters:
string - Java String containing characters to encode as UTF8 +
Returns:
LuaString with UTF8 bytes corresponding to the supplied String
+
+
+
+ +

+valueOf

+
+public static LuaString valueOf(byte[] bytes,
+                                int off,
+                                int len)
+
+
Construct a LuaString around a byte array without copying the contents. +

+ The array is used directly after this is called, so clients must not change contents. +

+

+

+
Parameters:
bytes - byte buffer
off - offset into the byte buffer
len - length of the byte buffer +
Returns:
LuaString wrapping the byte buffer
+
+
+
+ +

+valueOf

+
+public static LuaString valueOf(char[] bytes)
+
+
Construct a LuaString using the supplied characters as byte values. +

+ Only th elow-order 8-bits of each character are used, the remainder is ignored. +

+ This is most useful for constructing byte sequences that do not conform to UTF8. +

+

+
Parameters:
bytes - array of char, whose values are truncated at 8-bits each and put into a byte array. +
Returns:
LuaString wrapping a copy of the byte buffer
+
+
+
+ +

+valueOf

+
+public static LuaString valueOf(byte[] bytes)
+
+
Construct a LuaString around a byte array without copying the contents. +

+ The array is used directly after this is called, so clients must not change contents. +

+

+

+
Parameters:
bytes - byte buffer +
Returns:
LuaString wrapping the byte buffer
+
+
+
+ +

+isstring

+
+public boolean isstring()
+
+
Description copied from class: LuaValue
+
Check if this is a string +

+

+
Overrides:
isstring in class LuaValue
+
+
+ +
Returns:
true if this is a string, + meaning derives from LuaString or LuaNumber, + otherwise false
See Also:
LuaValue.tostring(), +LuaValue.checkstring(), +LuaValue.optstring(LuaString), +LuaValue.TSTRING
+
+
+
+ +

+getmetatable

+
+public LuaValue getmetatable()
+
+
Description copied from class: LuaValue
+
Get the metatable for this LuaValue +

+ For LuaTable and LuaUserdata instances, + the metatable returned is this instance metatable. + For all other types, the class metatable value will be returned. +

+

+
Overrides:
getmetatable in class LuaValue
+
+
+ +
Returns:
metatable, or null if it there is none
See Also:
LuaBoolean.s_metatable, +LuaNumber.s_metatable, +LuaNil.s_metatable, +LuaFunction.s_metatable, +LuaThread.s_metatable
+
+
+
+ +

+type

+
+public int type()
+
+
Description copied from class: LuaValue
+
Get the enumeration value for the type of this value. +

+

+
Specified by:
type in class LuaValue
+
+
+ +
Returns:
value for this type, one of + TNIL, + TBOOLEAN, + TNUMBER, + TSTRING, + TTABLE, + TFUNCTION, + TUSERDATA, + TTHREAD
See Also:
LuaValue.typename()
+
+
+
+ +

+typename

+
+public java.lang.String typename()
+
+
Description copied from class: LuaValue
+
Get the String name of the type of this value. +

+

+

+
Specified by:
typename in class LuaValue
+
+
+ +
Returns:
name from type name list LuaValue.TYPE_NAMES + corresponding to the type of this value: + "nil", "boolean", "number", "string", + "table", "function", "userdata", "thread"
See Also:
LuaValue.type()
+
+
+
+ +

+tojstring

+
+public java.lang.String tojstring()
+
+
Description copied from class: LuaValue
+
Convert to human readable String for any type. +

+

+
Overrides:
tojstring in class LuaValue
+
+
+ +
Returns:
String for use by human readers based on type.
See Also:
LuaValue.tostring(), +LuaValue.optjstring(String), +LuaValue.checkjstring(), +LuaValue.isstring(), +TSTRING
+
+
+
+ +

+get

+
+public LuaValue get(LuaValue key)
+
+
Description copied from class: LuaValue
+
Get a value in a table including metatag processing using INDEX. +

+

+
Overrides:
get in class LuaValue
+
+
+
Parameters:
key - the key to look up, must not be NIL or null +
Returns:
LuaValue for that key, or NIL if not found and no metatag
See Also:
LuaValue.get(int), +LuaValue.get(String), +LuaValue.rawget(LuaValue)
+
+
+
+ +

+neg

+
+public LuaValue neg()
+
+
Description copied from class: LuaValue
+
Unary minus: return negative value (-this) as defined by lua unary minus operator +

+

+
Overrides:
neg in class LuaValue
+
+
+ +
Returns:
boolean inverse as LuaBoolean if boolean or nil, + numeric inverse as if numeric, + or metatag processing result if UNM metatag is defined
+
+
+
+ +

+add

+
+public LuaValue add(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Add: Perform numeric add operation with another value + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
add in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the add with +
Returns:
value of (this + rhs) if both are numeric, + or LuaValue if metatag processing occurs
See Also:
LuaValue.arithmt(LuaValue, LuaValue)
+
+
+
+ +

+add

+
+public LuaValue add(double rhs)
+
+
Description copied from class: LuaValue
+
Add: Perform numeric add operation with another value + of double type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
add in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the add with +
Returns:
value of (this + rhs) if this is numeric
See Also:
LuaValue.add(LuaValue)
+
+
+
+ +

+add

+
+public LuaValue add(int rhs)
+
+
Description copied from class: LuaValue
+
Add: Perform numeric add operation with another value + of int type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
add in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the add with +
Returns:
value of (this + rhs) if this is numeric
See Also:
LuaValue.add(LuaValue)
+
+
+
+ +

+sub

+
+public LuaValue sub(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Subtract: Perform numeric subtract operation with another value + of unknown type, + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
sub in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the subtract with +
Returns:
value of (this - rhs) if both are numeric, + or LuaValue if metatag processing occurs
See Also:
LuaValue.arithmt(LuaValue, LuaValue)
+
+
+
+ +

+sub

+
+public LuaValue sub(double rhs)
+
+
Description copied from class: LuaValue
+
Subtract: Perform numeric subtract operation with another value + of double type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
sub in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the subtract with +
Returns:
value of (this - rhs) if this is numeric
See Also:
LuaValue.sub(LuaValue)
+
+
+
+ +

+sub

+
+public LuaValue sub(int rhs)
+
+
Description copied from class: LuaValue
+
Subtract: Perform numeric subtract operation with another value + of int type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
sub in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the subtract with +
Returns:
value of (this - rhs) if this is numeric
See Also:
LuaValue.sub(LuaValue)
+
+
+
+ +

+subFrom

+
+public LuaValue subFrom(double lhs)
+
+
Description copied from class: LuaValue
+
Reverse-subtract: Perform numeric subtract operation from an int value + with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
subFrom in class LuaValue
+
+
+
Parameters:
lhs - The left-hand-side value from which to perform the subtraction +
Returns:
value of (lhs - this) if this is numeric
See Also:
LuaValue.sub(LuaValue), +LuaValue.sub(double), +LuaValue.sub(int)
+
+
+
+ +

+mul

+
+public LuaValue mul(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Multiply: Perform numeric multiply operation with another value + of unknown type, + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
mul in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the multiply with +
Returns:
value of (this * rhs) if both are numeric, + or LuaValue if metatag processing occurs
See Also:
LuaValue.arithmt(LuaValue, LuaValue)
+
+
+
+ +

+mul

+
+public LuaValue mul(double rhs)
+
+
Description copied from class: LuaValue
+
Multiply: Perform numeric multiply operation with another value + of double type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
mul in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the multiply with +
Returns:
value of (this * rhs) if this is numeric
See Also:
LuaValue.mul(LuaValue)
+
+
+
+ +

+mul

+
+public LuaValue mul(int rhs)
+
+
Description copied from class: LuaValue
+
Multiply: Perform numeric multiply operation with another value + of int type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
mul in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the multiply with +
Returns:
value of (this * rhs) if this is numeric
See Also:
LuaValue.mul(LuaValue)
+
+
+
+ +

+pow

+
+public LuaValue pow(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Raise to power: Raise this value to a power + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
pow in class LuaValue
+
+
+
Parameters:
rhs - The power to raise this value to +
Returns:
value of (this ^ rhs) if both are numeric, + or LuaValue if metatag processing occurs
See Also:
LuaValue.arithmt(LuaValue, LuaValue)
+
+
+
+ +

+pow

+
+public LuaValue pow(double rhs)
+
+
Description copied from class: LuaValue
+
Raise to power: Raise this value to a power + of double type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
pow in class LuaValue
+
+
+
Parameters:
rhs - The power to raise this value to +
Returns:
value of (this ^ rhs) if this is numeric
See Also:
LuaValue.pow(LuaValue)
+
+
+
+ +

+pow

+
+public LuaValue pow(int rhs)
+
+
Description copied from class: LuaValue
+
Raise to power: Raise this value to a power + of int type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
pow in class LuaValue
+
+
+
Parameters:
rhs - The power to raise this value to +
Returns:
value of (this ^ rhs) if this is numeric
See Also:
LuaValue.pow(LuaValue)
+
+
+
+ +

+powWith

+
+public LuaValue powWith(double lhs)
+
+
Description copied from class: LuaValue
+
Reverse-raise to power: Raise another value of double type to this power + with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
powWith in class LuaValue
+
+
+
Parameters:
lhs - The left-hand-side value which will be raised to this power +
Returns:
value of (lhs ^ this) if this is numeric
See Also:
LuaValue.pow(LuaValue), +LuaValue.pow(double), +LuaValue.pow(int)
+
+
+
+ +

+powWith

+
+public LuaValue powWith(int lhs)
+
+
Description copied from class: LuaValue
+
Reverse-raise to power: Raise another value of double type to this power + with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
powWith in class LuaValue
+
+
+
Parameters:
lhs - The left-hand-side value which will be raised to this power +
Returns:
value of (lhs ^ this) if this is numeric
See Also:
LuaValue.pow(LuaValue), +LuaValue.pow(double), +LuaValue.pow(int)
+
+
+
+ +

+div

+
+public LuaValue div(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Divide: Perform numeric divide operation by another value + of unknown type, + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
div in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the divulo with +
Returns:
value of (this / rhs) if both are numeric, + or LuaValue if metatag processing occurs
See Also:
LuaValue.arithmt(LuaValue, LuaValue)
+
+
+
+ +

+div

+
+public LuaValue div(double rhs)
+
+
Description copied from class: LuaValue
+
Divide: Perform numeric divide operation by another value + of double type without metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+ For metatag processing LuaValue.div(LuaValue) must be used +

+

+
Overrides:
div in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the divulo with +
Returns:
value of (this / rhs) if this is numeric
See Also:
LuaValue.div(LuaValue)
+
+
+
+ +

+div

+
+public LuaValue div(int rhs)
+
+
Description copied from class: LuaValue
+
Divide: Perform numeric divide operation by another value + of int type without metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+ For metatag processing LuaValue.div(LuaValue) must be used +

+

+
Overrides:
div in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the divulo with +
Returns:
value of (this / rhs) if this is numeric
See Also:
LuaValue.div(LuaValue)
+
+
+
+ +

+divInto

+
+public LuaValue divInto(double lhs)
+
+
Description copied from class: LuaValue
+
Reverse-divide: Perform numeric divide operation into another value + with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
divInto in class LuaValue
+
+
+
Parameters:
lhs - The left-hand-side value which will be divided by this +
Returns:
value of (lhs / this) if this is numeric
See Also:
LuaValue.div(LuaValue), +LuaValue.div(double), +LuaValue.div(int)
+
+
+
+ +

+mod

+
+public LuaValue mod(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Modulo: Perform numeric modulo operation with another value + of unknown type, + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
mod in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the modulo with +
Returns:
value of (this % rhs) if both are numeric, + or LuaValue if metatag processing occurs
See Also:
LuaValue.arithmt(LuaValue, LuaValue)
+
+
+
+ +

+mod

+
+public LuaValue mod(double rhs)
+
+
Description copied from class: LuaValue
+
Modulo: Perform numeric modulo operation with another value + of double type without metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+ For metatag processing LuaValue.mod(LuaValue) must be used +

+

+
Overrides:
mod in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the modulo with +
Returns:
value of (this % rhs) if this is numeric
See Also:
LuaValue.mod(LuaValue)
+
+
+
+ +

+mod

+
+public LuaValue mod(int rhs)
+
+
Description copied from class: LuaValue
+
Modulo: Perform numeric modulo operation with another value + of int type without metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+ For metatag processing LuaValue.mod(LuaValue) must be used +

+

+
Overrides:
mod in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the modulo with +
Returns:
value of (this % rhs) if this is numeric
See Also:
LuaValue.mod(LuaValue)
+
+
+
+ +

+modFrom

+
+public LuaValue modFrom(double lhs)
+
+
Description copied from class: LuaValue
+
Reverse-modulo: Perform numeric modulo operation from another value + with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Overrides:
modFrom in class LuaValue
+
+
+
Parameters:
lhs - The left-hand-side value which will be modulo'ed by this +
Returns:
value of (lhs % this) if this is numeric
See Also:
LuaValue.mod(LuaValue), +LuaValue.mod(double), +LuaValue.mod(int)
+
+
+
+ +

+lt

+
+public LuaValue lt(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Less than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
lt in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this < rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lt_b

+
+public boolean lt_b(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Less than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
lt_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this < rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lt_b

+
+public boolean lt_b(int rhs)
+
+
Description copied from class: LuaValue
+
Less than: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
lt_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this < rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(int), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lt_b

+
+public boolean lt_b(double rhs)
+
+
Description copied from class: LuaValue
+
Less than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
lt_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this < rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq

+
+public LuaValue lteq(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Less than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
lteq in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this <= rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq_b

+
+public boolean lteq_b(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Less than or equals: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
lteq_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this <= rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq_b

+
+public boolean lteq_b(int rhs)
+
+
Description copied from class: LuaValue
+
Less than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
lteq_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this <= rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(int), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq_b

+
+public boolean lteq_b(double rhs)
+
+
Description copied from class: LuaValue
+
Less than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
lteq_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this <= rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(double), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt

+
+public LuaValue gt(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Greater than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
gt in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this > rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt_b

+
+public boolean gt_b(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Greater than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
gt_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this > rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt_b

+
+public boolean gt_b(int rhs)
+
+
Description copied from class: LuaValue
+
Greater than: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
gt_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this > rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(int), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt_b

+
+public boolean gt_b(double rhs)
+
+
Description copied from class: LuaValue
+
Greater than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
gt_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this > rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq

+
+public LuaValue gteq(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Greater than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
gteq in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this >= rhs), FALSE if not, + or LuaValue if metatag processing occurs
See Also:
LuaValue.gteq_b(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq_b

+
+public boolean gteq_b(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Greater than or equals: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Overrides:
gteq_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this >= rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(LuaValue), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq_b

+
+public boolean gteq_b(int rhs)
+
+
Description copied from class: LuaValue
+
Greater than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
gteq_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this >= rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(int), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq_b

+
+public boolean gteq_b(double rhs)
+
+
Description copied from class: LuaValue
+
Greater than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Overrides:
gteq_b in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this >= rhs), false if not, + and boolean interpreation of result if metatag processing occurs.
See Also:
LuaValue.gteq(double), +LuaValue.comparemt(LuaValue, LuaValue)
+
+
+
+ +

+concat

+
+public LuaValue concat(LuaValue rhs)
+
+
Description copied from class: LuaValue
+
Concatenate another value onto this value and return the result + using rules of lua string concatenation including metatag processing. +

+ Only strings and numbers as represented can be concatenated, meaning + each operand must derive from LuaString or LuaNumber. +

+

+
Overrides:
concat in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the operation with
+
+
+
+ +

+concat

+
+public Buffer concat(Buffer rhs)
+
+
Description copied from class: LuaValue
+
Concatenate a Buffer onto this value and return the result + using rules of lua string concatenation including metatag processing. +

+ Only strings and numbers as represented can be concatenated, meaning + each operand must derive from LuaString or LuaNumber. +

+

+
Overrides:
concat in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side Buffer to perform the operation with +
Returns:
LuaString resulting from concatenation of (this .. rhs)
+
+
+
+ +

+concatTo

+
+public LuaValue concatTo(LuaNumber lhs)
+
+
Description copied from class: LuaValue
+
Reverse-concatenation: concatenate this value onto another value + known to be a LuaNumber + and return the result using rules of lua string concatenation including + metatag processing. +

+ Only strings and numbers as represented can be concatenated, meaning + each operand must derive from LuaString or LuaNumber. +

+

+
Overrides:
concatTo in class LuaValue
+
+
+
Parameters:
lhs - The left-hand-side value onto which this will be concatenated
See Also:
LuaValue.concat(LuaValue)
+
+
+
+ +

+concatTo

+
+public LuaValue concatTo(LuaString lhs)
+
+
Description copied from class: LuaValue
+
Reverse-concatenation: concatenate this value onto another value + known to be a LuaString + and return the result using rules of lua string concatenation including + metatag processing. +

+ Only strings and numbers as represented can be concatenated, meaning + each operand must derive from LuaString or LuaNumber. +

+

+
Overrides:
concatTo in class LuaValue
+
+
+
Parameters:
lhs - The left-hand-side value onto which this will be concatenated
See Also:
LuaValue.concat(LuaValue)
+
+
+
+ +

+strcmp

+
+public int strcmp(LuaValue lhs)
+
+
Description copied from class: LuaValue
+
Perform string comparison with another value + of any type + using string comparison based on byte values. +

+ Only strings can be compared, meaning + each operand must derive from LuaString. +

+

+
Overrides:
strcmp in class LuaValue
+
+
+
Parameters:
lhs - The right-hand-side value to perform the comparison with
+
+
+
+ +

+strcmp

+
+public int strcmp(LuaString rhs)
+
+
Description copied from class: LuaValue
+
Perform string comparison with another value + known to be a LuaString + using string comparison based on byte values. +

+ Only strings can be compared, meaning + each operand must derive from LuaString. +

+

+
Overrides:
strcmp in class LuaValue
+
+
+
Parameters:
rhs - The right-hand-side value to perform the comparison with
+
+
+
+ +

+checkint

+
+public int checkint()
+
+
Description copied from class: LuaValue
+
Check that the value is numeric, and convert and cast value to int, or throw LuaError if not numeric +

+ Values that are LuaNumber will be cast to int and may lose precision. + Values that are LuaString that can be converted to a number will be converted, + then cast to int, so may also lose precision. +

+

+
Overrides:
checkint in class LuaValue
+
+
+ +
Returns:
value cast to a int if numeric
See Also:
LuaValue.checkinteger(), +LuaValue.checklong(), +LuaValue.checkdouble(), +LuaValue.optint(int), +LuaValue.TNUMBER
+
+
+
+ +

+checkinteger

+
+public LuaInteger checkinteger()
+
+
Description copied from class: LuaValue
+
Check that the value is numeric, and convert and cast value to int, or throw LuaError if not numeric +

+ Values that are LuaNumber will be cast to int and may lose precision. + Values that are LuaString that can be converted to a number will be converted, + then cast to int, so may also lose precision. +

+

+
Overrides:
checkinteger in class LuaValue
+
+
+ +
Returns:
value cast to a int and wrapped in LuaInteger if numeric
See Also:
LuaValue.checkint(), +LuaValue.checklong(), +LuaValue.checkdouble(), +LuaValue.optinteger(LuaInteger), +LuaValue.TNUMBER
+
+
+
+ +

+checklong

+
+public long checklong()
+
+
Description copied from class: LuaValue
+
Check that the value is numeric, and convert and cast value to long, or throw LuaError if not numeric +

+ Values that are LuaNumber will be cast to long and may lose precision. + Values that are LuaString that can be converted to a number will be converted, + then cast to long, so may also lose precision. +

+

+
Overrides:
checklong in class LuaValue
+
+
+ +
Returns:
value cast to a long if numeric
See Also:
LuaValue.checkint(), +LuaValue.checkinteger(), +LuaValue.checkdouble(), +LuaValue.optlong(long), +LuaValue.TNUMBER
+
+
+
+ +

+checkdouble

+
+public double checkdouble()
+
+
Description copied from class: LuaValue
+
Check that the value is numeric and return the value as a double, + or throw LuaError if not numeric +

+ Values that are LuaNumber and values that are LuaString + that can be converted to a number will be converted to double. +

+

+
Overrides:
checkdouble in class LuaValue
+
+
+ +
Returns:
value cast to a double if numeric
See Also:
LuaValue.checkint(), +LuaValue.checkinteger(), +LuaValue.checklong(), +LuaValue.optdouble(double), +LuaValue.TNUMBER
+
+
+
+ +

+checknumber

+
+public LuaNumber checknumber()
+
+
Description copied from class: LuaValue
+
Check that the value is numeric, and return as a LuaNumber if so, or throw LuaError +

+ Values that are LuaString that can be converted to a number will be converted and returned. +

+

+
Overrides:
checknumber in class LuaValue
+
+
+ +
Returns:
value as a LuaNumber if numeric
See Also:
LuaValue.checkint(), +LuaValue.checkinteger(), +LuaValue.checkdouble(), +LuaValue.checklong(), +LuaValue.optnumber(LuaNumber), +LuaValue.TNUMBER
+
+
+
+ +

+checknumber

+
+public LuaNumber checknumber(java.lang.String msg)
+
+
Description copied from class: LuaValue
+
Check that the value is numeric, and return as a LuaNumber if so, or throw LuaError +

+ Values that are LuaString that can be converted to a number will be converted and returned. +

+

+
Overrides:
checknumber in class LuaValue
+
+
+
Parameters:
msg - String message to supply if conversion fails +
Returns:
value as a LuaNumber if numeric
See Also:
LuaValue.checkint(), +LuaValue.checkinteger(), +LuaValue.checkdouble(), +LuaValue.checklong(), +LuaValue.optnumber(LuaNumber), +LuaValue.TNUMBER
+
+
+
+ +

+tonumber

+
+public LuaValue tonumber()
+
+
Description copied from class: LuaValue
+
Conditionally convert to lua number without throwing errors. +

+ In lua all numbers are strings, but not all strings are numbers. + This function will return + the LuaValue this if it is a number + or a string convertible to a number, + and NIL for all other cases. +

+ This allows values to be tested for their "numeric-ness" without + the penalty of throwing exceptions, + nor the cost of converting the type and creating storage for it. +

+

+
Overrides:
tonumber in class LuaValue
+
+
+ +
Returns:
this if it is a LuaNumber + or LuaString that can be converted to a number, + otherwise LuaValue.NIL
See Also:
LuaValue.tostring(), +LuaValue.optnumber(LuaNumber), +LuaValue.checknumber(), +LuaValue.toint(), +LuaValue.todouble()
+
+
+
+ +

+isnumber

+
+public boolean isnumber()
+
+
Description copied from class: LuaValue
+
Check if this is a number +

+

+
Overrides:
isnumber in class LuaValue
+
+
+ +
Returns:
true if this is a number, + meaning derives from LuaNumber + or derives from LuaString and is convertible to a number, + otherwise false
See Also:
LuaValue.tonumber(), +LuaValue.checknumber(), +LuaValue.optnumber(LuaNumber), +LuaValue.TNUMBER
+
+
+
+ +

+isint

+
+public boolean isint()
+
+
Description copied from class: LuaValue
+
Check if this is a number and is representable by java int + without rounding or truncation +

+

+
Overrides:
isint in class LuaValue
+
+
+ +
Returns:
true if this is a number + meaning derives from LuaNumber + or derives from LuaString and is convertible to a number, + and can be represented by int, + otherwise false
See Also:
LuaValue.isinttype(), +LuaValue.islong(), +LuaValue.tonumber(), +LuaValue.checkint(), +LuaValue.optint(int), +LuaValue.TNUMBER
+
+
+
+ +

+islong

+
+public boolean islong()
+
+
Description copied from class: LuaValue
+
Check if this is a number and is representable by java long + without rounding or truncation +

+

+
Overrides:
islong in class LuaValue
+
+
+ +
Returns:
true if this is a number + meaning derives from LuaNumber + or derives from LuaString and is convertible to a number, + and can be represented by long, + otherwise false
See Also:
LuaValue.tonumber(), +LuaValue.checklong(), +LuaValue.optlong(long), +LuaValue.TNUMBER
+
+
+
+ +

+tobyte

+
+public byte tobyte()
+
+
Description copied from class: LuaValue
+
Convert to byte if numeric, or 0 if not. +

+

+
Overrides:
tobyte in class LuaValue
+
+
+ +
Returns:
Value cast to byte if number or string convertible to number, otherwise 0
See Also:
LuaValue.toint(), +LuaValue.todouble(), +#optbyte(byte), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+tochar

+
+public char tochar()
+
+
Description copied from class: LuaValue
+
Convert to char if numeric, or 0 if not. +

+

+
Overrides:
tochar in class LuaValue
+
+
+ +
Returns:
Value cast to char if number or string convertible to number, otherwise 0
See Also:
LuaValue.toint(), +LuaValue.todouble(), +#optchar(char), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+todouble

+
+public double todouble()
+
+
Description copied from class: LuaValue
+
Convert to double if numeric, or 0 if not. +

+

+
Overrides:
todouble in class LuaValue
+
+
+ +
Returns:
Value cast to double if number or string convertible to number, otherwise 0
See Also:
LuaValue.toint(), +LuaValue.tobyte(), +LuaValue.tochar(), +LuaValue.toshort(), +LuaValue.tolong(), +LuaValue.tofloat(), +LuaValue.optdouble(double), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+tofloat

+
+public float tofloat()
+
+
Description copied from class: LuaValue
+
Convert to float if numeric, or 0 if not. +

+

+
Overrides:
tofloat in class LuaValue
+
+
+ +
Returns:
Value cast to float if number or string convertible to number, otherwise 0
See Also:
LuaValue.toint(), +LuaValue.todouble(), +#optfloat(float), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+toint

+
+public int toint()
+
+
Description copied from class: LuaValue
+
Convert to int if numeric, or 0 if not. +

+

+
Overrides:
toint in class LuaValue
+
+
+ +
Returns:
Value cast to int if number or string convertible to number, otherwise 0
See Also:
LuaValue.tobyte(), +LuaValue.tochar(), +LuaValue.toshort(), +LuaValue.tolong(), +LuaValue.tofloat(), +LuaValue.todouble(), +LuaValue.optint(int), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+tolong

+
+public long tolong()
+
+
Description copied from class: LuaValue
+
Convert to long if numeric, or 0 if not. +

+

+
Overrides:
tolong in class LuaValue
+
+
+ +
Returns:
Value cast to long if number or string convertible to number, otherwise 0
See Also:
LuaValue.isint(), +LuaValue.isinttype(), +LuaValue.toint(), +LuaValue.todouble(), +LuaValue.optlong(long), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+toshort

+
+public short toshort()
+
+
Description copied from class: LuaValue
+
Convert to short if numeric, or 0 if not. +

+

+
Overrides:
toshort in class LuaValue
+
+
+ +
Returns:
Value cast to short if number or string convertible to number, otherwise 0
See Also:
LuaValue.toint(), +LuaValue.todouble(), +#optshort(short), +LuaValue.checknumber(), +LuaValue.isnumber(), +TNUMBER
+
+
+
+ +

+optdouble

+
+public double optdouble(double defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a number or string convertible to number and return as double +

+

+
Overrides:
optdouble in class LuaValue
+
+
+
Parameters:
defval - double to return if this is nil or none +
Returns:
this cast to double if numeric, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.optint(int), +LuaValue.optinteger(LuaInteger), +LuaValue.checkdouble(), +LuaValue.todouble(), +LuaValue.tonumber(), +LuaValue.isnumber(), +LuaValue.TNUMBER
+
+
+
+ +

+optint

+
+public int optint(int defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a number or string convertible to number and return as int +

+

+
Overrides:
optint in class LuaValue
+
+
+
Parameters:
defval - int to return if this is nil or none +
Returns:
this cast to int if numeric, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.optdouble(double), +LuaValue.optlong(long), +LuaValue.optinteger(LuaInteger), +LuaValue.checkint(), +LuaValue.toint(), +LuaValue.tonumber(), +LuaValue.isnumber(), +LuaValue.TNUMBER
+
+
+
+ +

+optinteger

+
+public LuaInteger optinteger(LuaInteger defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a number or string convertible to number and return as LuaInteger +

+

+
Overrides:
optinteger in class LuaValue
+
+
+
Parameters:
defval - LuaInteger to return if this is nil or none +
Returns:
this converted and wrapped in LuaInteger if numeric, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.optdouble(double), +LuaValue.optint(int), +LuaValue.checkint(), +LuaValue.toint(), +LuaValue.tonumber(), +LuaValue.isnumber(), +LuaValue.TNUMBER
+
+
+
+ +

+optlong

+
+public long optlong(long defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a number or string convertible to number and return as long +

+

+
Overrides:
optlong in class LuaValue
+
+
+
Parameters:
defval - long to return if this is nil or none +
Returns:
this cast to long if numeric, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.optdouble(double), +LuaValue.optint(int), +LuaValue.checkint(), +LuaValue.toint(), +LuaValue.tonumber(), +LuaValue.isnumber(), +LuaValue.TNUMBER
+
+
+
+ +

+optnumber

+
+public LuaNumber optnumber(LuaNumber defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a number or string convertible to number and return as LuaNumber +

+

+
Overrides:
optnumber in class LuaValue
+
+
+
Parameters:
defval - LuaNumber to return if this is nil or none +
Returns:
this cast to LuaNumber if numeric, + defval if nil or none, + throws LuaError otherwise
See Also:
LuaValue.optdouble(double), +LuaValue.optlong(long), +LuaValue.optint(int), +LuaValue.checkint(), +LuaValue.toint(), +LuaValue.tonumber(), +LuaValue.isnumber(), +LuaValue.TNUMBER
+
+
+
+ +

+optstring

+
+public LuaString optstring(LuaString defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a string or number and return as LuaString +

+

+
Overrides:
optstring in class LuaValue
+
+
+
Parameters:
defval - LuaString to return if this is nil or none +
Returns:
this converted to LuaString if a string or number, + defval if nil or none, + throws LuaError if some other type
See Also:
LuaValue.tojstring(), +LuaValue.optjstring(String), +LuaValue.checkstring(), +LuaValue.toString(), +LuaValue.TSTRING
+
+
+
+ +

+tostring

+
+public LuaValue tostring()
+
+
Description copied from class: LuaValue
+
Conditionally convert to lua string without throwing errors. +

+ In lua all numbers are strings, so this function will return + the LuaValue this if it is a string or number, + and NIL for all other cases. +

+ This allows values to be tested for their "string-ness" without + the penalty of throwing exceptions. +

+

+
Overrides:
tostring in class LuaValue
+
+
+ +
Returns:
this if it is a LuaString or LuaNumber, + otherwise NIL
See Also:
LuaValue.tonumber(), +LuaValue.tojstring(), +LuaValue.optstring(LuaString), +LuaValue.checkstring(), +LuaValue.toString()
+
+
+
+ +

+optjstring

+
+public java.lang.String optjstring(java.lang.String defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a string or number and return as Java String +

+

+
Overrides:
optjstring in class LuaValue
+
+
+
Parameters:
defval - LuaString to return if this is nil or none +
Returns:
this converted to String if a string or number, + defval if nil or none, + throws LuaError if some other type
See Also:
LuaValue.tojstring(), +LuaValue.optstring(LuaString), +LuaValue.checkjstring(), +LuaValue.toString(), +LuaValue.TSTRING
+
+
+
+ +

+strvalue

+
+public LuaString strvalue()
+
+
Description copied from class: LuaValue
+
Convert this value to a string if it is a LuaString or LuaNumber, + or throw a LuaError if it is not +

+

+
Overrides:
strvalue in class LuaValue
+
+
+ +
Returns:
LuaString corresponding to the value if a string or number
+
+
+
+ +

+substring

+
+public LuaString substring(int beginIndex,
+                           int endIndex)
+
+
+
+
+
+
+ +

+hashCode

+
+public int hashCode()
+
+
+
Overrides:
hashCode in class java.lang.Object
+
+
+
+
+
+
+ +

+equals

+
+public boolean equals(java.lang.Object o)
+
+
+
Overrides:
equals in class LuaValue
+
+
+
+
+
+
+ +

+eq

+
+public LuaValue eq(LuaValue val)
+
+
Description copied from class: LuaValue
+
Equals: Perform equality comparison with another value + including metatag processing using EQ. +

+

+
Overrides:
eq in class LuaValue
+
+
+
Parameters:
val - The value to compare with. +
Returns:
TRUE if values are comparable and (this == rhs), + FALSE if comparable but not equal, + LuaValue if metatag processing occurs.
See Also:
LuaValue.eq_b(LuaValue), +LuaValue.raweq(LuaValue), +LuaValue.neq(LuaValue), +LuaValue.eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue), +LuaValue.EQ
+
+
+
+ +

+eq_b

+
+public boolean eq_b(LuaValue val)
+
+
Description copied from class: LuaValue
+
Equals: Perform equality comparison with another value + including metatag processing using EQ, + and return java boolean +

+

+
Overrides:
eq_b in class LuaValue
+
+
+
Parameters:
val - The value to compare with. +
Returns:
true if values are comparable and (this == rhs), + false if comparable but not equal, + result converted to java boolean if metatag processing occurs.
See Also:
LuaValue.eq(LuaValue), +LuaValue.raweq(LuaValue), +LuaValue.neq_b(LuaValue), +LuaValue.eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue), +LuaValue.EQ
+
+
+
+ +

+raweq

+
+public boolean raweq(LuaValue val)
+
+
Description copied from class: LuaValue
+
Equals: Perform direct equality comparison with another value + without metatag processing. +

+

+
Overrides:
raweq in class LuaValue
+
+
+
Parameters:
val - The value to compare with. +
Returns:
true if (this == rhs), false otherwise
See Also:
LuaValue.eq(LuaValue), +LuaValue.raweq(LuaUserdata), +LuaValue.raweq(LuaString), +LuaValue.raweq(double), +LuaValue.raweq(int), +LuaValue.EQ
+
+
+
+ +

+raweq

+
+public boolean raweq(LuaString s)
+
+
Description copied from class: LuaValue
+
Equals: Perform direct equality comparison with a LuaString value + without metatag processing. +

+

+
Overrides:
raweq in class LuaValue
+
+
+
Parameters:
s - The LuaString to compare with. +
Returns:
true if this is a LuaString + and their byte sequences match, + otherwise false
+
+
+
+ +

+equals

+
+public static boolean equals(LuaString a,
+                             int i,
+                             LuaString b,
+                             int j,
+                             int n)
+
+
+
+
+
+
+ +

+equals

+
+public static boolean equals(byte[] a,
+                             int i,
+                             byte[] b,
+                             int j,
+                             int n)
+
+
+
+
+
+
+ +

+write

+
+public void write(java.io.DataOutputStream writer,
+                  int i,
+                  int len)
+           throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+len

+
+public LuaValue len()
+
+
Description copied from class: LuaValue
+
Length operator: return lua length of object (#this) including metatag processing as java int +

+

+
Overrides:
len in class LuaValue
+
+
+ +
Returns:
length as defined by the lua # operator + or metatag processing result
+
+
+
+ +

+length

+
+public int length()
+
+
Description copied from class: LuaValue
+
Length operator: return lua length of object (#this) including metatag processing as java int +

+

+
Overrides:
length in class LuaValue
+
+
+ +
Returns:
length as defined by the lua # operator + or metatag processing result converted to java int using LuaValue.toint()
+
+
+
+ +

+luaByte

+
+public int luaByte(int index)
+
+
+
+
+
+
+ +

+charAt

+
+public int charAt(int index)
+
+
+
+
+
+
+ +

+checkjstring

+
+public java.lang.String checkjstring()
+
+
Description copied from class: LuaValue
+
Convert this value to a Java String. +

+ The string representations here will roughly match what is produced by the + C lua distribution, however hash codes have no relationship, + and there may be differences in number formatting. +

+

+
Overrides:
checkjstring in class LuaValue
+
+
+ +
Returns:
String representation of the value
See Also:
LuaValue.checkstring(), +LuaValue.optjstring(String), +LuaValue.tojstring(), +LuaValue.isstring(), +LuaValue.TSTRING
+
+
+
+ +

+checkstring

+
+public LuaString checkstring()
+
+
Description copied from class: LuaValue
+
Check that this is a lua string, or throw LuaError if it is not. +

+ In lua all numbers are strings, so this will succeed for + anything that derives from LuaString or LuaNumber. + Numbers will be converted to LuaString. +

+

+
Overrides:
checkstring in class LuaValue
+
+
+ +
Returns:
LuaString representation of the value if it is a LuaString or LuaNumber
See Also:
LuaValue.checkjstring(), +LuaValue.optstring(LuaString), +LuaValue.tostring(), +LuaValue.isstring(), +LuaValue.TSTRING
+
+
+
+ +

+toInputStream

+
+public java.io.InputStream toInputStream()
+
+
Convert value to an input stream. +

+

+ +
Returns:
InputStream whose data matches the bytes in this LuaString
+
+
+
+ +

+copyInto

+
+public void copyInto(int strOffset,
+                     byte[] bytes,
+                     int arrayOffset,
+                     int len)
+
+
Copy the bytes of the string into the given byte array. +

+

+
Parameters:
strOffset - offset from which to copy
bytes - destination byte array
arrayOffset - offset in destination
len - number of bytes to copy
+
+
+
+ +

+indexOfAny

+
+public int indexOfAny(LuaString accept)
+
+
Java version of strpbrk - find index of any byte that in an accept string. +

+

+
Parameters:
accept - LuaString containing characters to look for. +
Returns:
index of first match in the accept string, or -1 if not found.
+
+
+
+ +

+indexOf

+
+public int indexOf(byte b,
+                   int start)
+
+
Find the index of a byte starting at a point in this string +

+

+
Parameters:
b - the byte to look for
start - the first index in the string +
Returns:
index of first match found, or -1 if not found.
+
+
+
+ +

+indexOf

+
+public int indexOf(LuaString s,
+                   int start)
+
+
Find the index of a string starting at a point in this string +

+

+
Parameters:
s - the string to search for
start - the first index in the string +
Returns:
index of first match found, or -1 if not found.
+
+
+
+ +

+lastIndexOf

+
+public int lastIndexOf(LuaString s)
+
+
Find the last index of a string in this string +

+

+
Parameters:
s - the string to search for +
Returns:
index of last match found, or -1 if not found.
+
+
+
+ +

+decodeAsUtf8

+
+public static java.lang.String decodeAsUtf8(byte[] bytes,
+                                            int offset,
+                                            int length)
+
+
Convert to Java String interpreting as utf8 characters. +

+

+
Parameters:
bytes - byte array in UTF8 encoding to convert
offset - starting index in byte array
length - number of bytes to convert +
Returns:
Java String corresponding to the value of bytes interpreted using UTF8
See Also:
lengthAsUtf8(char[]), +encodeToUtf8(char[], byte[], int), +isValidUtf8()
+
+
+
+ +

+lengthAsUtf8

+
+public static int lengthAsUtf8(char[] chars)
+
+
Count the number of bytes required to encode the string as UTF-8. +

+

+
Parameters:
chars - Array of unicode characters to be encoded as UTF-8 +
Returns:
count of bytes needed to encode using UTF-8
See Also:
encodeToUtf8(char[], byte[], int), +decodeAsUtf8(byte[], int, int), +isValidUtf8()
+
+
+
+ +

+encodeToUtf8

+
+public static void encodeToUtf8(char[] chars,
+                                byte[] bytes,
+                                int off)
+
+
Encode the given Java string as UTF-8 bytes, writing the result to bytes + starting at offset. +

+ The string should be measured first with lengthAsUtf8 + to make sure the given byte array is large enough. +

+

+
Parameters:
chars - Array of unicode characters to be encoded as UTF-8
bytes - byte array to hold the result
off - offset into the byte array to start writing
See Also:
lengthAsUtf8(char[]), +decodeAsUtf8(byte[], int, int), +isValidUtf8()
+
+
+
+ +

+isValidUtf8

+
+public boolean isValidUtf8()
+
+
Check that a byte sequence is valid UTF-8 +

+

+ +
Returns:
true if it is valid UTF-8, otherwise false
See Also:
lengthAsUtf8(char[]), +encodeToUtf8(char[], byte[], int), +decodeAsUtf8(byte[], int, int)
+
+
+
+ +

+tonumber

+
+public LuaValue tonumber(int base)
+
+
convert to a number using a supplied base, or NIL if it can't be converted +

+

+
Parameters:
base - the base to use, such as 10 +
Returns:
IntValue, DoubleValue, or NIL depending on the content of the string.
See Also:
LuaValue.tonumber()
+
+
+
+ +

+scannumber

+
+public double scannumber(int base)
+
+
Convert to a number in a base, or return Double.NaN if not a number. +

+

+
Parameters:
base - the base to use, such as 10 +
Returns:
double value if conversion is valid, or Double.NaN if not
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/LuaTable.html b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaTable.html new file mode 100644 index 0000000000..6b635b20fc --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaTable.html @@ -0,0 +1,1563 @@ + + + + + + +LuaTable (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class LuaTable

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaTable
+
+
+
Direct Known Subclasses:
WeakTable
+
+
+
+
public class LuaTable
extends LuaValue
+ + +

+Subclass of LuaValue for representing lua tables. +

+ Almost all API's implemented in LuaTable are defined and documented in LuaValue. +

+ If a table is needed, the one of the type-checking functions can be used such as + istable(), + checktable(), or + opttable(LuaTable) +

+ The main table operations are defined on LuaValue + for getting and setting values with and without metatag processing: +

+

+ To iterate over key-value pairs from Java, use +

 LuaValue k = LuaValue.NIL;
+ while ( true ) {
+    Varargs n = table.next(k);
+    if ( (k = n.arg1()).isnil() )
+       break;
+    LuaValue v = n.arg(2)
+    process( k, v )
+ }
+ +

+ As with other types, LuaTable instances should be constructed via one of the table constructor + methods on LuaValue: +

+

+ +

+

+
See Also:
LuaValue
+
+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Field Summary
+protected  LuaValue[]array + +
+          the array values
+protected  inthashEntries + +
+          the number of hash entries
+protected  LuaValue[]hashKeys + +
+          the hash keys
+protected  LuaValue[]hashValues + +
+          the hash values
+protected  LuaValuem_metatable + +
+          metatable for this table, or null
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + + + + + + + + + + + + + +
+Constructor Summary
LuaTable() + +
+          Construct empty table
LuaTable(int narray, + int nhash) + +
+          Construct table with preset capacity.
LuaTable(LuaValue[] named, + LuaValue[] unnamed, + Varargs lastarg) + +
+          Construct table with named and unnamed parts.
LuaTable(Varargs varargs) + +
+          Construct table of unnamed elements.
LuaTable(Varargs varargs, + int firstarg) + +
+          Construct table of unnamed elements.
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+protected  LuaTablechangemode(boolean weakkeys, + boolean weakvalues) + +
+          Change the mode of a table
+ LuaTablechecktable() + +
+          Check that this is a LuaTable, or throw LuaError if it is not
+ LuaValueconcat(LuaString sep, + int i, + int j) + +
+          Concatenate the contents of a table efficiently, using Buffer
+ booleaneq_b(LuaValue val) + +
+          Equals: Perform equality comparison with another value + including metatag processing using EQ, + and return java boolean
+ LuaValueeq(LuaValue val) + +
+          Equals: Perform equality comparison with another value + including metatag processing using EQ.
+ LuaValueforeach(LuaValue func) + +
+          Call the supplied function once for each key-value pair
+ LuaValueforeachi(LuaValue func) + +
+          Call the supplied function once for each key-value pair + in the contiguous array part
+ LuaValueget(int key) + +
+          Get a value in a table including metatag processing using INDEX.
+ LuaValueget(LuaValue key) + +
+          Get a value in a table including metatag processing using INDEX.
+protected  intgetArrayLength() + +
+          Get the length of the array part of the table.
+protected  intgetHashLength() + +
+          Get the length of the hash part of the table.
+ LuaValuegetmetatable() + +
+          Get the metatable for this LuaValue
+ LuaValuegetn() + +
+          Implementation of lua 5.0 getn() function.
+protected  voidhashClearSlot(int i) + +
+          Clear a particular slot in the table
+ inthashFindSlot(LuaValue key) + +
+          Find the hashtable slot to use
+protected  LuaValuehashget(LuaValue key) + +
+           
+ voidhashset(LuaValue key, + LuaValue value) + +
+          Set a hashtable value
+ Varargsinext(LuaValue key) + +
+          Get the next element after a particular key in the + contiguous array part of a table
+ voidinsert(int pos, + LuaValue value) + +
+          Insert an element at a position in a list-table
+ booleanistable() + +
+          Check if this is a table
+ intkeyCount() + +
+          This may be deprecated in a future release.
+ LuaValue[]keys() + +
+          This may be deprecated in a future release.
+ LuaValuelen() + +
+          Length operator: return lua length of object (#this) including metatag processing as java int
+ intlength() + +
+          Length operator: return lua length of object (#this) including metatag processing as java int
+ intmaxn() + +
+          Return table.maxn() as defined by lua 5.0.
+ Varargsnext(LuaValue key) + +
+          Get the next element after a particular key in the table
+ LuaTableopttable(LuaTable defval) + +
+          Check that optional argument is a table and return as LuaTable
+ voidpresize(int narray) + +
+          Preallocate the array part of a table to be a certain size,
+ voidpresize(int narray, + int nhash) + +
+           
+ LuaValuerawget(int key) + +
+          Get a value in a table without metatag processing.
+ LuaValuerawget(LuaValue key) + +
+          Get a value in a table without metatag processing.
+ voidrawset(int key, + LuaValue value) + +
+          Set a value in a table without metatag processing.
+ voidrawset(LuaValue key, + LuaValue value) + +
+          caller must ensure key is not nil
+ LuaValueremove(int pos) + +
+          Remove the element at a position in a list-table
+ voidset(int key, + LuaValue value) + +
+          Set a value in a table without metatag processing using NEWINDEX.
+ voidset(LuaValue key, + LuaValue value) + +
+          caller must ensure key is not nil
+ LuaValuesetmetatable(LuaValue metatable) + +
+          Set the metatable for this LuaValue
+ voidsort(LuaValue comparator) + +
+          Sort the table using a comparator.
+ inttype() + +
+          Get the enumeration value for the type of this value.
+ java.lang.Stringtypename() + +
+          Get the String name of the type of this value.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, call, call, call, call, callmt, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eqmtcall, equals, error, get, getfenv, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, invoke, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isfunction, isint, isinttype, islong, isnil, isnumber, isstring, isthread, isuserdata, isuserdata, isweaknil, lenerror, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, not, onInvoke, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, raweq, raweq, raweq, raweq, raweq, rawget, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, setfenv, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+array

+
+protected LuaValue[] array
+
+
the array values +

+

+
+
+
+ +

+hashKeys

+
+protected LuaValue[] hashKeys
+
+
the hash keys +

+

+
+
+
+ +

+hashValues

+
+protected LuaValue[] hashValues
+
+
the hash values +

+

+
+
+
+ +

+hashEntries

+
+protected int hashEntries
+
+
the number of hash entries +

+

+
+
+
+ +

+m_metatable

+
+protected LuaValue m_metatable
+
+
metatable for this table, or null +

+

+
+
+ + + + + + + + +
+Constructor Detail
+ +

+LuaTable

+
+public LuaTable()
+
+
Construct empty table +

+

+
+ +

+LuaTable

+
+public LuaTable(int narray,
+                int nhash)
+
+
Construct table with preset capacity. +

+

+
Parameters:
narray - capacity of array part
nhash - capacity of hash part
+
+
+ +

+LuaTable

+
+public LuaTable(LuaValue[] named,
+                LuaValue[] unnamed,
+                Varargs lastarg)
+
+
Construct table with named and unnamed parts. +

+

+
Parameters:
named - Named elements in order key-a, value-a, key-b, value-b, ...
unnamed - Unnamed elements in order value-1, value-2, ...
lastarg - Additional unnamed values beyond unnamed.length
+
+
+ +

+LuaTable

+
+public LuaTable(Varargs varargs)
+
+
Construct table of unnamed elements. +

+

+
Parameters:
varargs - Unnamed elements in order value-1, value-2, ...
+
+
+ +

+LuaTable

+
+public LuaTable(Varargs varargs,
+                int firstarg)
+
+
Construct table of unnamed elements. +

+

+
Parameters:
varargs - Unnamed elements in order value-1, value-2, ...
firstarg - the index in varargs of the first argument to include in the table
+
+ + + + + + + + +
+Method Detail
+ +

+type

+
+public int type()
+
+
Description copied from class: LuaValue
+
Get the enumeration value for the type of this value. +

+

+
Specified by:
type in class LuaValue
+
+
+ +
Returns:
value for this type, one of + TNIL, + TBOOLEAN, + TNUMBER, + TSTRING, + TTABLE, + TFUNCTION, + TUSERDATA, + TTHREAD
See Also:
LuaValue.typename()
+
+
+
+ +

+typename

+
+public java.lang.String typename()
+
+
Description copied from class: LuaValue
+
Get the String name of the type of this value. +

+

+

+
Specified by:
typename in class LuaValue
+
+
+ +
Returns:
name from type name list LuaValue.TYPE_NAMES + corresponding to the type of this value: + "nil", "boolean", "number", "string", + "table", "function", "userdata", "thread"
See Also:
LuaValue.type()
+
+
+
+ +

+istable

+
+public boolean istable()
+
+
Description copied from class: LuaValue
+
Check if this is a table +

+

+
Overrides:
istable in class LuaValue
+
+
+ +
Returns:
true if this is a table, otherwise false
See Also:
LuaValue.checktable(), +LuaValue.opttable(LuaTable), +LuaValue.TTABLE
+
+
+
+ +

+checktable

+
+public LuaTable checktable()
+
+
Description copied from class: LuaValue
+
Check that this is a LuaTable, or throw LuaError if it is not +

+

+
Overrides:
checktable in class LuaValue
+
+
+ +
Returns:
this if it is a LuaTable
See Also:
LuaValue.istable(), +LuaValue.opttable(LuaTable), +LuaValue.TTABLE
+
+
+
+ +

+opttable

+
+public LuaTable opttable(LuaTable defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a table and return as LuaTable +

+

+
Overrides:
opttable in class LuaValue
+
+
+
Parameters:
defval - LuaTable to return if this is nil or none +
Returns:
this cast to LuaTable if a table, + defval if nil or none, + throws LuaError if some other type
See Also:
LuaValue.checktable(), +LuaValue.istable(), +LuaValue.TTABLE
+
+
+
+ +

+presize

+
+public void presize(int narray)
+
+
Description copied from class: LuaValue
+
Preallocate the array part of a table to be a certain size, +

+ Primarily used internally in response to a SETLIST bytecode. +

+

+
Overrides:
presize in class LuaValue
+
+
+
Parameters:
narray - the number of array slots to preallocate in the table.
+
+
+
+ +

+presize

+
+public void presize(int narray,
+                    int nhash)
+
+
+
+
+
+
+ +

+getArrayLength

+
+protected int getArrayLength()
+
+
Get the length of the array part of the table. +

+

+ +
Returns:
length of the array part, does not relate to count of objects in the table.
+
+
+
+ +

+getHashLength

+
+protected int getHashLength()
+
+
Get the length of the hash part of the table. +

+

+ +
Returns:
length of the hash part, does not relate to count of objects in the table.
+
+
+
+ +

+getmetatable

+
+public LuaValue getmetatable()
+
+
Description copied from class: LuaValue
+
Get the metatable for this LuaValue +

+ For LuaTable and LuaUserdata instances, + the metatable returned is this instance metatable. + For all other types, the class metatable value will be returned. +

+

+
Overrides:
getmetatable in class LuaValue
+
+
+ +
Returns:
metatable, or null if it there is none
See Also:
LuaBoolean.s_metatable, +LuaNumber.s_metatable, +LuaNil.s_metatable, +LuaFunction.s_metatable, +LuaThread.s_metatable
+
+
+
+ +

+setmetatable

+
+public LuaValue setmetatable(LuaValue metatable)
+
+
Description copied from class: LuaValue
+
Set the metatable for this LuaValue +

+ For LuaTable and LuaUserdata instances, the metatable is per instance. + For all other types, there is one metatable per type that can be set directly from java +

+

+
Overrides:
setmetatable in class LuaValue
+
+
+
Parameters:
metatable - LuaValue instance to serve as the metatable, or null to reset it. +
Returns:
this to allow chaining of Java function calls
See Also:
LuaBoolean.s_metatable, +LuaNumber.s_metatable, +LuaNil.s_metatable, +LuaFunction.s_metatable, +LuaThread.s_metatable
+
+
+
+ +

+changemode

+
+protected LuaTable changemode(boolean weakkeys,
+                              boolean weakvalues)
+
+
Change the mode of a table +

+

+
Parameters:
weakkeys - true to make the table have weak keys going forward
weakvalues - true to make the table have weak values going forward +
Returns:
this or a new WeakTable if the mode change requires copying.
+
+
+
+ +

+get

+
+public LuaValue get(int key)
+
+
Description copied from class: LuaValue
+
Get a value in a table including metatag processing using INDEX. +

+

+
Overrides:
get in class LuaValue
+
+
+
Parameters:
key - the key to look up +
Returns:
LuaValue for that key, or NIL if not found
See Also:
LuaValue.get(LuaValue), +LuaValue.rawget(int)
+
+
+
+ +

+get

+
+public LuaValue get(LuaValue key)
+
+
Description copied from class: LuaValue
+
Get a value in a table including metatag processing using INDEX. +

+

+
Overrides:
get in class LuaValue
+
+
+
Parameters:
key - the key to look up, must not be NIL or null +
Returns:
LuaValue for that key, or NIL if not found and no metatag
See Also:
LuaValue.get(int), +LuaValue.get(String), +LuaValue.rawget(LuaValue)
+
+
+
+ +

+rawget

+
+public LuaValue rawget(int key)
+
+
Description copied from class: LuaValue
+
Get a value in a table without metatag processing. +

+

+
Overrides:
rawget in class LuaValue
+
+
+
Parameters:
key - the key to look up +
Returns:
LuaValue for that key, or NIL if not found
+
+
+
+ +

+rawget

+
+public LuaValue rawget(LuaValue key)
+
+
Description copied from class: LuaValue
+
Get a value in a table without metatag processing. +

+

+
Overrides:
rawget in class LuaValue
+
+
+
Parameters:
key - the key to look up, must not be NIL or null +
Returns:
LuaValue for that key, or NIL if not found
+
+
+
+ +

+hashget

+
+protected LuaValue hashget(LuaValue key)
+
+
+
+
+
+
+ +

+set

+
+public void set(int key,
+                LuaValue value)
+
+
Description copied from class: LuaValue
+
Set a value in a table without metatag processing using NEWINDEX. +

+

+
Overrides:
set in class LuaValue
+
+
+
Parameters:
key - the key to use
value - the value to use, can be NIL, must not be null
+
+
+
+ +

+set

+
+public void set(LuaValue key,
+                LuaValue value)
+
+
caller must ensure key is not nil +

+

+
Overrides:
set in class LuaValue
+
+
+
Parameters:
key - the key to use, must not be NIL or null
value - the value to use, can be NIL, must not be null
+
+
+
+ +

+rawset

+
+public void rawset(int key,
+                   LuaValue value)
+
+
Description copied from class: LuaValue
+
Set a value in a table without metatag processing. +

+

+
Overrides:
rawset in class LuaValue
+
+
+
Parameters:
key - the key to use
value - the value to use, can be NIL, must not be null
+
+
+
+ +

+rawset

+
+public void rawset(LuaValue key,
+                   LuaValue value)
+
+
caller must ensure key is not nil +

+

+
Overrides:
rawset in class LuaValue
+
+
+
Parameters:
key - the key to use, must not be NIL or null
value - the value to use, can be NIL, must not be null
+
+
+
+ +

+remove

+
+public LuaValue remove(int pos)
+
+
Remove the element at a position in a list-table +

+

+
Parameters:
pos - the position to remove +
Returns:
The removed item, or LuaValue.NONE if not removed
+
+
+
+ +

+insert

+
+public void insert(int pos,
+                   LuaValue value)
+
+
Insert an element at a position in a list-table +

+

+
Parameters:
pos - the position to remove
value - The value to insert
+
+
+
+ +

+concat

+
+public LuaValue concat(LuaString sep,
+                       int i,
+                       int j)
+
+
Concatenate the contents of a table efficiently, using Buffer +

+

+
Parameters:
sep - LuaString separater to apply between elements
i - the first element index
j - the last element index, inclusive +
Returns:
LuaString value of the concatenation
+
+
+
+ +

+getn

+
+public LuaValue getn()
+
+
Description copied from class: LuaValue
+
Implementation of lua 5.0 getn() function. +

+

+
Overrides:
getn in class LuaValue
+
+
+ +
Returns:
value of getn() as defined in lua 5.0 spec if this is a LuaTable
+
+
+
+ +

+length

+
+public int length()
+
+
Description copied from class: LuaValue
+
Length operator: return lua length of object (#this) including metatag processing as java int +

+

+
Overrides:
length in class LuaValue
+
+
+ +
Returns:
length as defined by the lua # operator + or metatag processing result converted to java int using LuaValue.toint()
+
+
+
+ +

+len

+
+public LuaValue len()
+
+
Description copied from class: LuaValue
+
Length operator: return lua length of object (#this) including metatag processing as java int +

+

+
Overrides:
len in class LuaValue
+
+
+ +
Returns:
length as defined by the lua # operator + or metatag processing result
+
+
+
+ +

+maxn

+
+public int maxn()
+
+
Return table.maxn() as defined by lua 5.0. +

+ Provided for compatibility, not a scalable operation. +

+

+ +
Returns:
value for maxn
+
+
+
+ +

+next

+
+public Varargs next(LuaValue key)
+
+
Get the next element after a particular key in the table +

+

+
Overrides:
next in class LuaValue
+
+
+
Parameters:
key - LuaInteger value identifying a key to start from, + or NIL to start at the beginning +
Returns:
key,value or nil
See Also:
LuaTable, +#inext(), +LuaValue.valueOf(int), +Varargs.arg1(), +Varargs.arg(int), +LuaValue.isnil()
+
+
+
+ +

+inext

+
+public Varargs inext(LuaValue key)
+
+
Get the next element after a particular key in the + contiguous array part of a table +

+

+
Overrides:
inext in class LuaValue
+
+
+
Parameters:
key - LuaInteger value identifying a key to start from, + or NIL to start at the beginning +
Returns:
key,value or none
See Also:
LuaTable, +#next(), +LuaValue.valueOf(int), +Varargs.arg1(), +Varargs.arg(int), +LuaValue.isnil()
+
+
+
+ +

+foreach

+
+public LuaValue foreach(LuaValue func)
+
+
Call the supplied function once for each key-value pair +

+

+
Parameters:
func - function to call
+
+
+
+ +

+foreachi

+
+public LuaValue foreachi(LuaValue func)
+
+
Call the supplied function once for each key-value pair + in the contiguous array part +

+

+
Parameters:
func -
+
+
+
+ +

+hashset

+
+public void hashset(LuaValue key,
+                    LuaValue value)
+
+
Set a hashtable value +

+

+
Parameters:
key - key to set
value - value to set
+
+
+
+ +

+hashFindSlot

+
+public int hashFindSlot(LuaValue key)
+
+
Find the hashtable slot to use +

+

+
Parameters:
key - key to look for +
Returns:
slot to use
+
+
+
+ +

+hashClearSlot

+
+protected void hashClearSlot(int i)
+
+
Clear a particular slot in the table +

+

+
Parameters:
i - slot to clear.
+
+
+
+ +

+sort

+
+public void sort(LuaValue comparator)
+
+
Sort the table using a comparator. +

+

+
Parameters:
comparator - LuaValue to be called to compare elements.
+
+
+
+ +

+keyCount

+
+public int keyCount()
+
+
This may be deprecated in a future release. + It is recommended to count via iteration over next() instead +

+

+ +
Returns:
count of keys in the table
+
+
+
+ +

+keys

+
+public LuaValue[] keys()
+
+
This may be deprecated in a future release. + It is recommended to use next() instead +

+

+ +
Returns:
array of keys in the table
+
+
+
+ +

+eq

+
+public LuaValue eq(LuaValue val)
+
+
Description copied from class: LuaValue
+
Equals: Perform equality comparison with another value + including metatag processing using EQ. +

+

+
Overrides:
eq in class LuaValue
+
+
+
Parameters:
val - The value to compare with. +
Returns:
TRUE if values are comparable and (this == rhs), + FALSE if comparable but not equal, + LuaValue if metatag processing occurs.
See Also:
LuaValue.eq_b(LuaValue), +LuaValue.raweq(LuaValue), +LuaValue.neq(LuaValue), +LuaValue.eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue), +LuaValue.EQ
+
+
+
+ +

+eq_b

+
+public boolean eq_b(LuaValue val)
+
+
Description copied from class: LuaValue
+
Equals: Perform equality comparison with another value + including metatag processing using EQ, + and return java boolean +

+

+
Overrides:
eq_b in class LuaValue
+
+
+
Parameters:
val - The value to compare with. +
Returns:
true if values are comparable and (this == rhs), + false if comparable but not equal, + result converted to java boolean if metatag processing occurs.
See Also:
LuaValue.eq(LuaValue), +LuaValue.raweq(LuaValue), +LuaValue.neq_b(LuaValue), +LuaValue.eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue), +LuaValue.EQ
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/LuaThread.CallStack.html b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaThread.CallStack.html new file mode 100644 index 0000000000..54d529b15b --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaThread.CallStack.html @@ -0,0 +1,279 @@ + + + + + + +LuaThread.CallStack (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class LuaThread.CallStack

+
+java.lang.Object
+  extended by org.luaj.vm2.LuaThread.CallStack
+
+
+
Enclosing class:
LuaThread
+
+
+
+
public static class LuaThread.CallStack
extends java.lang.Object
+ + +

+


+ +

+ + + + + + + + + + + +
+Constructor Summary
LuaThread.CallStack() + +
+           
+  + + + + + + + + + + + + + + + +
+Method Summary
+ intgetCallstackDepth() + +
+          Get number of calls in stack
+ voidonReturn() + +
+          Method to signal the end of a call
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+LuaThread.CallStack

+
+public LuaThread.CallStack()
+
+
+ + + + + + + + +
+Method Detail
+ +

+onReturn

+
+public final void onReturn()
+
+
Method to signal the end of a call +

+

+
See Also:
DebugLib
+
+
+
+ +

+getCallstackDepth

+
+public final int getCallstackDepth()
+
+
Get number of calls in stack +

+

+ +
Returns:
number of calls in current call stack
See Also:
DebugLib
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/LuaThread.html b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaThread.html new file mode 100644 index 0000000000..62c6e6242d --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaThread.html @@ -0,0 +1,910 @@ + + + + + + +LuaThread (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class LuaThread

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaThread
+
+
+
+
public class LuaThread
extends LuaValue
+ + +

+Subclass of LuaValue that implements + a lua coroutine thread using Java Threads. +

+ A LuaThread is typically created in response to a scripted call to + coroutine.create() +

+ The threads must be initialized with the globals, so that + the global environment may be passed along according to rules of lua. + This is done via a call to setGlobals(LuaValue) + at some point during globals initialization. + See BaseLib for additional documentation and example code. +

+ The utility classes JsePlatform and JmePlatform + see to it that this initialization is done properly. + For this reason it is highly recommended to use one of these classes + when initializing globals. +

+ The behavior of coroutine threads matches closely the behavior + of C coroutine library. However, because of the use of Java threads + to manage call state, it is possible to yield from anywhere in luaj. +

+ Each Java thread wakes up at regular intervals and checks a weak reference + to determine if it can ever be resumed. If not, it throws + OrphanedThread which is an Error. + Applications should not catch OrphanedThread, because it can break + the thread safety of luaj. +

+ +

+

+
See Also:
LuaValue, +JsePlatform, +JmePlatform, +CoroutineLib
+
+ +

+ + + + + + + + + + + +
+Nested Class Summary
+static classLuaThread.CallStack + +
+           
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Field Summary
+static intcoroutine_count + +
+           
+ java.lang.ObjectdebugState + +
+          Thread-local used by DebugLib to store debugging state.
+ LuaValueerr + +
+          Field to hold state of error condition during debug hook function calls.
+static intGC_INTERVAL + +
+          Interval to check for LuaThread dereferencing.
+static intMAX_CALLSTACK + +
+           
+static LuaValues_metatable + +
+           
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + +
+Constructor Summary
LuaThread(LuaValue func, + LuaValue env) + +
+          Create a LuaThread around a function and environment
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ LuaThreadcheckthread() + +
+          Check that this is a LuaThread, or throw LuaError if it is not
+static LuaFunctiongetCallstackFunction(int level) + +
+          Get the function called as a specific location on the stack.
+ LuaValuegetfenv() + +
+          Get the environemnt for an instance.
+static LuaValuegetGlobals() + +
+          Get the current thread's environment
+ LuaValuegetmetatable() + +
+          Get the metatable for this LuaValue
+static LuaThreadgetRunning() + +
+          Get the currently running thread.
+ java.lang.StringgetStatus() + +
+           
+static booleanisMainThread(LuaThread r) + +
+          Test if this is the main thread
+ booleanisthread() + +
+          Check if this is a thread
+static LuaThread.CallStackonCall(LuaFunction function) + +
+          Callback used at the beginning of a call to prepare for possible getfenv/setfenv calls
+ LuaThreadoptthread(LuaThread defval) + +
+          Check that optional argument is a thread and return as LuaThread
+ Varargsresume(Varargs args) + +
+          Start or resume this thread
+static LuaValuesetErrorFunc(LuaValue errfunc) + +
+          Replace the error function of the currently running thread.
+ voidsetfenv(LuaValue env) + +
+          Set the environment on an object.
+static voidsetGlobals(LuaValue globals) + +
+          Set the globals of the current thread.
+ inttype() + +
+          Get the enumeration value for the type of this value.
+ java.lang.Stringtypename() + +
+          Get the String name of the type of this value.
+static Varargsyield(Varargs args) + +
+          Yield the current thread with arguments
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, call, call, call, call, callmt, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isfunction, isint, isinttype, islong, isnil, isnumber, isstring, istable, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+s_metatable

+
+public static LuaValue s_metatable
+
+
+
+
+
+ +

+coroutine_count

+
+public static int coroutine_count
+
+
+
+
+
+ +

+err

+
+public LuaValue err
+
+
Field to hold state of error condition during debug hook function calls. +

+

+
+
+
+ +

+MAX_CALLSTACK

+
+public static final int MAX_CALLSTACK
+
+
+
See Also:
Constant Field Values
+
+
+ +

+GC_INTERVAL

+
+public static int GC_INTERVAL
+
+
Interval to check for LuaThread dereferencing. +

+

+
+
+
+ +

+debugState

+
+public java.lang.Object debugState
+
+
Thread-local used by DebugLib to store debugging state. +

+

+
+
+ + + + + + + + +
+Constructor Detail
+ +

+LuaThread

+
+public LuaThread(LuaValue func,
+                 LuaValue env)
+
+
Create a LuaThread around a function and environment +

+

+
Parameters:
func - The function to execute
env - The environment to apply to the thread
+
+ + + + + + + + +
+Method Detail
+ +

+type

+
+public int type()
+
+
Description copied from class: LuaValue
+
Get the enumeration value for the type of this value. +

+

+
Specified by:
type in class LuaValue
+
+
+ +
Returns:
value for this type, one of + TNIL, + TBOOLEAN, + TNUMBER, + TSTRING, + TTABLE, + TFUNCTION, + TUSERDATA, + TTHREAD
See Also:
LuaValue.typename()
+
+
+
+ +

+typename

+
+public java.lang.String typename()
+
+
Description copied from class: LuaValue
+
Get the String name of the type of this value. +

+

+

+
Specified by:
typename in class LuaValue
+
+
+ +
Returns:
name from type name list LuaValue.TYPE_NAMES + corresponding to the type of this value: + "nil", "boolean", "number", "string", + "table", "function", "userdata", "thread"
See Also:
LuaValue.type()
+
+
+
+ +

+isthread

+
+public boolean isthread()
+
+
Description copied from class: LuaValue
+
Check if this is a thread +

+

+
Overrides:
isthread in class LuaValue
+
+
+ +
Returns:
true if this is a thread, otherwise false
See Also:
LuaValue.checkthread(), +LuaValue.optthread(LuaThread), +LuaValue.TTHREAD
+
+
+
+ +

+optthread

+
+public LuaThread optthread(LuaThread defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a thread and return as LuaThread +

+

+
Overrides:
optthread in class LuaValue
+
+
+
Parameters:
defval - LuaThread to return if this is nil or none +
Returns:
this cast to LuaTable if a thread, + defval if nil or none, + throws LuaError if some other type
See Also:
LuaValue.checkthread(), +LuaValue.isthread(), +LuaValue.TTHREAD
+
+
+
+ +

+checkthread

+
+public LuaThread checkthread()
+
+
Description copied from class: LuaValue
+
Check that this is a LuaThread, or throw LuaError if it is not +

+

+
Overrides:
checkthread in class LuaValue
+
+
+ +
Returns:
this if it is a LuaThread
See Also:
LuaValue.isthread(), +LuaValue.optthread(LuaThread), +LuaValue.TTHREAD
+
+
+
+ +

+getmetatable

+
+public LuaValue getmetatable()
+
+
Description copied from class: LuaValue
+
Get the metatable for this LuaValue +

+ For LuaTable and LuaUserdata instances, + the metatable returned is this instance metatable. + For all other types, the class metatable value will be returned. +

+

+
Overrides:
getmetatable in class LuaValue
+
+
+ +
Returns:
metatable, or null if it there is none
See Also:
LuaBoolean.s_metatable, +LuaNumber.s_metatable, +LuaNil.s_metatable, +LuaFunction.s_metatable, +s_metatable
+
+
+
+ +

+getfenv

+
+public LuaValue getfenv()
+
+
Description copied from class: LuaValue
+
Get the environemnt for an instance. +

+

+
Overrides:
getfenv in class LuaValue
+
+
+ +
Returns:
LuaValue currently set as the instances environent.
+
+
+
+ +

+setfenv

+
+public void setfenv(LuaValue env)
+
+
Description copied from class: LuaValue
+
Set the environment on an object. +

+ Typically the environment is created once per application via a platform + helper method such as JsePlatform.standardGlobals() + However, any object can serve as an environment if it contains suitable metatag + values to implement LuaValue.get(LuaValue) to provide the environment values. +

+

+
Overrides:
setfenv in class LuaValue
+
+
+
Parameters:
env - LuaValue (typically a LuaTable) containing the environment.
See Also:
JmePlatform, +JsePlatform
+
+
+
+ +

+getStatus

+
+public java.lang.String getStatus()
+
+
+
+
+
+
+ +

+getRunning

+
+public static LuaThread getRunning()
+
+
Get the currently running thread. +

+

+ +
Returns:
LuaThread that is currenly running
+
+
+
+ +

+isMainThread

+
+public static boolean isMainThread(LuaThread r)
+
+
Test if this is the main thread +

+

+ +
Returns:
true if this is the main thread
+
+
+
+ +

+setGlobals

+
+public static void setGlobals(LuaValue globals)
+
+
Set the globals of the current thread. +

+ This must be done once before any other code executes. +

+

+
Parameters:
globals - The global variables for the main ghread.
+
+
+
+ +

+getGlobals

+
+public static LuaValue getGlobals()
+
+
Get the current thread's environment +

+

+ +
Returns:
LuaValue containing the global variables of the current thread.
+
+
+
+ +

+onCall

+
+public static final LuaThread.CallStack onCall(LuaFunction function)
+
+
Callback used at the beginning of a call to prepare for possible getfenv/setfenv calls +

+

+
Parameters:
function - Function being called +
Returns:
CallStack which is used to signal the return or a tail-call recursion
See Also:
DebugLib
+
+
+
+ +

+getCallstackFunction

+
+public static final LuaFunction getCallstackFunction(int level)
+
+
Get the function called as a specific location on the stack. +

+

+
Parameters:
level - 1 for the function calling this one, 2 for the next one. +
Returns:
LuaFunction on the call stack, or null if outside of range of active stack
+
+
+
+ +

+setErrorFunc

+
+public static LuaValue setErrorFunc(LuaValue errfunc)
+
+
Replace the error function of the currently running thread. +

+

+
Parameters:
errfunc - the new error function to use. +
Returns:
the previous error function.
+
+
+
+ +

+yield

+
+public static Varargs yield(Varargs args)
+
+
Yield the current thread with arguments +

+

+
Parameters:
args - The arguments to send as return values to resume(Varargs) +
Returns:
Varargs provided as arguments to resume(Varargs)
+
+
+
+ +

+resume

+
+public Varargs resume(Varargs args)
+
+
Start or resume this thread +

+

+
Parameters:
args - The arguments to send as return values to yield(Varargs) +
Returns:
Varargs provided as arguments to yield(Varargs)
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/LuaUserdata.html b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaUserdata.html new file mode 100644 index 0000000000..237d0088b3 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaUserdata.html @@ -0,0 +1,1010 @@ + + + + + + +LuaUserdata (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class LuaUserdata

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaUserdata
+
+
+
+
public class LuaUserdata
extends LuaValue
+ + +

+


+ +

+ + + + + + + + + + + + + + + +
+Field Summary
+ java.lang.Objectm_instance + +
+           
+ LuaValuem_metatable + +
+           
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + + + + +
+Constructor Summary
LuaUserdata(java.lang.Object obj) + +
+           
LuaUserdata(java.lang.Object obj, + LuaValue metatable) + +
+           
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ java.lang.Objectcheckuserdata() + +
+          Check that this is a LuaUserdata, or throw LuaError if it is not
+ java.lang.Objectcheckuserdata(java.lang.Class c) + +
+          Check that this is a LuaUserdata, or throw LuaError if it is not
+ booleaneq_b(LuaValue val) + +
+          Equals: Perform equality comparison with another value + including metatag processing using EQ, + and return java boolean
+ LuaValueeq(LuaValue val) + +
+          Equals: Perform equality comparison with another value + including metatag processing using EQ.
+ booleaneqmt(LuaValue val) + +
+           
+ booleanequals(java.lang.Object val) + +
+           
+ LuaValueget(LuaValue key) + +
+          Get a value in a table including metatag processing using INDEX.
+ LuaValuegetmetatable() + +
+          Get the metatable for this LuaValue
+ inthashCode() + +
+           
+ booleanisuserdata() + +
+          Check if this is a userdata
+ booleanisuserdata(java.lang.Class c) + +
+          Check if this is a userdata of type c
+ java.lang.Objectoptuserdata(java.lang.Class c, + java.lang.Object defval) + +
+          Check that optional argument is a userdata whose instance is of a type + and return the Object instance
+ java.lang.Objectoptuserdata(java.lang.Object defval) + +
+          Check that optional argument is a userdata and return the Object instance
+ booleanraweq(LuaUserdata val) + +
+          Equals: Perform direct equality comparison with a LuaUserdata value + without metatag processing.
+ booleanraweq(LuaValue val) + +
+          Equals: Perform direct equality comparison with another value + without metatag processing.
+ voidset(LuaValue key, + LuaValue value) + +
+          Set a value in a table without metatag processing using NEWINDEX.
+ LuaValuesetmetatable(LuaValue metatable) + +
+          Set the metatable for this LuaValue
+ java.lang.Stringtojstring() + +
+          Convert to human readable String for any type.
+ java.lang.Objecttouserdata() + +
+          Convert to userdata instance, or null.
+ java.lang.Objecttouserdata(java.lang.Class c) + +
+          Convert to userdata instance if specific type, or null.
+ inttype() + +
+          Get the enumeration value for the type of this value.
+ java.lang.Stringtypename() + +
+          Get the String name of the type of this value.
+ java.lang.Objectuserdata() + +
+           
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, call, call, call, call, callmt, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eqmtcall, error, get, get, getfenv, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isfunction, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, setfenv, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+m_instance

+
+public final java.lang.Object m_instance
+
+
+
+
+
+ +

+m_metatable

+
+public LuaValue m_metatable
+
+
+
+
+ + + + + + + + +
+Constructor Detail
+ +

+LuaUserdata

+
+public LuaUserdata(java.lang.Object obj)
+
+
+
+ +

+LuaUserdata

+
+public LuaUserdata(java.lang.Object obj,
+                   LuaValue metatable)
+
+
+ + + + + + + + +
+Method Detail
+ +

+tojstring

+
+public java.lang.String tojstring()
+
+
Description copied from class: LuaValue
+
Convert to human readable String for any type. +

+

+
Overrides:
tojstring in class LuaValue
+
+
+ +
Returns:
String for use by human readers based on type.
See Also:
LuaValue.tostring(), +LuaValue.optjstring(String), +LuaValue.checkjstring(), +LuaValue.isstring(), +TSTRING
+
+
+
+ +

+type

+
+public int type()
+
+
Description copied from class: LuaValue
+
Get the enumeration value for the type of this value. +

+

+
Specified by:
type in class LuaValue
+
+
+ +
Returns:
value for this type, one of + TNIL, + TBOOLEAN, + TNUMBER, + TSTRING, + TTABLE, + TFUNCTION, + TUSERDATA, + TTHREAD
See Also:
LuaValue.typename()
+
+
+
+ +

+typename

+
+public java.lang.String typename()
+
+
Description copied from class: LuaValue
+
Get the String name of the type of this value. +

+

+

+
Specified by:
typename in class LuaValue
+
+
+ +
Returns:
name from type name list LuaValue.TYPE_NAMES + corresponding to the type of this value: + "nil", "boolean", "number", "string", + "table", "function", "userdata", "thread"
See Also:
LuaValue.type()
+
+
+
+ +

+hashCode

+
+public int hashCode()
+
+
+
Overrides:
hashCode in class java.lang.Object
+
+
+
+
+
+
+ +

+userdata

+
+public java.lang.Object userdata()
+
+
+
+
+
+
+ +

+isuserdata

+
+public boolean isuserdata()
+
+
Description copied from class: LuaValue
+
Check if this is a userdata +

+

+
Overrides:
isuserdata in class LuaValue
+
+
+ +
Returns:
true if this is a userdata, otherwise false
See Also:
LuaValue.isuserdata(Class), +LuaValue.touserdata(), +LuaValue.checkuserdata(), +LuaValue.optuserdata(Object), +LuaValue.TUSERDATA
+
+
+
+ +

+isuserdata

+
+public boolean isuserdata(java.lang.Class c)
+
+
Description copied from class: LuaValue
+
Check if this is a userdata of type c +

+

+
Overrides:
isuserdata in class LuaValue
+
+
+
Parameters:
c - Class to test instance against +
Returns:
true if this is a userdata + and the instance is assignable to c, + otherwise false
See Also:
LuaValue.isuserdata(), +LuaValue.touserdata(Class), +LuaValue.checkuserdata(Class), +#optuserdata(Object,Class), +LuaValue.TUSERDATA
+
+
+
+ +

+touserdata

+
+public java.lang.Object touserdata()
+
+
Description copied from class: LuaValue
+
Convert to userdata instance, or null. +

+

+
Overrides:
touserdata in class LuaValue
+
+
+ +
Returns:
userdata instance if userdata, or null if not LuaUserdata
See Also:
LuaValue.optuserdata(Object), +LuaValue.checkuserdata(), +LuaValue.isuserdata(), +LuaValue.TUSERDATA
+
+
+
+ +

+touserdata

+
+public java.lang.Object touserdata(java.lang.Class c)
+
+
Description copied from class: LuaValue
+
Convert to userdata instance if specific type, or null. +

+

+
Overrides:
touserdata in class LuaValue
+
+
+ +
Returns:
userdata instance if is a userdata whose instance derives from c, + or null if not LuaUserdata
See Also:
LuaValue.optuserdata(Class,Object), +LuaValue.checkuserdata(Class), +LuaValue.isuserdata(Class), +LuaValue.TUSERDATA
+
+
+
+ +

+optuserdata

+
+public java.lang.Object optuserdata(java.lang.Object defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a userdata and return the Object instance +

+

+
Overrides:
optuserdata in class LuaValue
+
+
+
Parameters:
defval - Object to return if this is nil or none +
Returns:
Object instance of the userdata if a LuaUserdata, + defval if nil or none, + throws LuaError if some other type
See Also:
LuaValue.checkuserdata(), +LuaValue.isuserdata(), +LuaValue.optuserdata(Class, Object), +LuaValue.TUSERDATA
+
+
+
+ +

+optuserdata

+
+public java.lang.Object optuserdata(java.lang.Class c,
+                                    java.lang.Object defval)
+
+
Description copied from class: LuaValue
+
Check that optional argument is a userdata whose instance is of a type + and return the Object instance +

+

+
Overrides:
optuserdata in class LuaValue
+
+
+
Parameters:
c - Class to test userdata instance against
defval - Object to return if this is nil or none +
Returns:
Object instance of the userdata if a LuaUserdata and instance is assignable to c, + defval if nil or none, + throws LuaError if some other type
See Also:
LuaValue.checkuserdata(Class), +LuaValue.isuserdata(Class), +LuaValue.optuserdata(Object), +LuaValue.TUSERDATA
+
+
+
+ +

+getmetatable

+
+public LuaValue getmetatable()
+
+
Description copied from class: LuaValue
+
Get the metatable for this LuaValue +

+ For LuaTable and LuaUserdata instances, + the metatable returned is this instance metatable. + For all other types, the class metatable value will be returned. +

+

+
Overrides:
getmetatable in class LuaValue
+
+
+ +
Returns:
metatable, or null if it there is none
See Also:
LuaBoolean.s_metatable, +LuaNumber.s_metatable, +LuaNil.s_metatable, +LuaFunction.s_metatable, +LuaThread.s_metatable
+
+
+
+ +

+setmetatable

+
+public LuaValue setmetatable(LuaValue metatable)
+
+
Description copied from class: LuaValue
+
Set the metatable for this LuaValue +

+ For LuaTable and LuaUserdata instances, the metatable is per instance. + For all other types, there is one metatable per type that can be set directly from java +

+

+
Overrides:
setmetatable in class LuaValue
+
+
+
Parameters:
metatable - LuaValue instance to serve as the metatable, or null to reset it. +
Returns:
this to allow chaining of Java function calls
See Also:
LuaBoolean.s_metatable, +LuaNumber.s_metatable, +LuaNil.s_metatable, +LuaFunction.s_metatable, +LuaThread.s_metatable
+
+
+
+ +

+checkuserdata

+
+public java.lang.Object checkuserdata()
+
+
Description copied from class: LuaValue
+
Check that this is a LuaUserdata, or throw LuaError if it is not +

+

+
Overrides:
checkuserdata in class LuaValue
+
+
+ +
Returns:
this if it is a LuaUserdata
See Also:
LuaValue.isuserdata(), +LuaValue.optuserdata(Object), +LuaValue.checkuserdata(Class), +LuaValue.TUSERDATA
+
+
+
+ +

+checkuserdata

+
+public java.lang.Object checkuserdata(java.lang.Class c)
+
+
Description copied from class: LuaValue
+
Check that this is a LuaUserdata, or throw LuaError if it is not +

+

+
Overrides:
checkuserdata in class LuaValue
+
+
+ +
Returns:
this if it is a LuaUserdata
See Also:
LuaValue.isuserdata(Class), +LuaValue.optuserdata(Class, Object), +LuaValue.checkuserdata(), +LuaValue.TUSERDATA
+
+
+
+ +

+get

+
+public LuaValue get(LuaValue key)
+
+
Description copied from class: LuaValue
+
Get a value in a table including metatag processing using INDEX. +

+

+
Overrides:
get in class LuaValue
+
+
+
Parameters:
key - the key to look up, must not be NIL or null +
Returns:
LuaValue for that key, or NIL if not found and no metatag
See Also:
LuaValue.get(int), +LuaValue.get(String), +LuaValue.rawget(LuaValue)
+
+
+
+ +

+set

+
+public void set(LuaValue key,
+                LuaValue value)
+
+
Description copied from class: LuaValue
+
Set a value in a table without metatag processing using NEWINDEX. +

+

+
Overrides:
set in class LuaValue
+
+
+
Parameters:
key - the key to use, must not be NIL or null
value - the value to use, can be NIL, must not be null
+
+
+
+ +

+equals

+
+public boolean equals(java.lang.Object val)
+
+
+
Overrides:
equals in class LuaValue
+
+
+
+
+
+
+ +

+eq

+
+public LuaValue eq(LuaValue val)
+
+
Description copied from class: LuaValue
+
Equals: Perform equality comparison with another value + including metatag processing using EQ. +

+

+
Overrides:
eq in class LuaValue
+
+
+
Parameters:
val - The value to compare with. +
Returns:
TRUE if values are comparable and (this == rhs), + FALSE if comparable but not equal, + LuaValue if metatag processing occurs.
See Also:
LuaValue.eq_b(LuaValue), +LuaValue.raweq(LuaValue), +LuaValue.neq(LuaValue), +LuaValue.eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue), +LuaValue.EQ
+
+
+
+ +

+eq_b

+
+public boolean eq_b(LuaValue val)
+
+
Description copied from class: LuaValue
+
Equals: Perform equality comparison with another value + including metatag processing using EQ, + and return java boolean +

+

+
Overrides:
eq_b in class LuaValue
+
+
+
Parameters:
val - The value to compare with. +
Returns:
true if values are comparable and (this == rhs), + false if comparable but not equal, + result converted to java boolean if metatag processing occurs.
See Also:
LuaValue.eq(LuaValue), +LuaValue.raweq(LuaValue), +LuaValue.neq_b(LuaValue), +LuaValue.eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue), +LuaValue.EQ
+
+
+
+ +

+raweq

+
+public boolean raweq(LuaValue val)
+
+
Description copied from class: LuaValue
+
Equals: Perform direct equality comparison with another value + without metatag processing. +

+

+
Overrides:
raweq in class LuaValue
+
+
+
Parameters:
val - The value to compare with. +
Returns:
true if (this == rhs), false otherwise
See Also:
LuaValue.eq(LuaValue), +LuaValue.raweq(LuaUserdata), +LuaValue.raweq(LuaString), +LuaValue.raweq(double), +LuaValue.raweq(int), +LuaValue.EQ
+
+
+
+ +

+raweq

+
+public boolean raweq(LuaUserdata val)
+
+
Description copied from class: LuaValue
+
Equals: Perform direct equality comparison with a LuaUserdata value + without metatag processing. +

+

+
Overrides:
raweq in class LuaValue
+
+
+
Parameters:
val - The LuaUserdata to compare with. +
Returns:
true if this is userdata + and their metatables are the same using == + and their instances are equal using LuaValue.equals(Object), + otherwise false
See Also:
LuaValue.eq(LuaValue), +LuaValue.raweq(LuaValue)
+
+
+
+ +

+eqmt

+
+public boolean eqmt(LuaValue val)
+
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/LuaValue.html b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaValue.html new file mode 100644 index 0000000000..95ab7ad66c --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/LuaValue.html @@ -0,0 +1,8292 @@ + + + + + + +LuaValue (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class LuaValue

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+
+
+
Direct Known Subclasses:
IoLib.File, LuaBoolean, LuaFunction, LuaNil, LuaNumber, LuaString, LuaTable, LuaThread, LuaUserdata
+
+
+
+
public abstract class LuaValue
extends Varargs
+ + +

+Base class for all concrete lua type values. +

+ Establishes base implementations for all the operations on lua types. + This allows Java clients to deal essentially with one type for all Java values, namely LuaValue. +

+ Constructors are provided as static methods for common Java types, such as + valueOf(int) or valueOf(String) + to allow for instance pooling. +

+ Constants are defined for the lua values + NIL, TRUE, and FALSE. + A constant NONE is defined which is a Varargs list having no values. +

+ Operations are performed on values directly via their Java methods. + For example, the following code divides two numbers: +

 LuaValue a = LuaValue.valueOf( 5 );
+ LuaValue b = LuaValue.valueOf( 4 );
+ LuaValue c = a.div(b);
+  
+ Note that in this example, c will be a LuaDouble, but would be a LuaInteger + if the value of a were changed to 8, say. + In general the value of c in practice will vary depending on both the types and values of a and b + as well as any metatable/metatag processing that occurs. +

+ Field access and function calls are similar, with common overloads to simplify Java usage: +

 LuaValue globals = JsePlatform.standardGlobals();
+ LuaValue sqrt = globals.get("math").get("sqrt");
+ LuaValue print = globals.get("print");
+ LuaValue d = sqrt.call( a );
+ print.call( LuaValue.valueOf("sqrt(5):"), a );
+  
+

+ To supply variable arguments or get multiple return values, use + invoke(Varargs) or invokemethod(LuaValue, Varargs) methods: +

 LuaValue modf = globals.get("math").get("modf");
+ Varargs r = modf.invoke( d );
+ print.call( r.arg(1), r.arg(2) );
+  
+

+ To load and run a script, LoadState is used: +

 LoadState.load( new FileInputStream("main.lua"), "main.lua", globals ).call();
+  
+

+ although require could also be used: +

 globals.get("require").call(LuaValue.valueOf("main"));
+  
+ For this to work the file must be in the current directory, or in the class path, + dependening on the platform. + See JsePlatform and JmePlatform for details. +

+ In general a LuaError may be thrown on any operation when the + types supplied to any operation are illegal from a lua perspective. + Examples could be attempting to concatenate a NIL value, or attempting arithmetic + on values that are not number. +

+ There are several methods for preinitializing tables, such as: +

+

+ Predefined constants exist for the standard lua type constants + TNIL, TBOOLEAN, TLIGHTUSERDATA, TNUMBER, TSTRING, + TTABLE, TFUNCTION, TUSERDATA, TTHREAD, + and extended lua type constants + TINT, TNONE, TVALUE +

+ Predefined constants exist for all strings used as metatags: + INDEX, NEWINDEX, CALL, MODE, METATABLE, + ADD, SUB, DIV, MUL, POW, + MOD, UNM, LEN, EQ, LT, + LE, TOSTRING, and CONCAT. +

+ +

+

+
See Also:
JsePlatform, +JmePlatform, +LoadState, +Varargs
+
+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Field Summary
+static LuaStringADD + +
+          LuaString constant with value "__add" for use as metatag
+static LuaStringCALL + +
+          LuaString constant with value "__call" for use as metatag
+static LuaStringCONCAT + +
+          LuaString constant with value "__concat" for use as metatag
+static LuaStringDIV + +
+          LuaString constant with value "__div" for use as metatag
+static LuaStringEMPTYSTRING + +
+          LuaString constant with value ""
+static LuaStringEQ + +
+          LuaString constant with value "__eq" for use as metatag
+static LuaBooleanFALSE + +
+          LuaBoolean constant corresponding to lua false
+static LuaStringINDEX + +
+          LuaString constant with value "__index" for use as metatag
+static LuaStringLE + +
+          LuaString constant with value "__le" for use as metatag
+static LuaStringLEN + +
+          LuaString constant with value "__len" for use as metatag
+static LuaStringLT + +
+          LuaString constant with value "__lt" for use as metatag
+static LuaStringMETATABLE + +
+          LuaString constant with value "__metatable" for use as metatag
+static LuaNumberMINUSONE + +
+          LuaValue number constant equal to -1
+static LuaStringMOD + +
+          LuaString constant with value "__mod" for use as metatag
+static LuaStringMODE + +
+          LuaString constant with value "__mode" for use as metatag
+static LuaStringMUL + +
+          LuaString constant with value "__mul" for use as metatag
+static LuaStringNEWINDEX + +
+          LuaString constant with value "__newindex" for use as metatag
+static LuaValueNIL + +
+          LuaValue constant corresponding to lua nil
+static LuaValue[]NILS + +
+          Array of NIL values to optimize filling stacks using System.arraycopy().
+static LuaValueNONE + +
+          LuaValue constant corresponding to a Varargs list of no values
+static LuaValue[]NOVALS + +
+          LuaValue array constant with no values
+static LuaNumberONE + +
+          LuaValue number constant equal to 1
+static LuaStringPOW + +
+          LuaString constant with value "__pow" for use as metatag
+static LuaStringSUB + +
+          LuaString constant with value "__sub" for use as metatag
+static intTBOOLEAN + +
+          Type enumeration constant for lua booleans
+static intTFUNCTION + +
+          Type enumeration constant for lua functions
+static intTINT + +
+          Type enumeration constant for lua numbers that are ints, for compatibility with lua 5.1 number patch only
+static intTLIGHTUSERDATA + +
+          Type enumeration constant for lua light userdata, for compatibility with C-based lua only
+static intTNIL + +
+          Type enumeration constant for lua nil
+static intTNONE + +
+          Type enumeration constant for lua values that have no type, for example weak table entries
+static intTNUMBER + +
+          Type enumeration constant for lua numbers
+static LuaStringTOSTRING + +
+          LuaString constant with value "__tostring" for use as metatag
+static LuaBooleanTRUE + +
+          LuaBoolean constant corresponding to lua true
+static intTSTRING + +
+          Type enumeration constant for lua strings
+static intTTABLE + +
+          Type enumeration constant for lua tables
+static intTTHREAD + +
+          Type enumeration constant for lua threads
+static intTUSERDATA + +
+          Type enumeration constant for lua userdatas
+static intTVALUE + +
+          Type enumeration constant for unknown values, for compatibility with C-based lua only
+static java.lang.String[]TYPE_NAMES + +
+          String array constant containing names of each of the lua value types
+static LuaStringUNM + +
+          LuaString constant with value "__unm" for use as metatag
+static LuaNumberZERO + +
+          LuaValue number constant equal to 0
+  + + + + + + + + + + +
+Constructor Summary
LuaValue() + +
+           
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ LuaValueadd(double rhs) + +
+          Add: Perform numeric add operation with another value + of double type with metatag processing
+ LuaValueadd(int rhs) + +
+          Add: Perform numeric add operation with another value + of int type with metatag processing
+ LuaValueadd(LuaValue rhs) + +
+          Add: Perform numeric add operation with another value + including metatag processing.
+ LuaValueand(LuaValue rhs) + +
+          Perform boolean and with another operand, based on lua rules for boolean evaluation.
+ LuaValuearg(int index) + +
+          Get the n-th argument value (1-based).
+ LuaValuearg1() + +
+          Get the first argument in the list.
+static LuaValueargerror(int iarg, + java.lang.String msg) + +
+          Throw a LuaError indicating an invalid argument was supplied to a function
+protected  LuaValueargerror(java.lang.String expected) + +
+          Throw a LuaError indicating an invalid argument was supplied to a function
+protected  LuaValuearitherror() + +
+          Throw a LuaError based on an arithmetic error such as add, or pow, + typically due to an invalid operand type
+protected  LuaValuearitherror(java.lang.String fun) + +
+          Throw a LuaError based on an arithmetic error such as add, or pow, + typically due to an invalid operand type
+protected  LuaValuearithmt(LuaValue tag, + LuaValue op2) + +
+          Perform metatag processing for arithmetic operations.
+protected  LuaValuearithmtwith(LuaValue tag, + double op1) + +
+          Perform metatag processing for arithmetic operations when the left-hand-side is a number.
+static voidassert_(boolean b, + java.lang.String msg) + +
+          Assert a condition is true, or throw a LuaError if not
+ Bufferbuffer() + +
+          Convert the value to a Buffer for more efficient concatenation of + multiple strings.
+ LuaValuecall() + +
+          Call this with 0 arguments, including metatag processing, + and return only the first return value.
+ LuaValuecall(LuaValue arg) + +
+          Call this with 1 argument, including metatag processing, + and return only the first return value.
+ LuaValuecall(LuaValue arg1, + LuaValue arg2) + +
+          Call this with 2 arguments, including metatag processing, + and return only the first return value.
+ LuaValuecall(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+          Call this with 3 arguments, including metatag processing, + and return only the first return value.
+protected  LuaValuecallmt() + +
+          Get the metatag value for the CALL metatag, if it exists.
+ booleancheckboolean() + +
+          Check that the value is a LuaBoolean, + or throw LuaError if not
+ LuaClosurecheckclosure() + +
+          Check that the value is a LuaClosure , + or throw LuaError if not
+ doublecheckdouble() + +
+          Check that the value is numeric and return the value as a double, + or throw LuaError if not numeric
+ LuaValuecheckfunction() + +
+          Check that the value is a function , or throw LuaError if not
+ intcheckint() + +
+          Check that the value is numeric, and convert and cast value to int, or throw LuaError if not numeric
+ LuaIntegercheckinteger() + +
+          Check that the value is numeric, and convert and cast value to int, or throw LuaError if not numeric
+ java.lang.Stringcheckjstring() + +
+          Convert this value to a Java String.
+ longchecklong() + +
+          Check that the value is numeric, and convert and cast value to long, or throw LuaError if not numeric
+protected  LuaValuecheckmetatag(LuaValue tag, + java.lang.String reason) + +
+          Get particular metatag, or throw LuaError if it doesn't exist
+ LuaValuechecknotnil() + +
+          Check that this is not the value NIL, or throw LuaError if it is
+ LuaNumberchecknumber() + +
+          Check that the value is numeric, and return as a LuaNumber if so, or throw LuaError
+ LuaNumberchecknumber(java.lang.String msg) + +
+          Check that the value is numeric, and return as a LuaNumber if so, or throw LuaError
+ LuaStringcheckstring() + +
+          Check that this is a lua string, or throw LuaError if it is not.
+ LuaTablechecktable() + +
+          Check that this is a LuaTable, or throw LuaError if it is not
+ LuaThreadcheckthread() + +
+          Check that this is a LuaThread, or throw LuaError if it is not
+ java.lang.Objectcheckuserdata() + +
+          Check that this is a LuaUserdata, or throw LuaError if it is not
+ java.lang.Objectcheckuserdata(java.lang.Class c) + +
+          Check that this is a LuaUserdata, or throw LuaError if it is not
+ LuaValuecheckvalidkey() + +
+          Check that this is a valid key in a table index operation, or throw LuaError if not
+protected  LuaValuecompareerror(LuaValue rhs) + +
+          Throw a LuaError based on a comparison error such as greater-than or less-than, + typically due to an invalid operand type
+protected  LuaValuecompareerror(java.lang.String rhs) + +
+          Throw a LuaError based on a comparison error such as greater-than or less-than, + typically due to an invalid operand type
+ LuaValuecomparemt(LuaValue tag, + LuaValue op1) + +
+          Perform metatag processing for comparison operations.
+ Bufferconcat(Buffer rhs) + +
+          Concatenate a Buffer onto this value and return the result + using rules of lua string concatenation including metatag processing.
+ LuaValueconcat(LuaValue rhs) + +
+          Concatenate another value onto this value and return the result + using rules of lua string concatenation including metatag processing.
+ LuaValueconcatmt(LuaValue rhs) + +
+          Perform metatag processing for concatenation operations.
+ LuaValueconcatTo(LuaNumber lhs) + +
+          Reverse-concatenation: concatenate this value onto another value + known to be a LuaNumber + and return the result using rules of lua string concatenation including + metatag processing.
+ LuaValueconcatTo(LuaString lhs) + +
+          Reverse-concatenation: concatenate this value onto another value + known to be a LuaString + and return the result using rules of lua string concatenation including + metatag processing.
+ LuaValueconcatTo(LuaValue lhs) + +
+          Reverse-concatenation: concatenate this value onto another value + whose type is unknwon + and return the result using rules of lua string concatenation including + metatag processing.
+ LuaValuediv(double rhs) + +
+          Divide: Perform numeric divide operation by another value + of double type without metatag processing
+ LuaValuediv(int rhs) + +
+          Divide: Perform numeric divide operation by another value + of int type without metatag processing
+ LuaValuediv(LuaValue rhs) + +
+          Divide: Perform numeric divide operation by another value + of unknown type, + including metatag processing.
+ LuaValuedivInto(double lhs) + +
+          Reverse-divide: Perform numeric divide operation into another value + with metatag processing
+ booleaneq_b(LuaValue val) + +
+          Equals: Perform equality comparison with another value + including metatag processing using EQ, + and return java boolean
+ LuaValueeq(LuaValue val) + +
+          Equals: Perform equality comparison with another value + including metatag processing using EQ.
+static booleaneqmtcall(LuaValue lhs, + LuaValue lhsmt, + LuaValue rhs, + LuaValue rhsmt) + +
+          Perform equality testing metatag processing
+ booleanequals(java.lang.Object obj) + +
+           
+static LuaValueerror(java.lang.String message) + +
+          Throw a LuaError with a particular message
+ LuaValueget(int key) + +
+          Get a value in a table including metatag processing using INDEX.
+ LuaValueget(LuaValue key) + +
+          Get a value in a table including metatag processing using INDEX.
+ LuaValueget(java.lang.String key) + +
+          Get a value in a table including metatag processing using INDEX.
+ LuaValuegetfenv() + +
+          Get the environemnt for an instance.
+ LuaValuegetmetatable() + +
+          Get the metatable for this LuaValue
+ LuaValuegetn() + +
+          Implementation of lua 5.0 getn() function.
+protected static LuaValuegettable(LuaValue t, + LuaValue key) + +
+          get value from metatable operations, or NIL if not defined by metatables
+ booleangt_b(double rhs) + +
+          Greater than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ booleangt_b(int rhs) + +
+          Greater than: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean.
+ booleangt_b(LuaValue rhs) + +
+          Greater than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ LuaValuegt(double rhs) + +
+          Greater than: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue.
+ LuaValuegt(int rhs) + +
+          Greater than: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue.
+ LuaValuegt(LuaValue rhs) + +
+          Greater than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ booleangteq_b(double rhs) + +
+          Greater than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, + and returning java boolean.
+ booleangteq_b(int rhs) + +
+          Greater than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean.
+ booleangteq_b(LuaValue rhs) + +
+          Greater than or equals: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ LuaValuegteq(double rhs) + +
+          Greater than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue.
+ LuaValuegteq(int rhs) + +
+          Greater than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue.
+ LuaValuegteq(LuaValue rhs) + +
+          Greater than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+protected  LuaValueillegal(java.lang.String op, + java.lang.String typename) + +
+          Throw a LuaError indicating an illegal operation occurred, + typically involved in managing weak references
+ Varargsinext(LuaValue index) + +
+          Find the next integer-key,value pair if this is a table, + return NIL if there are no more, or throw a LuaError if not a table.
+ Varargsinvoke() + +
+          Call this with 0 arguments, including metatag processing, + and retain all return values in a Varargs.
+ Varargsinvoke(LuaValue[] args) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ Varargsinvoke(LuaValue[] args, + Varargs varargs) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ Varargsinvoke(LuaValue arg1, + LuaValue arg2, + Varargs varargs) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ Varargsinvoke(LuaValue arg, + Varargs varargs) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ Varargsinvoke(Varargs args) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ Varargsinvokemethod(LuaValue name) + +
+          Call named method on this with 0 arguments, including metatag processing, + and retain all return values in a Varargs.
+ Varargsinvokemethod(LuaValue name, + LuaValue[] args) + +
+          Call named method on this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ Varargsinvokemethod(LuaValue name, + Varargs args) + +
+          Call named method on this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ Varargsinvokemethod(java.lang.String name) + +
+          Call named method on this with 0 arguments, including metatag processing, + and retain all return values in a Varargs.
+ Varargsinvokemethod(java.lang.String name, + LuaValue[] args) + +
+          Call named method on this with 1 argument, including metatag processing, + and retain all return values in a Varargs.
+ Varargsinvokemethod(java.lang.String name, + Varargs args) + +
+          Call named method on this with 1 argument, including metatag processing, + and retain all return values in a Varargs.
+ booleanisboolean() + +
+          Check if this is a boolean
+ booleanisclosure() + +
+          Check if this is a function that is a closure, + meaning interprets lua bytecode for its execution
+ booleanisfunction() + +
+          Check if this is a function
+ booleanisint() + +
+          Check if this is a number and is representable by java int + without rounding or truncation
+ booleanisinttype() + +
+          Check if this is a LuaInteger
+ booleanislong() + +
+          Check if this is a number and is representable by java long + without rounding or truncation
+ booleanisnil() + +
+          Check if this is nil
+ booleanisnumber() + +
+          Check if this is a number
+ booleanisstring() + +
+          Check if this is a string
+ booleanistable() + +
+          Check if this is a table
+ booleanisthread() + +
+          Check if this is a thread
+ booleanisuserdata() + +
+          Check if this is a userdata
+ booleanisuserdata(java.lang.Class c) + +
+          Check if this is a userdata of type c
+ booleanisweaknil() + +
+          Test if this is a weak reference and its value no longer is referenced.
+ LuaValuelen() + +
+          Length operator: return lua length of object (#this) including metatag processing as java int
+protected  LuaValuelenerror() + +
+          Throw a LuaError based on the len operator, + typically due to an invalid operand type
+ intlength() + +
+          Length operator: return lua length of object (#this) including metatag processing as java int
+static LuaTablelistOf(LuaValue[] unnamedValues) + +
+          Construct a LuaTable initialized with supplied array values.
+static LuaTablelistOf(LuaValue[] unnamedValues, + Varargs lastarg) + +
+          Construct a LuaTable initialized with supplied array values.
+ LuaValueload(LuaValue library) + +
+          Load a library instance by setting its environment to this + and calling it, which should iniitalize the library instance and + install itself into this instance.
+ booleanlt_b(double rhs) + +
+          Less than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ booleanlt_b(int rhs) + +
+          Less than: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean.
+ booleanlt_b(LuaValue rhs) + +
+          Less than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ LuaValuelt(double rhs) + +
+          Less than: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue.
+ LuaValuelt(int rhs) + +
+          Less than: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue.
+ LuaValuelt(LuaValue rhs) + +
+          Less than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ booleanlteq_b(double rhs) + +
+          Less than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, + and returning java boolean.
+ booleanlteq_b(int rhs) + +
+          Less than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean.
+ booleanlteq_b(LuaValue rhs) + +
+          Less than or equals: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ LuaValuelteq(double rhs) + +
+          Less than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue.
+ LuaValuelteq(int rhs) + +
+          Less than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue.
+ LuaValuelteq(LuaValue rhs) + +
+          Less than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ LuaValuemetatag(LuaValue tag) + +
+          Get particular metatag, or return NIL if it doesn't exist
+ LuaValuemethod(LuaValue name) + +
+          Call named method on this with 0 arguments, including metatag processing, + and return only the first return value.
+ LuaValuemethod(LuaValue name, + LuaValue arg) + +
+          Call named method on this with 1 argument, including metatag processing, + and return only the first return value.
+ LuaValuemethod(LuaValue name, + LuaValue arg1, + LuaValue arg2) + +
+          Call named method on this with 2 arguments, including metatag processing, + and return only the first return value.
+ LuaValuemethod(java.lang.String name) + +
+          Call named method on this with 0 arguments, including metatag processing, + and return only the first return value.
+ LuaValuemethod(java.lang.String name, + LuaValue arg) + +
+          Call named method on this with 1 argument, including metatag processing, + and return only the first return value.
+ LuaValuemethod(java.lang.String name, + LuaValue arg1, + LuaValue arg2) + +
+          Call named method on this with 2 arguments, including metatag processing, + and return only the first return value.
+ LuaValuemod(double rhs) + +
+          Modulo: Perform numeric modulo operation with another value + of double type without metatag processing
+ LuaValuemod(int rhs) + +
+          Modulo: Perform numeric modulo operation with another value + of int type without metatag processing
+ LuaValuemod(LuaValue rhs) + +
+          Modulo: Perform numeric modulo operation with another value + of unknown type, + including metatag processing.
+ LuaValuemodFrom(double lhs) + +
+          Reverse-modulo: Perform numeric modulo operation from another value + with metatag processing
+ LuaValuemul(double rhs) + +
+          Multiply: Perform numeric multiply operation with another value + of double type with metatag processing
+ LuaValuemul(int rhs) + +
+          Multiply: Perform numeric multiply operation with another value + of int type with metatag processing
+ LuaValuemul(LuaValue rhs) + +
+          Multiply: Perform numeric multiply operation with another value + of unknown type, + including metatag processing.
+ intnarg() + +
+          Get the number of arguments, or 0 if there are none.
+ LuaValueneg() + +
+          Unary minus: return negative value (-this) as defined by lua unary minus operator
+ booleanneq_b(LuaValue val) + +
+          Notquals: Perform inequality comparison with another value + including metatag processing using EQ.
+ LuaValueneq(LuaValue val) + +
+          Notquals: Perform inequality comparison with another value + including metatag processing using EQ.
+ Varargsnext(LuaValue index) + +
+          Find the next key,value pair if this is a table, + return NIL if there are no more, or throw a LuaError if not a table.
+ LuaValuenot() + +
+          Unary not: return inverse boolean value (~this) as defined by lua not operator
+ VarargsonInvoke(Varargs args) + +
+          Callback used during tail call processing to invoke the function once.
+ booleanoptboolean(boolean defval) + +
+          Check that optional argument is a boolean and return its boolean value
+ LuaClosureoptclosure(LuaClosure defval) + +
+          Check that optional argument is a closure and return as LuaClosure
+ doubleoptdouble(double defval) + +
+          Check that optional argument is a number or string convertible to number and return as double
+ LuaFunctionoptfunction(LuaFunction defval) + +
+          Check that optional argument is a function and return as LuaFunction
+ intoptint(int defval) + +
+          Check that optional argument is a number or string convertible to number and return as int
+ LuaIntegeroptinteger(LuaInteger defval) + +
+          Check that optional argument is a number or string convertible to number and return as LuaInteger
+ java.lang.Stringoptjstring(java.lang.String defval) + +
+          Check that optional argument is a string or number and return as Java String
+ longoptlong(long defval) + +
+          Check that optional argument is a number or string convertible to number and return as long
+ LuaNumberoptnumber(LuaNumber defval) + +
+          Check that optional argument is a number or string convertible to number and return as LuaNumber
+ LuaStringoptstring(LuaString defval) + +
+          Check that optional argument is a string or number and return as LuaString
+ LuaTableopttable(LuaTable defval) + +
+          Check that optional argument is a table and return as LuaTable
+ LuaThreadoptthread(LuaThread defval) + +
+          Check that optional argument is a thread and return as LuaThread
+ java.lang.Objectoptuserdata(java.lang.Class c, + java.lang.Object defval) + +
+          Check that optional argument is a userdata whose instance is of a type + and return the Object instance
+ java.lang.Objectoptuserdata(java.lang.Object defval) + +
+          Check that optional argument is a userdata and return the Object instance
+ LuaValueoptvalue(LuaValue defval) + +
+          Perform argument check that this is not nil or none.
+ LuaValueor(LuaValue rhs) + +
+          Perform boolean or with another operand, based on lua rules for boolean evaluation.
+ LuaValuepow(double rhs) + +
+          Raise to power: Raise this value to a power + of double type with metatag processing
+ LuaValuepow(int rhs) + +
+          Raise to power: Raise this value to a power + of int type with metatag processing
+ LuaValuepow(LuaValue rhs) + +
+          Raise to power: Raise this value to a power + including metatag processing.
+ LuaValuepowWith(double lhs) + +
+          Reverse-raise to power: Raise another value of double type to this power + with metatag processing
+ LuaValuepowWith(int lhs) + +
+          Reverse-raise to power: Raise another value of double type to this power + with metatag processing
+ voidpresize(int i) + +
+          Preallocate the array part of a table to be a certain size,
+ booleanraweq(double val) + +
+          Equals: Perform direct equality comparison with a double value + without metatag processing.
+ booleanraweq(int val) + +
+          Equals: Perform direct equality comparison with a int value + without metatag processing.
+ booleanraweq(LuaString val) + +
+          Equals: Perform direct equality comparison with a LuaString value + without metatag processing.
+ booleanraweq(LuaUserdata val) + +
+          Equals: Perform direct equality comparison with a LuaUserdata value + without metatag processing.
+ booleanraweq(LuaValue val) + +
+          Equals: Perform direct equality comparison with another value + without metatag processing.
+ LuaValuerawget(int key) + +
+          Get a value in a table without metatag processing.
+ LuaValuerawget(LuaValue key) + +
+          Get a value in a table without metatag processing.
+ LuaValuerawget(java.lang.String key) + +
+          Get a value in a table without metatag processing.
+ voidrawset(int key, + LuaValue value) + +
+          Set a value in a table without metatag processing.
+ voidrawset(int key, + java.lang.String value) + +
+          Set a value in a table without metatag processing.
+ voidrawset(LuaValue key, + LuaValue value) + +
+          Set a value in a table without metatag processing.
+ voidrawset(java.lang.String key, + double value) + +
+          Set a value in a table without metatag processing.
+ voidrawset(java.lang.String key, + int value) + +
+          Set a value in a table without metatag processing.
+ voidrawset(java.lang.String key, + LuaValue value) + +
+          Set a value in a table without metatag processing.
+ voidrawset(java.lang.String key, + java.lang.String value) + +
+          Set a value in a table without metatag processing.
+ voidrawsetlist(int key0, + Varargs values) + +
+          Set list values in a table without invoking metatag processing
+ voidset(int key, + LuaValue value) + +
+          Set a value in a table without metatag processing using NEWINDEX.
+ voidset(int key, + java.lang.String value) + +
+          Set a value in a table without metatag processing using NEWINDEX.
+ voidset(LuaValue key, + LuaValue value) + +
+          Set a value in a table without metatag processing using NEWINDEX.
+ voidset(java.lang.String key, + double value) + +
+          Set a value in a table without metatag processing using NEWINDEX.
+ voidset(java.lang.String key, + int value) + +
+          Set a value in a table without metatag processing using NEWINDEX.
+ voidset(java.lang.String key, + LuaValue value) + +
+          Set a value in a table without metatag processing using NEWINDEX.
+ voidset(java.lang.String key, + java.lang.String value) + +
+          Set a value in a table without metatag processing using NEWINDEX.
+ voidsetfenv(LuaValue env) + +
+          Set the environment on an object.
+ LuaValuesetmetatable(LuaValue metatable) + +
+          Set the metatable for this LuaValue
+protected static booleansettable(LuaValue t, + LuaValue key, + LuaValue value) + +
+          Perform field assignment including metatag processing.
+ intstrcmp(LuaString rhs) + +
+          Perform string comparison with another value + known to be a LuaString + using string comparison based on byte values.
+ intstrcmp(LuaValue rhs) + +
+          Perform string comparison with another value + of any type + using string comparison based on byte values.
+ LuaValuestrongkey() + +
+          Return the key part of this value if it is a weak table entry, or NIL if it was weak and is no longer referenced.
+ LuaValuestrongvalue() + +
+          Return this value as a strong reference, or NIL if it was weak and is no longer referenced.
+ LuaStringstrvalue() + +
+          Convert this value to a string if it is a LuaString or LuaNumber, + or throw a LuaError if it is not
+ LuaValuesub(double rhs) + +
+          Subtract: Perform numeric subtract operation with another value + of double type with metatag processing
+ LuaValuesub(int rhs) + +
+          Subtract: Perform numeric subtract operation with another value + of int type with metatag processing
+ LuaValuesub(LuaValue rhs) + +
+          Subtract: Perform numeric subtract operation with another value + of unknown type, + including metatag processing.
+ LuaValuesubFrom(double lhs) + +
+          Reverse-subtract: Perform numeric subtract operation from an int value + with metatag processing
+ LuaValuesubFrom(int lhs) + +
+          Reverse-subtract: Perform numeric subtract operation from a double value + without metatag processing
+static LuaTabletableOf() + +
+          Construct an empty LuaTable.
+static LuaTabletableOf(int narray, + int nhash) + +
+          Construct an empty LuaTable preallocated to hold array and hashed elements
+static LuaTabletableOf(LuaValue[] namedValues) + +
+          Construct a LuaTable initialized with supplied named values.
+static LuaTabletableOf(LuaValue[] namedValues, + LuaValue[] unnamedValues) + +
+          Construct a LuaTable initialized with supplied named values and sequential elements.
+static LuaTabletableOf(LuaValue[] namedValues, + LuaValue[] unnamedValues, + Varargs lastarg) + +
+          Construct a LuaTable initialized with supplied named values and sequential elements in an array part and as varargs.
+static LuaTabletableOf(Varargs varargs, + int firstarg) + +
+          Construct a LuaTable initialized with supplied array values.
+static VarargstailcallOf(LuaValue func, + Varargs args) + +
+          Construct a TailcallVarargs around a function and arguments.
+ booleantestfor_b(LuaValue limit, + LuaValue step) + +
+          Perform end-condition test in for-loop processing.
+ booleantoboolean() + +
+          Convert to boolean false if NIL or FALSE, true if anything else
+ bytetobyte() + +
+          Convert to byte if numeric, or 0 if not.
+ chartochar() + +
+          Convert to char if numeric, or 0 if not.
+ doubletodouble() + +
+          Convert to double if numeric, or 0 if not.
+ floattofloat() + +
+          Convert to float if numeric, or 0 if not.
+ inttoint() + +
+          Convert to int if numeric, or 0 if not.
+ java.lang.Stringtojstring() + +
+          Convert to human readable String for any type.
+ longtolong() + +
+          Convert to long if numeric, or 0 if not.
+ LuaValuetonumber() + +
+          Conditionally convert to lua number without throwing errors.
+ shorttoshort() + +
+          Convert to short if numeric, or 0 if not.
+ LuaValuetostring() + +
+          Conditionally convert to lua string without throwing errors.
+ java.lang.StringtoString() + +
+          Convert the value to a human readable string using tojstring()
+ java.lang.Objecttouserdata() + +
+          Convert to userdata instance, or null.
+ java.lang.Objecttouserdata(java.lang.Class c) + +
+          Convert to userdata instance if specific type, or null.
+abstract  inttype() + +
+          Get the enumeration value for the type of this value.
+abstract  java.lang.Stringtypename() + +
+          Get the String name of the type of this value.
+protected  LuaValuetyperror(java.lang.String expected) + +
+          Throw a LuaError indicating an invalid type was supplied to a function
+protected  LuaValueunimplemented(java.lang.String fun) + +
+          Throw a LuaError indicating an operation is not implemented
+static LuaUserdatauserdataOf(java.lang.Object o) + +
+          Construct a LuaUserdata for an object.
+static LuaUserdatauserdataOf(java.lang.Object o, + LuaValue metatable) + +
+          Construct a LuaUserdata for an object with a user supplied metatable.
+static LuaBooleanvalueOf(boolean b) + +
+          Convert java boolean to a LuaValue.
+static LuaStringvalueOf(byte[] bytes) + +
+          Convert bytes in an array to a LuaValue.
+static LuaStringvalueOf(byte[] bytes, + int off, + int len) + +
+          Convert bytes in an array to a LuaValue.
+static LuaNumbervalueOf(double d) + +
+          Convert java double to a LuaValue.
+static LuaIntegervalueOf(int i) + +
+          Convert java int to a LuaValue.
+static LuaStringvalueOf(java.lang.String s) + +
+          Convert java string to a LuaValue.
+static VarargsvarargsOf(LuaValue[] v) + +
+          Construct a Varargs around an array of LuaValues.
+static VarargsvarargsOf(LuaValue[] v, + int offset, + int length) + +
+          Construct a Varargs around an array of LuaValues.
+static VarargsvarargsOf(LuaValue[] v, + int offset, + int length, + Varargs more) + +
+          Construct a Varargs around an array of LuaValues.
+static VarargsvarargsOf(LuaValue[] v, + Varargs r) + +
+          Construct a Varargs around an array of LuaValues.
+static VarargsvarargsOf(LuaValue v1, + LuaValue v2, + Varargs v3) + +
+          Construct a Varargs around a set of 3 or more LuaValues.
+static VarargsvarargsOf(LuaValue v, + Varargs r) + +
+          Construct a Varargs around a set of 2 or more LuaValues.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+TINT

+
+public static final int TINT
+
+
Type enumeration constant for lua numbers that are ints, for compatibility with lua 5.1 number patch only +

+

+
See Also:
Constant Field Values
+
+
+ +

+TNONE

+
+public static final int TNONE
+
+
Type enumeration constant for lua values that have no type, for example weak table entries +

+

+
See Also:
Constant Field Values
+
+
+ +

+TNIL

+
+public static final int TNIL
+
+
Type enumeration constant for lua nil +

+

+
See Also:
Constant Field Values
+
+
+ +

+TBOOLEAN

+
+public static final int TBOOLEAN
+
+
Type enumeration constant for lua booleans +

+

+
See Also:
Constant Field Values
+
+
+ +

+TLIGHTUSERDATA

+
+public static final int TLIGHTUSERDATA
+
+
Type enumeration constant for lua light userdata, for compatibility with C-based lua only +

+

+
See Also:
Constant Field Values
+
+
+ +

+TNUMBER

+
+public static final int TNUMBER
+
+
Type enumeration constant for lua numbers +

+

+
See Also:
Constant Field Values
+
+
+ +

+TSTRING

+
+public static final int TSTRING
+
+
Type enumeration constant for lua strings +

+

+
See Also:
Constant Field Values
+
+
+ +

+TTABLE

+
+public static final int TTABLE
+
+
Type enumeration constant for lua tables +

+

+
See Also:
Constant Field Values
+
+
+ +

+TFUNCTION

+
+public static final int TFUNCTION
+
+
Type enumeration constant for lua functions +

+

+
See Also:
Constant Field Values
+
+
+ +

+TUSERDATA

+
+public static final int TUSERDATA
+
+
Type enumeration constant for lua userdatas +

+

+
See Also:
Constant Field Values
+
+
+ +

+TTHREAD

+
+public static final int TTHREAD
+
+
Type enumeration constant for lua threads +

+

+
See Also:
Constant Field Values
+
+
+ +

+TVALUE

+
+public static final int TVALUE
+
+
Type enumeration constant for unknown values, for compatibility with C-based lua only +

+

+
See Also:
Constant Field Values
+
+
+ +

+TYPE_NAMES

+
+public static final java.lang.String[] TYPE_NAMES
+
+
String array constant containing names of each of the lua value types +

+

+
See Also:
type(), +typename()
+
+
+ +

+NIL

+
+public static final LuaValue NIL
+
+
LuaValue constant corresponding to lua nil +

+

+
+
+
+ +

+TRUE

+
+public static final LuaBoolean TRUE
+
+
LuaBoolean constant corresponding to lua true +

+

+
+
+
+ +

+FALSE

+
+public static final LuaBoolean FALSE
+
+
LuaBoolean constant corresponding to lua false +

+

+
+
+
+ +

+NONE

+
+public static final LuaValue NONE
+
+
LuaValue constant corresponding to a Varargs list of no values +

+

+
+
+
+ +

+ZERO

+
+public static final LuaNumber ZERO
+
+
LuaValue number constant equal to 0 +

+

+
+
+
+ +

+ONE

+
+public static final LuaNumber ONE
+
+
LuaValue number constant equal to 1 +

+

+
+
+
+ +

+MINUSONE

+
+public static final LuaNumber MINUSONE
+
+
LuaValue number constant equal to -1 +

+

+
+
+
+ +

+NOVALS

+
+public static final LuaValue[] NOVALS
+
+
LuaValue array constant with no values +

+

+
+
+
+ +

+INDEX

+
+public static final LuaString INDEX
+
+
LuaString constant with value "__index" for use as metatag +

+

+
+
+
+ +

+NEWINDEX

+
+public static final LuaString NEWINDEX
+
+
LuaString constant with value "__newindex" for use as metatag +

+

+
+
+
+ +

+CALL

+
+public static final LuaString CALL
+
+
LuaString constant with value "__call" for use as metatag +

+

+
+
+
+ +

+MODE

+
+public static final LuaString MODE
+
+
LuaString constant with value "__mode" for use as metatag +

+

+
+
+
+ +

+METATABLE

+
+public static final LuaString METATABLE
+
+
LuaString constant with value "__metatable" for use as metatag +

+

+
+
+
+ +

+ADD

+
+public static final LuaString ADD
+
+
LuaString constant with value "__add" for use as metatag +

+

+
+
+
+ +

+SUB

+
+public static final LuaString SUB
+
+
LuaString constant with value "__sub" for use as metatag +

+

+
+
+
+ +

+DIV

+
+public static final LuaString DIV
+
+
LuaString constant with value "__div" for use as metatag +

+

+
+
+
+ +

+MUL

+
+public static final LuaString MUL
+
+
LuaString constant with value "__mul" for use as metatag +

+

+
+
+
+ +

+POW

+
+public static final LuaString POW
+
+
LuaString constant with value "__pow" for use as metatag +

+

+
+
+
+ +

+MOD

+
+public static final LuaString MOD
+
+
LuaString constant with value "__mod" for use as metatag +

+

+
+
+
+ +

+UNM

+
+public static final LuaString UNM
+
+
LuaString constant with value "__unm" for use as metatag +

+

+
+
+
+ +

+LEN

+
+public static final LuaString LEN
+
+
LuaString constant with value "__len" for use as metatag +

+

+
+
+
+ +

+EQ

+
+public static final LuaString EQ
+
+
LuaString constant with value "__eq" for use as metatag +

+

+
+
+
+ +

+LT

+
+public static final LuaString LT
+
+
LuaString constant with value "__lt" for use as metatag +

+

+
+
+
+ +

+LE

+
+public static final LuaString LE
+
+
LuaString constant with value "__le" for use as metatag +

+

+
+
+
+ +

+TOSTRING

+
+public static final LuaString TOSTRING
+
+
LuaString constant with value "__tostring" for use as metatag +

+

+
+
+
+ +

+CONCAT

+
+public static final LuaString CONCAT
+
+
LuaString constant with value "__concat" for use as metatag +

+

+
+
+
+ +

+EMPTYSTRING

+
+public static final LuaString EMPTYSTRING
+
+
LuaString constant with value "" +

+

+
+
+
+ +

+NILS

+
+public static final LuaValue[] NILS
+
+
Array of NIL values to optimize filling stacks using System.arraycopy(). + Must not be modified. +

+

+
+
+ + + + + + + + +
+Constructor Detail
+ +

+LuaValue

+
+public LuaValue()
+
+
+ + + + + + + + +
+Method Detail
+ +

+type

+
+public abstract int type()
+
+
Get the enumeration value for the type of this value. +

+

+ +
Returns:
value for this type, one of + TNIL, + TBOOLEAN, + TNUMBER, + TSTRING, + TTABLE, + TFUNCTION, + TUSERDATA, + TTHREAD
See Also:
typename()
+
+
+
+ +

+typename

+
+public abstract java.lang.String typename()
+
+
Get the String name of the type of this value. +

+

+

+ +
Returns:
name from type name list TYPE_NAMES + corresponding to the type of this value: + "nil", "boolean", "number", "string", + "table", "function", "userdata", "thread"
See Also:
type()
+
+
+
+ +

+isboolean

+
+public boolean isboolean()
+
+
Check if this is a boolean +

+

+ +
Returns:
true if this is a boolean, otherwise false
See Also:
isboolean(), +toboolean(), +checkboolean(), +optboolean(boolean), +#TOBOLEAN
+
+
+
+ +

+isclosure

+
+public boolean isclosure()
+
+
Check if this is a function that is a closure, + meaning interprets lua bytecode for its execution +

+

+ +
Returns:
true if this is a closure, otherwise false
See Also:
isfunction(), +checkclosure(), +optclosure(LuaClosure), +TFUNCTION
+
+
+
+ +

+isfunction

+
+public boolean isfunction()
+
+
Check if this is a function +

+

+ +
Returns:
true if this is a function, otherwise false
See Also:
isclosure(), +checkfunction(), +#optfunciton(LuaFunction), +TFUNCTION
+
+
+
+ +

+isint

+
+public boolean isint()
+
+
Check if this is a number and is representable by java int + without rounding or truncation +

+

+ +
Returns:
true if this is a number + meaning derives from LuaNumber + or derives from LuaString and is convertible to a number, + and can be represented by int, + otherwise false
See Also:
isinttype(), +islong(), +tonumber(), +checkint(), +optint(int), +TNUMBER
+
+
+
+ +

+isinttype

+
+public boolean isinttype()
+
+
Check if this is a LuaInteger +

+ No attempt to convert from string will be made by this call. +

+

+ +
Returns:
true if this is a LuaInteger, + otherwise false
See Also:
isint(), +isnumber(), +tonumber(), +TNUMBER
+
+
+
+ +

+islong

+
+public boolean islong()
+
+
Check if this is a number and is representable by java long + without rounding or truncation +

+

+ +
Returns:
true if this is a number + meaning derives from LuaNumber + or derives from LuaString and is convertible to a number, + and can be represented by long, + otherwise false
See Also:
tonumber(), +checklong(), +optlong(long), +TNUMBER
+
+
+
+ +

+isnil

+
+public boolean isnil()
+
+
Check if this is nil +

+

+ +
Returns:
true if this is nil, otherwise false
See Also:
NIL, +NONE, +checknotnil(), +optvalue(LuaValue), +Varargs.isnoneornil(int), +TNIL, +TNONE
+
+
+
+ +

+isnumber

+
+public boolean isnumber()
+
+
Check if this is a number +

+

+ +
Returns:
true if this is a number, + meaning derives from LuaNumber + or derives from LuaString and is convertible to a number, + otherwise false
See Also:
tonumber(), +checknumber(), +optnumber(LuaNumber), +TNUMBER
+
+
+
+ +

+isstring

+
+public boolean isstring()
+
+
Check if this is a string +

+

+ +
Returns:
true if this is a string, + meaning derives from LuaString or LuaNumber, + otherwise false
See Also:
tostring(), +checkstring(), +optstring(LuaString), +TSTRING
+
+
+
+ +

+isthread

+
+public boolean isthread()
+
+
Check if this is a thread +

+

+ +
Returns:
true if this is a thread, otherwise false
See Also:
checkthread(), +optthread(LuaThread), +TTHREAD
+
+
+
+ +

+istable

+
+public boolean istable()
+
+
Check if this is a table +

+

+ +
Returns:
true if this is a table, otherwise false
See Also:
checktable(), +opttable(LuaTable), +TTABLE
+
+
+
+ +

+isuserdata

+
+public boolean isuserdata()
+
+
Check if this is a userdata +

+

+ +
Returns:
true if this is a userdata, otherwise false
See Also:
isuserdata(Class), +touserdata(), +checkuserdata(), +optuserdata(Object), +TUSERDATA
+
+
+
+ +

+isuserdata

+
+public boolean isuserdata(java.lang.Class c)
+
+
Check if this is a userdata of type c +

+

+
Parameters:
c - Class to test instance against +
Returns:
true if this is a userdata + and the instance is assignable to c, + otherwise false
See Also:
isuserdata(), +touserdata(Class), +checkuserdata(Class), +#optuserdata(Object,Class), +TUSERDATA
+
+
+
+ +

+toboolean

+
+public boolean toboolean()
+
+
Convert to boolean false if NIL or FALSE, true if anything else +

+

+ +
Returns:
Value cast to byte if number or string convertible to number, otherwise 0
See Also:
optboolean(boolean), +checkboolean(), +isboolean(), +TBOOLEAN
+
+
+
+ +

+tobyte

+
+public byte tobyte()
+
+
Convert to byte if numeric, or 0 if not. +

+

+ +
Returns:
Value cast to byte if number or string convertible to number, otherwise 0
See Also:
toint(), +todouble(), +#optbyte(byte), +checknumber(), +isnumber(), +TNUMBER
+
+
+
+ +

+tochar

+
+public char tochar()
+
+
Convert to char if numeric, or 0 if not. +

+

+ +
Returns:
Value cast to char if number or string convertible to number, otherwise 0
See Also:
toint(), +todouble(), +#optchar(char), +checknumber(), +isnumber(), +TNUMBER
+
+
+
+ +

+todouble

+
+public double todouble()
+
+
Convert to double if numeric, or 0 if not. +

+

+ +
Returns:
Value cast to double if number or string convertible to number, otherwise 0
See Also:
toint(), +tobyte(), +tochar(), +toshort(), +tolong(), +tofloat(), +optdouble(double), +checknumber(), +isnumber(), +TNUMBER
+
+
+
+ +

+tofloat

+
+public float tofloat()
+
+
Convert to float if numeric, or 0 if not. +

+

+ +
Returns:
Value cast to float if number or string convertible to number, otherwise 0
See Also:
toint(), +todouble(), +#optfloat(float), +checknumber(), +isnumber(), +TNUMBER
+
+
+
+ +

+toint

+
+public int toint()
+
+
Convert to int if numeric, or 0 if not. +

+

+ +
Returns:
Value cast to int if number or string convertible to number, otherwise 0
See Also:
tobyte(), +tochar(), +toshort(), +tolong(), +tofloat(), +todouble(), +optint(int), +checknumber(), +isnumber(), +TNUMBER
+
+
+
+ +

+tolong

+
+public long tolong()
+
+
Convert to long if numeric, or 0 if not. +

+

+ +
Returns:
Value cast to long if number or string convertible to number, otherwise 0
See Also:
isint(), +isinttype(), +toint(), +todouble(), +optlong(long), +checknumber(), +isnumber(), +TNUMBER
+
+
+
+ +

+toshort

+
+public short toshort()
+
+
Convert to short if numeric, or 0 if not. +

+

+ +
Returns:
Value cast to short if number or string convertible to number, otherwise 0
See Also:
toint(), +todouble(), +#optshort(short), +checknumber(), +isnumber(), +TNUMBER
+
+
+
+ +

+tojstring

+
+public java.lang.String tojstring()
+
+
Convert to human readable String for any type. +

+

+
Overrides:
tojstring in class Varargs
+
+
+ +
Returns:
String for use by human readers based on type.
See Also:
tostring(), +optjstring(String), +checkjstring(), +isstring(), +TSTRING
+
+
+
+ +

+touserdata

+
+public java.lang.Object touserdata()
+
+
Convert to userdata instance, or null. +

+

+ +
Returns:
userdata instance if userdata, or null if not LuaUserdata
See Also:
optuserdata(Object), +checkuserdata(), +isuserdata(), +TUSERDATA
+
+
+
+ +

+touserdata

+
+public java.lang.Object touserdata(java.lang.Class c)
+
+
Convert to userdata instance if specific type, or null. +

+

+ +
Returns:
userdata instance if is a userdata whose instance derives from c, + or null if not LuaUserdata
See Also:
optuserdata(Class,Object), +checkuserdata(Class), +isuserdata(Class), +TUSERDATA
+
+
+
+ +

+toString

+
+public java.lang.String toString()
+
+
Convert the value to a human readable string using tojstring() +

+

+
Overrides:
toString in class Varargs
+
+
+ +
Returns:
String value intended to be human readible.
See Also:
tostring(), +tojstring(), +optstring(LuaString), +checkstring(), +toString()
+
+
+
+ +

+tonumber

+
+public LuaValue tonumber()
+
+
Conditionally convert to lua number without throwing errors. +

+ In lua all numbers are strings, but not all strings are numbers. + This function will return + the LuaValue this if it is a number + or a string convertible to a number, + and NIL for all other cases. +

+ This allows values to be tested for their "numeric-ness" without + the penalty of throwing exceptions, + nor the cost of converting the type and creating storage for it. +

+

+ +
Returns:
this if it is a LuaNumber + or LuaString that can be converted to a number, + otherwise NIL
See Also:
tostring(), +optnumber(LuaNumber), +checknumber(), +toint(), +todouble()
+
+
+
+ +

+tostring

+
+public LuaValue tostring()
+
+
Conditionally convert to lua string without throwing errors. +

+ In lua all numbers are strings, so this function will return + the LuaValue this if it is a string or number, + and NIL for all other cases. +

+ This allows values to be tested for their "string-ness" without + the penalty of throwing exceptions. +

+

+ +
Returns:
this if it is a LuaString or LuaNumber, + otherwise NIL
See Also:
tonumber(), +tojstring(), +optstring(LuaString), +checkstring(), +toString()
+
+
+
+ +

+optboolean

+
+public boolean optboolean(boolean defval)
+
+
Check that optional argument is a boolean and return its boolean value +

+

+
Parameters:
defval - boolean value to return if this is nil or none +
Returns:
this cast to boolean if a , + defval if nil or none, + throws LuaError otherwise +
Throws: +
LuaError - if was not a boolean or nil or none.
See Also:
checkboolean(), +isboolean(), +TBOOLEAN
+
+
+
+ +

+optclosure

+
+public LuaClosure optclosure(LuaClosure defval)
+
+
Check that optional argument is a closure and return as LuaClosure +

+ A LuaClosure is a that executes lua byteccode. +

+

+
Parameters:
defval - LuaClosure to return if this is nil or none +
Returns:
this cast to LuaClosure if a function, + defval if nil or none, + throws LuaError otherwise +
Throws: +
LuaError - if was not a closure or nil or none.
See Also:
checkclosure(), +isclosure(), +TFUNCTION
+
+
+
+ +

+optdouble

+
+public double optdouble(double defval)
+
+
Check that optional argument is a number or string convertible to number and return as double +

+

+
Parameters:
defval - double to return if this is nil or none +
Returns:
this cast to double if numeric, + defval if nil or none, + throws LuaError otherwise +
Throws: +
LuaError - if was not numeric or nil or none.
See Also:
optint(int), +optinteger(LuaInteger), +checkdouble(), +todouble(), +tonumber(), +isnumber(), +TNUMBER
+
+
+
+ +

+optfunction

+
+public LuaFunction optfunction(LuaFunction defval)
+
+
Check that optional argument is a function and return as LuaFunction +

+ A LuaFunction may either be a Java function that implements + functionality directly in Java, + or a LuaClosure + which is a LuaFunction that executes lua bytecode. +

+

+
Parameters:
defval - LuaFunction to return if this is nil or none +
Returns:
this cast to LuaFunction if a function, + defval if nil or none, + throws LuaError otherwise +
Throws: +
LuaError - if was not a function or nil or none.
See Also:
checkfunction(), +isfunction(), +TFUNCTION
+
+
+
+ +

+optint

+
+public int optint(int defval)
+
+
Check that optional argument is a number or string convertible to number and return as int +

+

+
Parameters:
defval - int to return if this is nil or none +
Returns:
this cast to int if numeric, + defval if nil or none, + throws LuaError otherwise +
Throws: +
LuaError - if was not numeric or nil or none.
See Also:
optdouble(double), +optlong(long), +optinteger(LuaInteger), +checkint(), +toint(), +tonumber(), +isnumber(), +TNUMBER
+
+
+
+ +

+optinteger

+
+public LuaInteger optinteger(LuaInteger defval)
+
+
Check that optional argument is a number or string convertible to number and return as LuaInteger +

+

+
Parameters:
defval - LuaInteger to return if this is nil or none +
Returns:
this converted and wrapped in LuaInteger if numeric, + defval if nil or none, + throws LuaError otherwise +
Throws: +
LuaError - if was not numeric or nil or none.
See Also:
optdouble(double), +optint(int), +checkint(), +toint(), +tonumber(), +isnumber(), +TNUMBER
+
+
+
+ +

+optlong

+
+public long optlong(long defval)
+
+
Check that optional argument is a number or string convertible to number and return as long +

+

+
Parameters:
defval - long to return if this is nil or none +
Returns:
this cast to long if numeric, + defval if nil or none, + throws LuaError otherwise +
Throws: +
LuaError - if was not numeric or nil or none.
See Also:
optdouble(double), +optint(int), +checkint(), +toint(), +tonumber(), +isnumber(), +TNUMBER
+
+
+
+ +

+optnumber

+
+public LuaNumber optnumber(LuaNumber defval)
+
+
Check that optional argument is a number or string convertible to number and return as LuaNumber +

+

+
Parameters:
defval - LuaNumber to return if this is nil or none +
Returns:
this cast to LuaNumber if numeric, + defval if nil or none, + throws LuaError otherwise +
Throws: +
LuaError - if was not numeric or nil or none.
See Also:
optdouble(double), +optlong(long), +optint(int), +checkint(), +toint(), +tonumber(), +isnumber(), +TNUMBER
+
+
+
+ +

+optjstring

+
+public java.lang.String optjstring(java.lang.String defval)
+
+
Check that optional argument is a string or number and return as Java String +

+

+
Parameters:
defval - LuaString to return if this is nil or none +
Returns:
this converted to String if a string or number, + defval if nil or none, + throws LuaError if some other type +
Throws: +
LuaError - if was not a string or number or nil or none.
See Also:
tojstring(), +optstring(LuaString), +checkjstring(), +toString(), +TSTRING
+
+
+
+ +

+optstring

+
+public LuaString optstring(LuaString defval)
+
+
Check that optional argument is a string or number and return as LuaString +

+

+
Parameters:
defval - LuaString to return if this is nil or none +
Returns:
this converted to LuaString if a string or number, + defval if nil or none, + throws LuaError if some other type +
Throws: +
LuaError - if was not a string or number or nil or none.
See Also:
tojstring(), +optjstring(String), +checkstring(), +toString(), +TSTRING
+
+
+
+ +

+opttable

+
+public LuaTable opttable(LuaTable defval)
+
+
Check that optional argument is a table and return as LuaTable +

+

+
Parameters:
defval - LuaTable to return if this is nil or none +
Returns:
this cast to LuaTable if a table, + defval if nil or none, + throws LuaError if some other type +
Throws: +
LuaError - if was not a table or nil or none.
See Also:
checktable(), +istable(), +TTABLE
+
+
+
+ +

+optthread

+
+public LuaThread optthread(LuaThread defval)
+
+
Check that optional argument is a thread and return as LuaThread +

+

+
Parameters:
defval - LuaThread to return if this is nil or none +
Returns:
this cast to LuaTable if a thread, + defval if nil or none, + throws LuaError if some other type +
Throws: +
LuaError - if was not a thread or nil or none.
See Also:
checkthread(), +isthread(), +TTHREAD
+
+
+
+ +

+optuserdata

+
+public java.lang.Object optuserdata(java.lang.Object defval)
+
+
Check that optional argument is a userdata and return the Object instance +

+

+
Parameters:
defval - Object to return if this is nil or none +
Returns:
Object instance of the userdata if a LuaUserdata, + defval if nil or none, + throws LuaError if some other type +
Throws: +
LuaError - if was not a userdata or nil or none.
See Also:
checkuserdata(), +isuserdata(), +optuserdata(Class, Object), +TUSERDATA
+
+
+
+ +

+optuserdata

+
+public java.lang.Object optuserdata(java.lang.Class c,
+                                    java.lang.Object defval)
+
+
Check that optional argument is a userdata whose instance is of a type + and return the Object instance +

+

+
Parameters:
c - Class to test userdata instance against
defval - Object to return if this is nil or none +
Returns:
Object instance of the userdata if a LuaUserdata and instance is assignable to c, + defval if nil or none, + throws LuaError if some other type +
Throws: +
LuaError - if was not a userdata whose instance is assignable to c or nil or none.
See Also:
checkuserdata(Class), +isuserdata(Class), +optuserdata(Object), +TUSERDATA
+
+
+
+ +

+optvalue

+
+public LuaValue optvalue(LuaValue defval)
+
+
Perform argument check that this is not nil or none. +

+

+
Parameters:
defval - LuaValue to return if this is nil or none +
Returns:
this if not nil or none, else defval
See Also:
NIL, +NONE, +isnil(), +Varargs.isnoneornil(int), +TNIL, +TNONE
+
+
+
+ +

+checkboolean

+
+public boolean checkboolean()
+
+
Check that the value is a LuaBoolean, + or throw LuaError if not +

+

+ +
Returns:
boolean value for this if it is a LuaBoolean +
Throws: +
LuaError - if not a LuaBoolean
See Also:
optboolean(boolean), +TBOOLEAN
+
+
+
+ +

+checkclosure

+
+public LuaClosure checkclosure()
+
+
Check that the value is a LuaClosure , + or throw LuaError if not +

+ LuaClosure is a subclass of that interprets lua bytecode. +

+

+ +
Returns:
this cast as LuaClosure +
Throws: +
LuaError - if not a LuaClosure
See Also:
checkfunction(), +optclosure(LuaClosure), +isclosure(), +TFUNCTION
+
+
+
+ +

+checkdouble

+
+public double checkdouble()
+
+
Check that the value is numeric and return the value as a double, + or throw LuaError if not numeric +

+ Values that are LuaNumber and values that are LuaString + that can be converted to a number will be converted to double. +

+

+ +
Returns:
value cast to a double if numeric +
Throws: +
LuaError - if not a LuaNumber or is a LuaString that can't be converted to number
See Also:
checkint(), +checkinteger(), +checklong(), +optdouble(double), +TNUMBER
+
+
+
+ +

+checkfunction

+
+public LuaValue checkfunction()
+
+
Check that the value is a function , or throw LuaError if not +

+ A function is considered anything whose type() returns TFUNCTION. + In practice it will be either a built-in Java function, typically deriving from + LuaFunction or a LuaClosure which represents lua source compiled + into lua bytecode. +

+

+ +
Returns:
this if if a lua function or closure +
Throws: +
LuaError - if not a function
See Also:
checkclosure()
+
+
+
+ +

+checkint

+
+public int checkint()
+
+
Check that the value is numeric, and convert and cast value to int, or throw LuaError if not numeric +

+ Values that are LuaNumber will be cast to int and may lose precision. + Values that are LuaString that can be converted to a number will be converted, + then cast to int, so may also lose precision. +

+

+ +
Returns:
value cast to a int if numeric +
Throws: +
LuaError - if not a LuaNumber or is a LuaString that can't be converted to number
See Also:
checkinteger(), +checklong(), +checkdouble(), +optint(int), +TNUMBER
+
+
+
+ +

+checkinteger

+
+public LuaInteger checkinteger()
+
+
Check that the value is numeric, and convert and cast value to int, or throw LuaError if not numeric +

+ Values that are LuaNumber will be cast to int and may lose precision. + Values that are LuaString that can be converted to a number will be converted, + then cast to int, so may also lose precision. +

+

+ +
Returns:
value cast to a int and wrapped in LuaInteger if numeric +
Throws: +
LuaError - if not a LuaNumber or is a LuaString that can't be converted to number
See Also:
checkint(), +checklong(), +checkdouble(), +optinteger(LuaInteger), +TNUMBER
+
+
+
+ +

+checklong

+
+public long checklong()
+
+
Check that the value is numeric, and convert and cast value to long, or throw LuaError if not numeric +

+ Values that are LuaNumber will be cast to long and may lose precision. + Values that are LuaString that can be converted to a number will be converted, + then cast to long, so may also lose precision. +

+

+ +
Returns:
value cast to a long if numeric +
Throws: +
LuaError - if not a LuaNumber or is a LuaString that can't be converted to number
See Also:
checkint(), +checkinteger(), +checkdouble(), +optlong(long), +TNUMBER
+
+
+
+ +

+checknumber

+
+public LuaNumber checknumber()
+
+
Check that the value is numeric, and return as a LuaNumber if so, or throw LuaError +

+ Values that are LuaString that can be converted to a number will be converted and returned. +

+

+ +
Returns:
value as a LuaNumber if numeric +
Throws: +
LuaError - if not a LuaNumber or is a LuaString that can't be converted to number
See Also:
checkint(), +checkinteger(), +checkdouble(), +checklong(), +optnumber(LuaNumber), +TNUMBER
+
+
+
+ +

+checknumber

+
+public LuaNumber checknumber(java.lang.String msg)
+
+
Check that the value is numeric, and return as a LuaNumber if so, or throw LuaError +

+ Values that are LuaString that can be converted to a number will be converted and returned. +

+

+
Parameters:
msg - String message to supply if conversion fails +
Returns:
value as a LuaNumber if numeric +
Throws: +
LuaError - if not a LuaNumber or is a LuaString that can't be converted to number
See Also:
checkint(), +checkinteger(), +checkdouble(), +checklong(), +optnumber(LuaNumber), +TNUMBER
+
+
+
+ +

+checkjstring

+
+public java.lang.String checkjstring()
+
+
Convert this value to a Java String. +

+ The string representations here will roughly match what is produced by the + C lua distribution, however hash codes have no relationship, + and there may be differences in number formatting. +

+

+ +
Returns:
String representation of the value
See Also:
checkstring(), +optjstring(String), +tojstring(), +isstring(), +TSTRING
+
+
+
+ +

+checkstring

+
+public LuaString checkstring()
+
+
Check that this is a lua string, or throw LuaError if it is not. +

+ In lua all numbers are strings, so this will succeed for + anything that derives from LuaString or LuaNumber. + Numbers will be converted to LuaString. +

+

+ +
Returns:
LuaString representation of the value if it is a LuaString or LuaNumber +
Throws: +
LuaError - if this is not a LuaTable
See Also:
checkjstring(), +optstring(LuaString), +tostring(), +isstring(), +TSTRING
+
+
+
+ +

+checktable

+
+public LuaTable checktable()
+
+
Check that this is a LuaTable, or throw LuaError if it is not +

+

+ +
Returns:
this if it is a LuaTable +
Throws: +
LuaError - if this is not a LuaTable
See Also:
istable(), +opttable(LuaTable), +TTABLE
+
+
+
+ +

+checkthread

+
+public LuaThread checkthread()
+
+
Check that this is a LuaThread, or throw LuaError if it is not +

+

+ +
Returns:
this if it is a LuaThread +
Throws: +
LuaError - if this is not a LuaThread
See Also:
isthread(), +optthread(LuaThread), +TTHREAD
+
+
+
+ +

+checkuserdata

+
+public java.lang.Object checkuserdata()
+
+
Check that this is a LuaUserdata, or throw LuaError if it is not +

+

+ +
Returns:
this if it is a LuaUserdata +
Throws: +
LuaError - if this is not a LuaUserdata
See Also:
isuserdata(), +optuserdata(Object), +checkuserdata(Class), +TUSERDATA
+
+
+
+ +

+checkuserdata

+
+public java.lang.Object checkuserdata(java.lang.Class c)
+
+
Check that this is a LuaUserdata, or throw LuaError if it is not +

+

+ +
Returns:
this if it is a LuaUserdata +
Throws: +
LuaError - if this is not a LuaUserdata
See Also:
isuserdata(Class), +optuserdata(Class, Object), +checkuserdata(), +TUSERDATA
+
+
+
+ +

+checknotnil

+
+public LuaValue checknotnil()
+
+
Check that this is not the value NIL, or throw LuaError if it is +

+

+ +
Returns:
this if it is not NIL +
Throws: +
LuaError - if this is NIL
See Also:
optvalue(LuaValue)
+
+
+
+ +

+checkvalidkey

+
+public LuaValue checkvalidkey()
+
+
Check that this is a valid key in a table index operation, or throw LuaError if not +

+

+ +
Returns:
this if valid as a table key +
Throws: +
LuaError - if not valid as a table key
See Also:
isnil(), +isinttype()
+
+
+
+ +

+error

+
+public static LuaValue error(java.lang.String message)
+
+
Throw a LuaError with a particular message +

+

+
Parameters:
message - String providing message details +
Throws: +
LuaError - in all cases
+
+
+
+ +

+assert_

+
+public static void assert_(boolean b,
+                           java.lang.String msg)
+
+
Assert a condition is true, or throw a LuaError if not +

+

+
Parameters:
b - condition to test +
Throws: +
LuaError - if b is not true
+
+
+
+ +

+argerror

+
+protected LuaValue argerror(java.lang.String expected)
+
+
Throw a LuaError indicating an invalid argument was supplied to a function +

+

+
Parameters:
expected - String naming the type that was expected +
Throws: +
LuaError - in all cases
+
+
+
+ +

+argerror

+
+public static LuaValue argerror(int iarg,
+                                java.lang.String msg)
+
+
Throw a LuaError indicating an invalid argument was supplied to a function +

+

+
Parameters:
iarg - index of the argument that was invalid, first index is 1
msg - String providing information about the invalid argument +
Throws: +
LuaError - in all cases
+
+
+
+ +

+typerror

+
+protected LuaValue typerror(java.lang.String expected)
+
+
Throw a LuaError indicating an invalid type was supplied to a function +

+

+
Parameters:
expected - String naming the type that was expected +
Throws: +
LuaError - in all cases
+
+
+
+ +

+unimplemented

+
+protected LuaValue unimplemented(java.lang.String fun)
+
+
Throw a LuaError indicating an operation is not implemented +

+

+ +
Throws: +
LuaError - in all cases
+
+
+
+ +

+illegal

+
+protected LuaValue illegal(java.lang.String op,
+                           java.lang.String typename)
+
+
Throw a LuaError indicating an illegal operation occurred, + typically involved in managing weak references +

+

+ +
Throws: +
LuaError - in all cases
+
+
+
+ +

+lenerror

+
+protected LuaValue lenerror()
+
+
Throw a LuaError based on the len operator, + typically due to an invalid operand type +

+

+ +
Throws: +
LuaError - in all cases
+
+
+
+ +

+aritherror

+
+protected LuaValue aritherror()
+
+
Throw a LuaError based on an arithmetic error such as add, or pow, + typically due to an invalid operand type +

+

+ +
Throws: +
LuaError - in all cases
+
+
+
+ +

+aritherror

+
+protected LuaValue aritherror(java.lang.String fun)
+
+
Throw a LuaError based on an arithmetic error such as add, or pow, + typically due to an invalid operand type +

+

+
Parameters:
fun - String description of the function that was attempted +
Throws: +
LuaError - in all cases
+
+
+
+ +

+compareerror

+
+protected LuaValue compareerror(java.lang.String rhs)
+
+
Throw a LuaError based on a comparison error such as greater-than or less-than, + typically due to an invalid operand type +

+

+
Parameters:
rhs - String description of what was on the right-hand-side of the comparison that resulted in the error. +
Throws: +
LuaError - in all cases
+
+
+
+ +

+compareerror

+
+protected LuaValue compareerror(LuaValue rhs)
+
+
Throw a LuaError based on a comparison error such as greater-than or less-than, + typically due to an invalid operand type +

+

+
Parameters:
rhs - Right-hand-side of the comparison that resulted in the error. +
Throws: +
LuaError - in all cases
+
+
+
+ +

+get

+
+public LuaValue get(LuaValue key)
+
+
Get a value in a table including metatag processing using INDEX. +

+

+
Parameters:
key - the key to look up, must not be NIL or null +
Returns:
LuaValue for that key, or NIL if not found and no metatag +
Throws: +
LuaError - if this is not a table, + or there is no INDEX metatag, + or key is NIL
See Also:
get(int), +get(String), +rawget(LuaValue)
+
+
+
+ +

+get

+
+public LuaValue get(int key)
+
+
Get a value in a table including metatag processing using INDEX. +

+

+
Parameters:
key - the key to look up +
Returns:
LuaValue for that key, or NIL if not found +
Throws: +
LuaError - if this is not a table, + or there is no INDEX metatag
See Also:
get(LuaValue), +rawget(int)
+
+
+
+ +

+get

+
+public LuaValue get(java.lang.String key)
+
+
Get a value in a table including metatag processing using INDEX. +

+

+
Parameters:
key - the key to look up, must not be null +
Returns:
LuaValue for that key, or NIL if not found +
Throws: +
LuaError - if this is not a table, + or there is no INDEX metatag
See Also:
get(LuaValue), +rawget(String)
+
+
+
+ +

+set

+
+public void set(LuaValue key,
+                LuaValue value)
+
+
Set a value in a table without metatag processing using NEWINDEX. +

+

+
Parameters:
key - the key to use, must not be NIL or null
value - the value to use, can be NIL, must not be null +
Throws: +
LuaError - if this is not a table, + or key is NIL, + or there is no NEWINDEX metatag
+
+
+
+ +

+set

+
+public void set(int key,
+                LuaValue value)
+
+
Set a value in a table without metatag processing using NEWINDEX. +

+

+
Parameters:
key - the key to use
value - the value to use, can be NIL, must not be null +
Throws: +
LuaError - if this is not a table, + or there is no NEWINDEX metatag
+
+
+
+ +

+set

+
+public void set(int key,
+                java.lang.String value)
+
+
Set a value in a table without metatag processing using NEWINDEX. +

+

+
Parameters:
key - the key to use
value - the value to use, must not be null +
Throws: +
LuaError - if this is not a table, + or there is no NEWINDEX metatag
+
+
+
+ +

+set

+
+public void set(java.lang.String key,
+                LuaValue value)
+
+
Set a value in a table without metatag processing using NEWINDEX. +

+

+
Parameters:
key - the key to use, must not be NIL or null
value - the value to use, can be NIL, must not be null +
Throws: +
LuaError - if this is not a table, + or there is no NEWINDEX metatag
+
+
+
+ +

+set

+
+public void set(java.lang.String key,
+                double value)
+
+
Set a value in a table without metatag processing using NEWINDEX. +

+

+
Parameters:
key - the key to use, must not be null
value - the value to use +
Throws: +
LuaError - if this is not a table, + or there is no NEWINDEX metatag
+
+
+
+ +

+set

+
+public void set(java.lang.String key,
+                int value)
+
+
Set a value in a table without metatag processing using NEWINDEX. +

+

+
Parameters:
key - the key to use, must not be null
value - the value to use +
Throws: +
LuaError - if this is not a table, + or there is no NEWINDEX metatag
+
+
+
+ +

+set

+
+public void set(java.lang.String key,
+                java.lang.String value)
+
+
Set a value in a table without metatag processing using NEWINDEX. +

+

+
Parameters:
key - the key to use, must not be null
value - the value to use, must not be null +
Throws: +
LuaError - if this is not a table, + or there is no NEWINDEX metatag
+
+
+
+ +

+rawget

+
+public LuaValue rawget(LuaValue key)
+
+
Get a value in a table without metatag processing. +

+

+
Parameters:
key - the key to look up, must not be NIL or null +
Returns:
LuaValue for that key, or NIL if not found +
Throws: +
LuaError - if this is not a table, or key is NIL
+
+
+
+ +

+rawget

+
+public LuaValue rawget(int key)
+
+
Get a value in a table without metatag processing. +

+

+
Parameters:
key - the key to look up +
Returns:
LuaValue for that key, or NIL if not found +
Throws: +
LuaError - if this is not a table
+
+
+
+ +

+rawget

+
+public LuaValue rawget(java.lang.String key)
+
+
Get a value in a table without metatag processing. +

+

+
Parameters:
key - the key to look up, must not be null +
Returns:
LuaValue for that key, or NIL if not found +
Throws: +
LuaError - if this is not a table
+
+
+
+ +

+rawset

+
+public void rawset(LuaValue key,
+                   LuaValue value)
+
+
Set a value in a table without metatag processing. +

+

+
Parameters:
key - the key to use, must not be NIL or null
value - the value to use, can be NIL, must not be null +
Throws: +
LuaError - if this is not a table, or key is NIL
+
+
+
+ +

+rawset

+
+public void rawset(int key,
+                   LuaValue value)
+
+
Set a value in a table without metatag processing. +

+

+
Parameters:
key - the key to use
value - the value to use, can be NIL, must not be null +
Throws: +
LuaError - if this is not a table
+
+
+
+ +

+rawset

+
+public void rawset(int key,
+                   java.lang.String value)
+
+
Set a value in a table without metatag processing. +

+

+
Parameters:
key - the key to use
value - the value to use, can be NIL, must not be null +
Throws: +
LuaError - if this is not a table
+
+
+
+ +

+rawset

+
+public void rawset(java.lang.String key,
+                   LuaValue value)
+
+
Set a value in a table without metatag processing. +

+

+
Parameters:
key - the key to use, must not be null
value - the value to use, can be NIL, must not be null +
Throws: +
LuaError - if this is not a table
+
+
+
+ +

+rawset

+
+public void rawset(java.lang.String key,
+                   double value)
+
+
Set a value in a table without metatag processing. +

+

+
Parameters:
key - the key to use, must not be null
value - the value to use +
Throws: +
LuaError - if this is not a table
+
+
+
+ +

+rawset

+
+public void rawset(java.lang.String key,
+                   int value)
+
+
Set a value in a table without metatag processing. +

+

+
Parameters:
key - the key to use, must not be null
value - the value to use +
Throws: +
LuaError - if this is not a table
+
+
+
+ +

+rawset

+
+public void rawset(java.lang.String key,
+                   java.lang.String value)
+
+
Set a value in a table without metatag processing. +

+

+
Parameters:
key - the key to use, must not be null
value - the value to use, must not be null +
Throws: +
LuaError - if this is not a table
+
+
+
+ +

+rawsetlist

+
+public void rawsetlist(int key0,
+                       Varargs values)
+
+
Set list values in a table without invoking metatag processing +

+ Primarily used internally in response to a SETLIST bytecode. +

+

+
Parameters:
key0 - the first key to set in the table
values - the list of values to set +
Throws: +
LuaError - if this is not a table.
+
+
+
+ +

+presize

+
+public void presize(int i)
+
+
Preallocate the array part of a table to be a certain size, +

+ Primarily used internally in response to a SETLIST bytecode. +

+

+
Parameters:
i - the number of array slots to preallocate in the table. +
Throws: +
LuaError - if this is not a table.
+
+
+
+ +

+next

+
+public Varargs next(LuaValue index)
+
+
Find the next key,value pair if this is a table, + return NIL if there are no more, or throw a LuaError if not a table. +

+ To iterate over all key-value pairs in a table you can use +

 LuaValue k = LuaValue.NIL;
+ while ( true ) {
+    Varargs n = table.next(k);
+    if ( (k = n.arg1()).isnil() )
+       break;
+    LuaValue v = n.arg(2)
+    process( k, v )
+ }
+

+

+
Parameters:
index - LuaInteger value identifying a key to start from, + or NIL to start at the beginning +
Returns:
Varargs containing {key,value} for the next entry, + or NIL if there are no more. +
Throws: +
LuaError - if this is not a table, or the supplied key is invalid.
See Also:
LuaTable, +#inext(), +valueOf(int), +Varargs.arg1(), +Varargs.arg(int), +isnil()
+
+
+
+ +

+inext

+
+public Varargs inext(LuaValue index)
+
+
Find the next integer-key,value pair if this is a table, + return NIL if there are no more, or throw a LuaError if not a table. +

+ To iterate over integer keys in a table you can use +

 LuaValue k = LuaValue.NIL;
+   while ( true ) {
+      Varargs n = table.inext(k);
+      if ( (k = n.arg1()).isnil() )
+         break;
+      LuaValue v = n.arg(2)
+      process( k, v )
+   }
+  
+

+

+
Parameters:
index - LuaInteger value identifying a key to start from, + or NIL to start at the beginning +
Returns:
Varargs containing (key,value) for the next entry, + or NONE if there are no more. +
Throws: +
LuaError - if this is not a table, or the supplied key is invalid.
See Also:
LuaTable, +#next(), +valueOf(int), +Varargs.arg1(), +Varargs.arg(int), +isnil()
+
+
+
+ +

+load

+
+public LuaValue load(LuaValue library)
+
+
Load a library instance by setting its environment to this + and calling it, which should iniitalize the library instance and + install itself into this instance. +

+

+
Parameters:
library - The callable LuaValue to load into this +
Returns:
LuaValue containing the result of the initialization call.
+
+
+
+ +

+arg

+
+public LuaValue arg(int index)
+
+
Description copied from class: Varargs
+
Get the n-th argument value (1-based). +

+

+
Specified by:
arg in class Varargs
+
+
+
Parameters:
index - the index of the argument to get, 1 is the first argument +
Returns:
Value at position i, or LuaValue.NIL if there is none.
See Also:
Varargs.arg1(), +NIL
+
+
+
+ +

+narg

+
+public int narg()
+
+
Description copied from class: Varargs
+
Get the number of arguments, or 0 if there are none. +

+

+
Specified by:
narg in class Varargs
+
+
+ +
Returns:
number of arguments.
+
+
+
+ +

+arg1

+
+public LuaValue arg1()
+
+
Description copied from class: Varargs
+
Get the first argument in the list. +

+

+
Specified by:
arg1 in class Varargs
+
+
+ +
Returns:
LuaValue which is first in the list, or LuaValue.NIL if there are no values.
See Also:
Varargs.arg(int), +NIL
+
+
+
+ +

+getmetatable

+
+public LuaValue getmetatable()
+
+
Get the metatable for this LuaValue +

+ For LuaTable and LuaUserdata instances, + the metatable returned is this instance metatable. + For all other types, the class metatable value will be returned. +

+

+ +
Returns:
metatable, or null if it there is none
See Also:
LuaBoolean.s_metatable, +LuaNumber.s_metatable, +LuaNil.s_metatable, +LuaFunction.s_metatable, +LuaThread.s_metatable
+
+
+
+ +

+setmetatable

+
+public LuaValue setmetatable(LuaValue metatable)
+
+
Set the metatable for this LuaValue +

+ For LuaTable and LuaUserdata instances, the metatable is per instance. + For all other types, there is one metatable per type that can be set directly from java +

+

+
Parameters:
metatable - LuaValue instance to serve as the metatable, or null to reset it. +
Returns:
this to allow chaining of Java function calls
See Also:
LuaBoolean.s_metatable, +LuaNumber.s_metatable, +LuaNil.s_metatable, +LuaFunction.s_metatable, +LuaThread.s_metatable
+
+
+
+ +

+getfenv

+
+public LuaValue getfenv()
+
+
Get the environemnt for an instance. +

+

+ +
Returns:
LuaValue currently set as the instances environent.
+
+
+
+ +

+setfenv

+
+public void setfenv(LuaValue env)
+
+
Set the environment on an object. +

+ Typically the environment is created once per application via a platform + helper method such as JsePlatform.standardGlobals() + However, any object can serve as an environment if it contains suitable metatag + values to implement get(LuaValue) to provide the environment values. +

+

+
Parameters:
env - LuaValue (typically a LuaTable) containing the environment.
See Also:
JmePlatform, +JsePlatform
+
+
+
+ +

+call

+
+public LuaValue call()
+
+
Call this with 0 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use invoke() instead. +

+ To call this as a method call, use method(LuaValue) instead. +

+

+ +
Returns:
First return value (this()), or NIL if there were none. +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
call(LuaValue), +call(LuaValue,LuaValue), +call(LuaValue, LuaValue, LuaValue), +invoke(), +method(String), +method(LuaValue)
+
+
+
+ +

+call

+
+public LuaValue call(LuaValue arg)
+
+
Call this with 1 argument, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use invoke() instead. +

+ To call this as a method call, use method(LuaValue) instead. +

+

+
Parameters:
arg - First argument to supply to the called function +
Returns:
First return value (this(arg)), or NIL if there were none. +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
call(), +call(LuaValue,LuaValue), +call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue), +method(String,LuaValue), +method(LuaValue,LuaValue)
+
+
+
+ +

+call

+
+public LuaValue call(LuaValue arg1,
+                     LuaValue arg2)
+
+
Call this with 2 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use invoke() instead. +

+ To call this as a method call, use method(LuaValue) instead. +

+

+
Parameters:
arg1 - First argument to supply to the called function
arg2 - Second argument to supply to the called function +
Returns:
First return value (this(arg1,arg2)), or NIL if there were none. +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
call(), +call(LuaValue), +call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue,LuaValue), +method(String,LuaValue,LuaValue), +method(LuaValue,LuaValue,LuaValue)
+
+
+
+ +

+call

+
+public LuaValue call(LuaValue arg1,
+                     LuaValue arg2,
+                     LuaValue arg3)
+
+
Call this with 3 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use invoke() instead. +

+ To call this as a method call, use method(LuaValue) instead. +

+

+
Parameters:
arg1 - First argument to supply to the called function
arg2 - Second argument to supply to the called function
arg3 - Second argument to supply to the called function +
Returns:
First return value (this(arg1,arg2,arg3)), or NIL if there were none. +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
call(), +call(LuaValue), +call(LuaValue, LuaValue), +#invoke(LuaValue,LuaValue, LuaValue), +invokemethod(String,Varargs), +invokemethod(LuaValue,Varargs)
+
+
+
+ +

+method

+
+public LuaValue method(java.lang.String name)
+
+
Call named method on this with 0 arguments, including metatag processing, + and return only the first return value. +

+ Look up this[name] and if it is a LuaFunction, + call it inserting this as an additional first argument. + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use invoke() instead. +

+ To call this as a plain call, use call() instead. +

+

+
Parameters:
name - Name of the method to look up for invocation +
Returns:
All values returned from this:name() as a Varargs instance +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
call(), +invoke(), +method(LuaValue), +method(String,LuaValue), +method(String,LuaValue,LuaValue)
+
+
+
+ +

+method

+
+public LuaValue method(LuaValue name)
+
+
Call named method on this with 0 arguments, including metatag processing, + and return only the first return value. +

+ Look up this[name] and if it is a LuaFunction, + call it inserting this as an additional first argument, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use invoke() instead. +

+ To call this as a plain call, use call() instead. +

+

+
Parameters:
name - Name of the method to look up for invocation +
Returns:
All values returned from this:name() as a Varargs instance +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
call(), +invoke(), +method(String), +method(LuaValue,LuaValue), +method(LuaValue,LuaValue,LuaValue)
+
+
+
+ +

+method

+
+public LuaValue method(java.lang.String name,
+                       LuaValue arg)
+
+
Call named method on this with 1 argument, including metatag processing, + and return only the first return value. +

+ Look up this[name] and if it is a LuaFunction, + call it inserting this as an additional first argument, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use invoke() instead. +

+ To call this as a plain call, use call(LuaValue) instead. +

+

+
Parameters:
name - Name of the method to look up for invocation
arg - Argument to supply to the method +
Returns:
All values returned from this:name(arg) as a Varargs instance +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
call(LuaValue), +#invoke(LuaValue), +method(LuaValue,LuaValue), +method(String), +method(String,LuaValue,LuaValue)
+
+
+
+ +

+method

+
+public LuaValue method(LuaValue name,
+                       LuaValue arg)
+
+
Call named method on this with 1 argument, including metatag processing, + and return only the first return value. +

+ Look up this[name] and if it is a LuaFunction, + call it inserting this as an additional first argument, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use invoke() instead. +

+ To call this as a plain call, use call(LuaValue) instead. +

+

+
Parameters:
name - Name of the method to look up for invocation
arg - Argument to supply to the method +
Returns:
All values returned from this:name(arg) as a Varargs instance +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
call(LuaValue), +#invoke(LuaValue), +method(String,LuaValue), +method(LuaValue), +method(LuaValue,LuaValue,LuaValue)
+
+
+
+ +

+method

+
+public LuaValue method(java.lang.String name,
+                       LuaValue arg1,
+                       LuaValue arg2)
+
+
Call named method on this with 2 arguments, including metatag processing, + and return only the first return value. +

+ Look up this[name] and if it is a LuaFunction, + call it inserting this as an additional first argument, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use invoke() instead. +

+ To call this as a plain call, use call(LuaValue,LuaValue) instead. +

+

+
Parameters:
name - Name of the method to look up for invocation
arg1 - First argument to supply to the method
arg2 - Second argument to supply to the method +
Returns:
All values returned from this:name(arg1,arg2) as a Varargs instance +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
call(LuaValue,LuaValue), +invoke(LuaValue,Varargs), +method(String,LuaValue), +method(LuaValue,LuaValue,LuaValue)
+
+
+
+ +

+method

+
+public LuaValue method(LuaValue name,
+                       LuaValue arg1,
+                       LuaValue arg2)
+
+
Call named method on this with 2 arguments, including metatag processing, + and return only the first return value. +

+ Look up this[name] and if it is a LuaFunction, + call it inserting this as an additional first argument, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use invoke() instead. +

+ To call this as a plain call, use call(LuaValue,LuaValue) instead. +

+

+
Parameters:
name - Name of the method to look up for invocation
arg1 - First argument to supply to the method
arg2 - Second argument to supply to the method +
Returns:
All values returned from this:name(arg1,arg2) as a Varargs instance +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
call(LuaValue,LuaValue), +invoke(LuaValue,Varargs), +method(LuaValue,LuaValue), +method(String,LuaValue,LuaValue)
+
+
+
+ +

+invoke

+
+public Varargs invoke()
+
+
Call this with 0 arguments, including metatag processing, + and retain all return values in a Varargs. +

+ If this is a LuaFunction, call it, and return all values. + Otherwise, look for the CALL metatag and call that. +

+ To get a particular return value, us Varargs.arg(int) +

+ To call this as a method call, use invokemethod(LuaValue) instead. +

+

+ +
Returns:
All return values as a Varargs instance. +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
call(), +invoke(Varargs), +invokemethod(String), +invokemethod(LuaValue)
+
+
+
+ +

+invoke

+
+public Varargs invoke(Varargs args)
+
+
Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs. +

+ If this is a LuaFunction, call it, and return all values. + Otherwise, look for the CALL metatag and call that. +

+ To get a particular return value, us Varargs.arg(int) +

+ To call this as a method call, use invokemethod(LuaValue) instead. +

+

+
Parameters:
args - Varargs containing the arguments to supply to the called function +
Returns:
All return values as a Varargs instance. +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
varargsOf(LuaValue[]), +call(LuaValue), +invoke(), +invoke(LuaValue,Varargs), +invokemethod(String,Varargs), +invokemethod(LuaValue,Varargs)
+
+
+
+ +

+invoke

+
+public Varargs invoke(LuaValue arg,
+                      Varargs varargs)
+
+
Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs. +

+ If this is a LuaFunction, call it, and return all values. + Otherwise, look for the CALL metatag and call that. +

+ To get a particular return value, us Varargs.arg(int) +

+ To call this as a method call, use invokemethod(LuaValue,Varargs) instead. +

+

+
Parameters:
arg - The first argument to supply to the called function
varargs - Varargs containing the remaining arguments to supply to the called function +
Returns:
All return values as a Varargs instance. +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
varargsOf(LuaValue[]), +call(LuaValue,LuaValue), +invoke(LuaValue,Varargs), +invokemethod(String,Varargs), +invokemethod(LuaValue,Varargs)
+
+
+
+ +

+invoke

+
+public Varargs invoke(LuaValue arg1,
+                      LuaValue arg2,
+                      Varargs varargs)
+
+
Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs. +

+ If this is a LuaFunction, call it, and return all values. + Otherwise, look for the CALL metatag and call that. +

+ To get a particular return value, us Varargs.arg(int) +

+ To call this as a method call, use invokemethod(LuaValue,Varargs) instead. +

+

+
Parameters:
arg1 - The first argument to supply to the called function
arg2 - The second argument to supply to the called function
varargs - Varargs containing the remaining arguments to supply to the called function +
Returns:
All return values as a Varargs instance. +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
varargsOf(LuaValue[]), +call(LuaValue,LuaValue,LuaValue), +invoke(LuaValue,LuaValue,Varargs), +invokemethod(String,Varargs), +invokemethod(LuaValue,Varargs)
+
+
+
+ +

+invoke

+
+public Varargs invoke(LuaValue[] args)
+
+
Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs. +

+ If this is a LuaFunction, call it, and return all values. + Otherwise, look for the CALL metatag and call that. +

+ To get a particular return value, us Varargs.arg(int) +

+ To call this as a method call, use invokemethod(LuaValue,Varargs) instead. +

+

+
Parameters:
args - Array of arguments to supply to the called function +
Returns:
All return values as a Varargs instance. +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
varargsOf(LuaValue[]), +call(LuaValue,LuaValue,LuaValue), +invoke(LuaValue,LuaValue,Varargs), +invokemethod(String,LuaValue[]), +invokemethod(LuaValue,LuaValue[])
+
+
+
+ +

+invoke

+
+public Varargs invoke(LuaValue[] args,
+                      Varargs varargs)
+
+
Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs. +

+ If this is a LuaFunction, call it, and return all values. + Otherwise, look for the CALL metatag and call that. +

+ To get a particular return value, us Varargs.arg(int) +

+ To call this as a method call, use invokemethod(LuaValue,Varargs) instead. +

+

+
Parameters:
args - Array of arguments to supply to the called function
varargs - Varargs containing additional arguments to supply to the called function +
Returns:
All return values as a Varargs instance. +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
varargsOf(LuaValue[]), +call(LuaValue,LuaValue,LuaValue), +invoke(LuaValue,LuaValue,Varargs), +invokemethod(String,LuaValue[]), +invokemethod(LuaValue,LuaValue[]), +invokemethod(String,Varargs), +invokemethod(LuaValue,Varargs)
+
+
+
+ +

+invokemethod

+
+public Varargs invokemethod(java.lang.String name)
+
+
Call named method on this with 0 arguments, including metatag processing, + and retain all return values in a Varargs. +

+ Look up this[name] and if it is a LuaFunction, + call it inserting this as an additional first argument, + and return all return values as a Varargs instance. + Otherwise, look for the CALL metatag and call that. +

+ To get a particular return value, us Varargs.arg(int) +

+ To call this as a plain call, use invoke() instead. +

+

+
Parameters:
name - Name of the method to look up for invocation +
Returns:
All values returned from this:name() as a Varargs instance +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
call(), +invoke(), +method(String), +invokemethod(LuaValue), +#invokemethod(String,LuaValue)
+
+
+
+ +

+invokemethod

+
+public Varargs invokemethod(LuaValue name)
+
+
Call named method on this with 0 arguments, including metatag processing, + and retain all return values in a Varargs. +

+ Look up this[name] and if it is a LuaFunction, + call it inserting this as an additional first argument, + and return all return values as a Varargs instance. + Otherwise, look for the CALL metatag and call that. +

+ To get a particular return value, us Varargs.arg(int) +

+ To call this as a plain call, use invoke() instead. +

+

+
Parameters:
name - Name of the method to look up for invocation +
Returns:
All values returned from this:name() as a Varargs instance +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
call(), +invoke(), +method(LuaValue), +invokemethod(String), +#invokemethod(LuaValue,LuaValue)
+
+
+
+ +

+invokemethod

+
+public Varargs invokemethod(java.lang.String name,
+                            Varargs args)
+
+
Call named method on this with 1 argument, including metatag processing, + and retain all return values in a Varargs. +

+ Look up this[name] and if it is a LuaFunction, + call it inserting this as an additional first argument, + and return all return values as a Varargs instance. + Otherwise, look for the CALL metatag and call that. +

+ To get a particular return value, us Varargs.arg(int) +

+ To call this as a plain call, use invoke(Varargs) instead. +

+

+
Parameters:
name - Name of the method to look up for invocation
args - Varargs containing arguments to supply to the called function after this +
Returns:
All values returned from this:name(args) as a Varargs instance +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
call(), +invoke(Varargs), +method(String), +invokemethod(LuaValue,Varargs), +invokemethod(String,LuaValue[])
+
+
+
+ +

+invokemethod

+
+public Varargs invokemethod(LuaValue name,
+                            Varargs args)
+
+
Call named method on this with variable arguments, including metatag processing, + and retain all return values in a Varargs. +

+ Look up this[name] and if it is a LuaFunction, + call it inserting this as an additional first argument, + and return all return values as a Varargs instance. + Otherwise, look for the CALL metatag and call that. +

+ To get a particular return value, us Varargs.arg(int) +

+ To call this as a plain call, use invoke(Varargs) instead. +

+

+
Parameters:
name - Name of the method to look up for invocation
args - Varargs containing arguments to supply to the called function after this +
Returns:
All values returned from this:name(args) as a Varargs instance +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
call(), +invoke(Varargs), +method(String), +invokemethod(String,Varargs), +invokemethod(LuaValue,LuaValue[])
+
+
+
+ +

+invokemethod

+
+public Varargs invokemethod(java.lang.String name,
+                            LuaValue[] args)
+
+
Call named method on this with 1 argument, including metatag processing, + and retain all return values in a Varargs. +

+ Look up this[name] and if it is a LuaFunction, + call it inserting this as an additional first argument, + and return all return values as a Varargs instance. + Otherwise, look for the CALL metatag and call that. +

+ To get a particular return value, us Varargs.arg(int) +

+ To call this as a plain call, use invoke(Varargs) instead. +

+

+
Parameters:
name - Name of the method to look up for invocation
args - Array of LuaValue containing arguments to supply to the called function after this +
Returns:
All values returned from this:name(args) as a Varargs instance +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
call(), +invoke(Varargs), +method(String), +invokemethod(LuaValue,LuaValue[]), +invokemethod(String,Varargs), +varargsOf(LuaValue[])
+
+
+
+ +

+invokemethod

+
+public Varargs invokemethod(LuaValue name,
+                            LuaValue[] args)
+
+
Call named method on this with variable arguments, including metatag processing, + and retain all return values in a Varargs. +

+ Look up this[name] and if it is a LuaFunction, + call it inserting this as an additional first argument, + and return all return values as a Varargs instance. + Otherwise, look for the CALL metatag and call that. +

+ To get a particular return value, us Varargs.arg(int) +

+ To call this as a plain call, use invoke(Varargs) instead. +

+

+
Parameters:
name - Name of the method to look up for invocation
args - Array of LuaValue containing arguments to supply to the called function after this +
Returns:
All values returned from this:name(args) as a Varargs instance +
Throws: +
LuaError - if not a function and CALL is not defined, + or the invoked function throws a LuaError + or the invoked closure throw a lua error
See Also:
call(), +invoke(Varargs), +method(String), +invokemethod(String,LuaValue[]), +invokemethod(LuaValue,Varargs), +varargsOf(LuaValue[])
+
+
+
+ +

+callmt

+
+protected LuaValue callmt()
+
+
Get the metatag value for the CALL metatag, if it exists. +

+

+ +
Returns:
LuaValue value if metatag is defined +
Throws: +
LuaError - if CALL metatag is not defined.
+
+
+
+ +

+not

+
+public LuaValue not()
+
+
Unary not: return inverse boolean value (~this) as defined by lua not operator +

+

+ +
Returns:
TRUE if NIL or FALSE, otherwise FALSE
+
+
+
+ +

+neg

+
+public LuaValue neg()
+
+
Unary minus: return negative value (-this) as defined by lua unary minus operator +

+

+ +
Returns:
boolean inverse as LuaBoolean if boolean or nil, + numeric inverse as if numeric, + or metatag processing result if UNM metatag is defined +
Throws: +
LuaError - if this is not a table or string, and has no UNM metatag
+
+
+
+ +

+len

+
+public LuaValue len()
+
+
Length operator: return lua length of object (#this) including metatag processing as java int +

+

+ +
Returns:
length as defined by the lua # operator + or metatag processing result +
Throws: +
LuaError - if this is not a table or string, and has no LEN metatag
+
+
+
+ +

+length

+
+public int length()
+
+
Length operator: return lua length of object (#this) including metatag processing as java int +

+

+ +
Returns:
length as defined by the lua # operator + or metatag processing result converted to java int using toint() +
Throws: +
LuaError - if this is not a table or string, and has no LEN metatag
+
+
+
+ +

+getn

+
+public LuaValue getn()
+
+
Implementation of lua 5.0 getn() function. +

+

+ +
Returns:
value of getn() as defined in lua 5.0 spec if this is a LuaTable +
Throws: +
LuaError - if this is not a LuaTable
+
+
+
+ +

+equals

+
+public boolean equals(java.lang.Object obj)
+
+
+
Overrides:
equals in class java.lang.Object
+
+
+
+
+
+
+ +

+eq

+
+public LuaValue eq(LuaValue val)
+
+
Equals: Perform equality comparison with another value + including metatag processing using EQ. +

+

+
Parameters:
val - The value to compare with. +
Returns:
TRUE if values are comparable and (this == rhs), + FALSE if comparable but not equal, + LuaValue if metatag processing occurs.
See Also:
eq_b(LuaValue), +raweq(LuaValue), +neq(LuaValue), +eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue), +EQ
+
+
+
+ +

+eq_b

+
+public boolean eq_b(LuaValue val)
+
+
Equals: Perform equality comparison with another value + including metatag processing using EQ, + and return java boolean +

+

+
Parameters:
val - The value to compare with. +
Returns:
true if values are comparable and (this == rhs), + false if comparable but not equal, + result converted to java boolean if metatag processing occurs.
See Also:
eq(LuaValue), +raweq(LuaValue), +neq_b(LuaValue), +eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue), +EQ
+
+
+
+ +

+neq

+
+public LuaValue neq(LuaValue val)
+
+
Notquals: Perform inequality comparison with another value + including metatag processing using EQ. +

+

+
Parameters:
val - The value to compare with. +
Returns:
TRUE if values are comparable and (this != rhs), + FALSE if comparable but equal, + inverse of LuaValue converted to LuaBoolean if metatag processing occurs.
See Also:
eq(LuaValue), +raweq(LuaValue), +eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue), +EQ
+
+
+
+ +

+neq_b

+
+public boolean neq_b(LuaValue val)
+
+
Notquals: Perform inequality comparison with another value + including metatag processing using EQ. +

+

+
Parameters:
val - The value to compare with. +
Returns:
true if values are comparable and (this != rhs), + false if comparable but equal, + inverse of result converted to boolean if metatag processing occurs.
See Also:
eq_b(LuaValue), +raweq(LuaValue), +eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue), +EQ
+
+
+
+ +

+raweq

+
+public boolean raweq(LuaValue val)
+
+
Equals: Perform direct equality comparison with another value + without metatag processing. +

+

+
Parameters:
val - The value to compare with. +
Returns:
true if (this == rhs), false otherwise
See Also:
eq(LuaValue), +raweq(LuaUserdata), +raweq(LuaString), +raweq(double), +raweq(int), +EQ
+
+
+
+ +

+raweq

+
+public boolean raweq(LuaUserdata val)
+
+
Equals: Perform direct equality comparison with a LuaUserdata value + without metatag processing. +

+

+
Parameters:
val - The LuaUserdata to compare with. +
Returns:
true if this is userdata + and their metatables are the same using == + and their instances are equal using equals(Object), + otherwise false
See Also:
eq(LuaValue), +raweq(LuaValue)
+
+
+
+ +

+raweq

+
+public boolean raweq(LuaString val)
+
+
Equals: Perform direct equality comparison with a LuaString value + without metatag processing. +

+

+
Parameters:
val - The LuaString to compare with. +
Returns:
true if this is a LuaString + and their byte sequences match, + otherwise false
+
+
+
+ +

+raweq

+
+public boolean raweq(double val)
+
+
Equals: Perform direct equality comparison with a double value + without metatag processing. +

+

+
Parameters:
val - The double value to compare with. +
Returns:
true if this is a LuaNumber + whose value equals val, + otherwise false
+
+
+
+ +

+raweq

+
+public boolean raweq(int val)
+
+
Equals: Perform direct equality comparison with a int value + without metatag processing. +

+

+
Parameters:
val - The double value to compare with. +
Returns:
true if this is a LuaNumber + whose value equals val, + otherwise false
+
+
+
+ +

+eqmtcall

+
+public static final boolean eqmtcall(LuaValue lhs,
+                                     LuaValue lhsmt,
+                                     LuaValue rhs,
+                                     LuaValue rhsmt)
+
+
Perform equality testing metatag processing +

+

+
Parameters:
lhs - left-hand-side of equality expression
lhsmt - metatag value for left-hand-side
rhs - right-hand-side of equality expression
rhsmt - metatag value for right-hand-side +
Returns:
true if metatag processing result is not NIL or FALSE +
Throws: +
LuaError - if metatag was not defined for either operand
See Also:
equals(Object), +eq(LuaValue), +raweq(LuaValue), +EQ
+
+
+
+ +

+add

+
+public LuaValue add(LuaValue rhs)
+
+
Add: Perform numeric add operation with another value + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Parameters:
rhs - The right-hand-side value to perform the add with +
Returns:
value of (this + rhs) if both are numeric, + or LuaValue if metatag processing occurs +
Throws: +
LuaError - if either operand is not a number or string convertible to number, + and neither has the ADD metatag defined
See Also:
arithmt(LuaValue, LuaValue)
+
+
+
+ +

+add

+
+public LuaValue add(double rhs)
+
+
Add: Perform numeric add operation with another value + of double type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Parameters:
rhs - The right-hand-side value to perform the add with +
Returns:
value of (this + rhs) if this is numeric +
Throws: +
LuaError - if this is not a number or string convertible to number
See Also:
add(LuaValue)
+
+
+
+ +

+add

+
+public LuaValue add(int rhs)
+
+
Add: Perform numeric add operation with another value + of int type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Parameters:
rhs - The right-hand-side value to perform the add with +
Returns:
value of (this + rhs) if this is numeric +
Throws: +
LuaError - if this is not a number or string convertible to number
See Also:
add(LuaValue)
+
+
+
+ +

+sub

+
+public LuaValue sub(LuaValue rhs)
+
+
Subtract: Perform numeric subtract operation with another value + of unknown type, + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Parameters:
rhs - The right-hand-side value to perform the subtract with +
Returns:
value of (this - rhs) if both are numeric, + or LuaValue if metatag processing occurs +
Throws: +
LuaError - if either operand is not a number or string convertible to number, + and neither has the SUB metatag defined
See Also:
arithmt(LuaValue, LuaValue)
+
+
+
+ +

+sub

+
+public LuaValue sub(double rhs)
+
+
Subtract: Perform numeric subtract operation with another value + of double type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Parameters:
rhs - The right-hand-side value to perform the subtract with +
Returns:
value of (this - rhs) if this is numeric +
Throws: +
LuaError - if this is not a number or string convertible to number
See Also:
sub(LuaValue)
+
+
+
+ +

+sub

+
+public LuaValue sub(int rhs)
+
+
Subtract: Perform numeric subtract operation with another value + of int type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Parameters:
rhs - The right-hand-side value to perform the subtract with +
Returns:
value of (this - rhs) if this is numeric +
Throws: +
LuaError - if this is not a number or string convertible to number
See Also:
sub(LuaValue)
+
+
+
+ +

+subFrom

+
+public LuaValue subFrom(double lhs)
+
+
Reverse-subtract: Perform numeric subtract operation from an int value + with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Parameters:
lhs - The left-hand-side value from which to perform the subtraction +
Returns:
value of (lhs - this) if this is numeric +
Throws: +
LuaError - if this is not a number or string convertible to number
See Also:
sub(LuaValue), +sub(double), +sub(int)
+
+
+
+ +

+subFrom

+
+public LuaValue subFrom(int lhs)
+
+
Reverse-subtract: Perform numeric subtract operation from a double value + without metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+ For metatag processing sub(LuaValue) must be used +

+

+
Parameters:
lhs - The left-hand-side value from which to perform the subtraction +
Returns:
value of (lhs - this) if this is numeric +
Throws: +
LuaError - if this is not a number or string convertible to number
See Also:
sub(LuaValue), +sub(double), +sub(int)
+
+
+
+ +

+mul

+
+public LuaValue mul(LuaValue rhs)
+
+
Multiply: Perform numeric multiply operation with another value + of unknown type, + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Parameters:
rhs - The right-hand-side value to perform the multiply with +
Returns:
value of (this * rhs) if both are numeric, + or LuaValue if metatag processing occurs +
Throws: +
LuaError - if either operand is not a number or string convertible to number, + and neither has the MUL metatag defined
See Also:
arithmt(LuaValue, LuaValue)
+
+
+
+ +

+mul

+
+public LuaValue mul(double rhs)
+
+
Multiply: Perform numeric multiply operation with another value + of double type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Parameters:
rhs - The right-hand-side value to perform the multiply with +
Returns:
value of (this * rhs) if this is numeric +
Throws: +
LuaError - if this is not a number or string convertible to number
See Also:
mul(LuaValue)
+
+
+
+ +

+mul

+
+public LuaValue mul(int rhs)
+
+
Multiply: Perform numeric multiply operation with another value + of int type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Parameters:
rhs - The right-hand-side value to perform the multiply with +
Returns:
value of (this * rhs) if this is numeric +
Throws: +
LuaError - if this is not a number or string convertible to number
See Also:
mul(LuaValue)
+
+
+
+ +

+pow

+
+public LuaValue pow(LuaValue rhs)
+
+
Raise to power: Raise this value to a power + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Parameters:
rhs - The power to raise this value to +
Returns:
value of (this ^ rhs) if both are numeric, + or LuaValue if metatag processing occurs +
Throws: +
LuaError - if either operand is not a number or string convertible to number, + and neither has the POW metatag defined
See Also:
arithmt(LuaValue, LuaValue)
+
+
+
+ +

+pow

+
+public LuaValue pow(double rhs)
+
+
Raise to power: Raise this value to a power + of double type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Parameters:
rhs - The power to raise this value to +
Returns:
value of (this ^ rhs) if this is numeric +
Throws: +
LuaError - if this is not a number or string convertible to number
See Also:
pow(LuaValue)
+
+
+
+ +

+pow

+
+public LuaValue pow(int rhs)
+
+
Raise to power: Raise this value to a power + of int type with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Parameters:
rhs - The power to raise this value to +
Returns:
value of (this ^ rhs) if this is numeric +
Throws: +
LuaError - if this is not a number or string convertible to number
See Also:
pow(LuaValue)
+
+
+
+ +

+powWith

+
+public LuaValue powWith(double lhs)
+
+
Reverse-raise to power: Raise another value of double type to this power + with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Parameters:
lhs - The left-hand-side value which will be raised to this power +
Returns:
value of (lhs ^ this) if this is numeric +
Throws: +
LuaError - if this is not a number or string convertible to number
See Also:
pow(LuaValue), +pow(double), +pow(int)
+
+
+
+ +

+powWith

+
+public LuaValue powWith(int lhs)
+
+
Reverse-raise to power: Raise another value of double type to this power + with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Parameters:
lhs - The left-hand-side value which will be raised to this power +
Returns:
value of (lhs ^ this) if this is numeric +
Throws: +
LuaError - if this is not a number or string convertible to number
See Also:
pow(LuaValue), +pow(double), +pow(int)
+
+
+
+ +

+div

+
+public LuaValue div(LuaValue rhs)
+
+
Divide: Perform numeric divide operation by another value + of unknown type, + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Parameters:
rhs - The right-hand-side value to perform the divulo with +
Returns:
value of (this / rhs) if both are numeric, + or LuaValue if metatag processing occurs +
Throws: +
LuaError - if either operand is not a number or string convertible to number, + and neither has the DIV metatag defined
See Also:
arithmt(LuaValue, LuaValue)
+
+
+
+ +

+div

+
+public LuaValue div(double rhs)
+
+
Divide: Perform numeric divide operation by another value + of double type without metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+ For metatag processing div(LuaValue) must be used +

+

+
Parameters:
rhs - The right-hand-side value to perform the divulo with +
Returns:
value of (this / rhs) if this is numeric +
Throws: +
LuaError - if this is not a number or string convertible to number
See Also:
div(LuaValue)
+
+
+
+ +

+div

+
+public LuaValue div(int rhs)
+
+
Divide: Perform numeric divide operation by another value + of int type without metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+ For metatag processing div(LuaValue) must be used +

+

+
Parameters:
rhs - The right-hand-side value to perform the divulo with +
Returns:
value of (this / rhs) if this is numeric +
Throws: +
LuaError - if this is not a number or string convertible to number
See Also:
div(LuaValue)
+
+
+
+ +

+divInto

+
+public LuaValue divInto(double lhs)
+
+
Reverse-divide: Perform numeric divide operation into another value + with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Parameters:
lhs - The left-hand-side value which will be divided by this +
Returns:
value of (lhs / this) if this is numeric +
Throws: +
LuaError - if this is not a number or string convertible to number
See Also:
div(LuaValue), +div(double), +div(int)
+
+
+
+ +

+mod

+
+public LuaValue mod(LuaValue rhs)
+
+
Modulo: Perform numeric modulo operation with another value + of unknown type, + including metatag processing. +

+ Each operand must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Parameters:
rhs - The right-hand-side value to perform the modulo with +
Returns:
value of (this % rhs) if both are numeric, + or LuaValue if metatag processing occurs +
Throws: +
LuaError - if either operand is not a number or string convertible to number, + and neither has the MOD metatag defined
See Also:
arithmt(LuaValue, LuaValue)
+
+
+
+ +

+mod

+
+public LuaValue mod(double rhs)
+
+
Modulo: Perform numeric modulo operation with another value + of double type without metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+ For metatag processing mod(LuaValue) must be used +

+

+
Parameters:
rhs - The right-hand-side value to perform the modulo with +
Returns:
value of (this % rhs) if this is numeric +
Throws: +
LuaError - if this is not a number or string convertible to number
See Also:
mod(LuaValue)
+
+
+
+ +

+mod

+
+public LuaValue mod(int rhs)
+
+
Modulo: Perform numeric modulo operation with another value + of int type without metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+ For metatag processing mod(LuaValue) must be used +

+

+
Parameters:
rhs - The right-hand-side value to perform the modulo with +
Returns:
value of (this % rhs) if this is numeric +
Throws: +
LuaError - if this is not a number or string convertible to number
See Also:
mod(LuaValue)
+
+
+
+ +

+modFrom

+
+public LuaValue modFrom(double lhs)
+
+
Reverse-modulo: Perform numeric modulo operation from another value + with metatag processing +

+ this must derive from LuaNumber + or derive from LuaString and be convertible to a number +

+

+
Parameters:
lhs - The left-hand-side value which will be modulo'ed by this +
Returns:
value of (lhs % this) if this is numeric +
Throws: +
LuaError - if this is not a number or string convertible to number
See Also:
mod(LuaValue), +mod(double), +mod(int)
+
+
+
+ +

+arithmt

+
+protected LuaValue arithmt(LuaValue tag,
+                           LuaValue op2)
+
+
Perform metatag processing for arithmetic operations. +

+ Finds the supplied metatag value for this or op2 and invokes it, + or throws LuaError if neither is defined. +

+

+
Parameters:
tag - The metatag to look up
op2 - The other operand value to perform the operation with +
Returns:
LuaValue resulting from metatag processing +
Throws: +
LuaError - if metatag was not defined for either operand
See Also:
add(LuaValue), +sub(LuaValue), +mul(LuaValue), +pow(LuaValue), +div(LuaValue), +mod(LuaValue), +ADD, +SUB, +MUL, +POW, +DIV, +MOD
+
+
+
+ +

+arithmtwith

+
+protected LuaValue arithmtwith(LuaValue tag,
+                               double op1)
+
+
Perform metatag processing for arithmetic operations when the left-hand-side is a number. +

+ Finds the supplied metatag value for this and invokes it, + or throws LuaError if neither is defined. +

+

+
Parameters:
tag - The metatag to look up
op1 - The value of the left-hand-side to perform the operation with +
Returns:
LuaValue resulting from metatag processing +
Throws: +
LuaError - if metatag was not defined for either operand
See Also:
add(LuaValue), +sub(LuaValue), +mul(LuaValue), +pow(LuaValue), +div(LuaValue), +mod(LuaValue), +ADD, +SUB, +MUL, +POW, +DIV, +MOD
+
+
+
+ +

+lt

+
+public LuaValue lt(LuaValue rhs)
+
+
Less than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this < rhs), FALSE if not, + or LuaValue if metatag processing occurs +
Throws: +
LuaError - if either both operands are not a strings or both are not numbers + and no LT metatag is defined.
See Also:
gteq_b(LuaValue), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lt

+
+public LuaValue lt(double rhs)
+
+
Less than: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this < rhs), FALSE if not, + or LuaValue if metatag processing occurs +
Throws: +
LuaError - if this is not a number + and no LT metatag is defined.
See Also:
gteq_b(double), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lt

+
+public LuaValue lt(int rhs)
+
+
Less than: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this < rhs), FALSE if not, + or LuaValue if metatag processing occurs +
Throws: +
LuaError - if this is not a number + and no LT metatag is defined.
See Also:
gteq_b(int), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lt_b

+
+public boolean lt_b(LuaValue rhs)
+
+
Less than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this < rhs), false if not, + and boolean interpreation of result if metatag processing occurs. +
Throws: +
LuaError - if either both operands are not a strings or both are not numbers + and no LT metatag is defined.
See Also:
gteq(LuaValue), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lt_b

+
+public boolean lt_b(int rhs)
+
+
Less than: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this < rhs), false if not, + and boolean interpreation of result if metatag processing occurs. +
Throws: +
LuaError - if this is not a number + and no LT metatag is defined.
See Also:
gteq(int), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lt_b

+
+public boolean lt_b(double rhs)
+
+
Less than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this < rhs), false if not, + and boolean interpreation of result if metatag processing occurs. +
Throws: +
LuaError - if either both operands are not a strings or both are not numbers + and no LT metatag is defined.
See Also:
gteq(LuaValue), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq

+
+public LuaValue lteq(LuaValue rhs)
+
+
Less than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this <= rhs), FALSE if not, + or LuaValue if metatag processing occurs +
Throws: +
LuaError - if either both operands are not a strings or both are not numbers + and no LE metatag is defined.
See Also:
gteq_b(LuaValue), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq

+
+public LuaValue lteq(double rhs)
+
+
Less than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this <= rhs), FALSE if not, + or LuaValue if metatag processing occurs +
Throws: +
LuaError - if this is not a number + and no LE metatag is defined.
See Also:
gteq_b(double), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq

+
+public LuaValue lteq(int rhs)
+
+
Less than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this <= rhs), FALSE if not, + or LuaValue if metatag processing occurs +
Throws: +
LuaError - if this is not a number + and no LE metatag is defined.
See Also:
gteq_b(int), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq_b

+
+public boolean lteq_b(LuaValue rhs)
+
+
Less than or equals: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this <= rhs), false if not, + and boolean interpreation of result if metatag processing occurs. +
Throws: +
LuaError - if either both operands are not a strings or both are not numbers + and no LE metatag is defined.
See Also:
gteq(LuaValue), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq_b

+
+public boolean lteq_b(int rhs)
+
+
Less than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this <= rhs), false if not, + and boolean interpreation of result if metatag processing occurs. +
Throws: +
LuaError - if this is not a number + and no LE metatag is defined.
See Also:
gteq(int), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+lteq_b

+
+public boolean lteq_b(double rhs)
+
+
Less than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this <= rhs), false if not, + and boolean interpreation of result if metatag processing occurs. +
Throws: +
LuaError - if this is not a number + and no LE metatag is defined.
See Also:
gteq(double), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt

+
+public LuaValue gt(LuaValue rhs)
+
+
Greater than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this > rhs), FALSE if not, + or LuaValue if metatag processing occurs +
Throws: +
LuaError - if either both operands are not a strings or both are not numbers + and no LE metatag is defined.
See Also:
gteq_b(LuaValue), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt

+
+public LuaValue gt(double rhs)
+
+
Greater than: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this > rhs), FALSE if not, + or LuaValue if metatag processing occurs +
Throws: +
LuaError - if this is not a number + and no LE metatag is defined.
See Also:
gteq_b(double), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt

+
+public LuaValue gt(int rhs)
+
+
Greater than: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this > rhs), FALSE if not, + or LuaValue if metatag processing occurs +
Throws: +
LuaError - if this is not a number + and no LE metatag is defined.
See Also:
gteq_b(int), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt_b

+
+public boolean gt_b(LuaValue rhs)
+
+
Greater than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this > rhs), false if not, + and boolean interpreation of result if metatag processing occurs. +
Throws: +
LuaError - if either both operands are not a strings or both are not numbers + and no LE metatag is defined.
See Also:
gteq(LuaValue), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt_b

+
+public boolean gt_b(int rhs)
+
+
Greater than: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this > rhs), false if not, + and boolean interpreation of result if metatag processing occurs. +
Throws: +
LuaError - if this is not a number + and no LE metatag is defined.
See Also:
gteq(int), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gt_b

+
+public boolean gt_b(double rhs)
+
+
Greater than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this > rhs), false if not, + and boolean interpreation of result if metatag processing occurs. +
Throws: +
LuaError - if either both operands are not a strings or both are not numbers + and no LE metatag is defined.
See Also:
gteq(LuaValue), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq

+
+public LuaValue gteq(LuaValue rhs)
+
+
Greater than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this >= rhs), FALSE if not, + or LuaValue if metatag processing occurs +
Throws: +
LuaError - if either both operands are not a strings or both are not numbers + and no LT metatag is defined.
See Also:
gteq_b(LuaValue), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq

+
+public LuaValue gteq(double rhs)
+
+
Greater than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this >= rhs), FALSE if not, + or LuaValue if metatag processing occurs +
Throws: +
LuaError - if this is not a number + and no LT metatag is defined.
See Also:
gteq_b(double), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq

+
+public LuaValue gteq(int rhs)
+
+
Greater than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
TRUE if (this >= rhs), FALSE if not, + or LuaValue if metatag processing occurs +
Throws: +
LuaError - if this is not a number + and no LT metatag is defined.
See Also:
gteq_b(int), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq_b

+
+public boolean gteq_b(LuaValue rhs)
+
+
Greater than or equals: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean. +

+ To be comparable, both operands must derive from LuaString + or both must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this >= rhs), false if not, + and boolean interpreation of result if metatag processing occurs. +
Throws: +
LuaError - if either both operands are not a strings or both are not numbers + and no LT metatag is defined.
See Also:
gteq(LuaValue), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq_b

+
+public boolean gteq_b(int rhs)
+
+
Greater than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this >= rhs), false if not, + and boolean interpreation of result if metatag processing occurs. +
Throws: +
LuaError - if this is not a number + and no LT metatag is defined.
See Also:
gteq(int), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+gteq_b

+
+public boolean gteq_b(double rhs)
+
+
Greater than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, + and returning java boolean. +

+ To be comparable, this must derive from LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Returns:
true if (this >= rhs), false if not, + and boolean interpreation of result if metatag processing occurs. +
Throws: +
LuaError - if this is not a number + and no LT metatag is defined.
See Also:
gteq(double), +comparemt(LuaValue, LuaValue)
+
+
+
+ +

+comparemt

+
+public LuaValue comparemt(LuaValue tag,
+                          LuaValue op1)
+
+
Perform metatag processing for comparison operations. +

+ Finds the supplied metatag value and invokes it, + or throws LuaError if none applies. +

+

+
Parameters:
tag - The metatag to look up
rhs - The right-hand-side value to perform the operation with +
Returns:
LuaValue resulting from metatag processing +
Throws: +
LuaError - if metatag was not defined for either operand, + or if the operands are not the same type, + or the metatag values for the two operands are different.
See Also:
gt(LuaValue), +gteq(LuaValue), +lt(LuaValue), +lteq(LuaValue)
+
+
+
+ +

+strcmp

+
+public int strcmp(LuaValue rhs)
+
+
Perform string comparison with another value + of any type + using string comparison based on byte values. +

+ Only strings can be compared, meaning + each operand must derive from LuaString. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Throws: +
LuaError - if either operand is not a string
+
+
+
+ +

+strcmp

+
+public int strcmp(LuaString rhs)
+
+
Perform string comparison with another value + known to be a LuaString + using string comparison based on byte values. +

+ Only strings can be compared, meaning + each operand must derive from LuaString. +

+

+
Parameters:
rhs - The right-hand-side value to perform the comparison with +
Throws: +
LuaError - if this is not a string
+
+
+
+ +

+concat

+
+public LuaValue concat(LuaValue rhs)
+
+
Concatenate another value onto this value and return the result + using rules of lua string concatenation including metatag processing. +

+ Only strings and numbers as represented can be concatenated, meaning + each operand must derive from LuaString or LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side value to perform the operation with +
Throws: +
LuaError - if either operand is not of an appropriate type, + such as nil or a table
+
+
+
+ +

+concatTo

+
+public LuaValue concatTo(LuaValue lhs)
+
+
Reverse-concatenation: concatenate this value onto another value + whose type is unknwon + and return the result using rules of lua string concatenation including + metatag processing. +

+ Only strings and numbers as represented can be concatenated, meaning + each operand must derive from LuaString or LuaNumber. +

+

+
Parameters:
lhs - The left-hand-side value onto which this will be concatenated +
Throws: +
LuaError - if either operand is not of an appropriate type, + such as nil or a table
See Also:
concat(LuaValue)
+
+
+
+ +

+concatTo

+
+public LuaValue concatTo(LuaNumber lhs)
+
+
Reverse-concatenation: concatenate this value onto another value + known to be a LuaNumber + and return the result using rules of lua string concatenation including + metatag processing. +

+ Only strings and numbers as represented can be concatenated, meaning + each operand must derive from LuaString or LuaNumber. +

+

+
Parameters:
lhs - The left-hand-side value onto which this will be concatenated +
Throws: +
LuaError - if either operand is not of an appropriate type, + such as nil or a table
See Also:
concat(LuaValue)
+
+
+
+ +

+concatTo

+
+public LuaValue concatTo(LuaString lhs)
+
+
Reverse-concatenation: concatenate this value onto another value + known to be a LuaString + and return the result using rules of lua string concatenation including + metatag processing. +

+ Only strings and numbers as represented can be concatenated, meaning + each operand must derive from LuaString or LuaNumber. +

+

+
Parameters:
lhs - The left-hand-side value onto which this will be concatenated +
Throws: +
LuaError - if either operand is not of an appropriate type, + such as nil or a table
See Also:
concat(LuaValue)
+
+
+
+ +

+buffer

+
+public Buffer buffer()
+
+
Convert the value to a Buffer for more efficient concatenation of + multiple strings. +

+

+ +
Returns:
Buffer instance containing the string or number
+
+
+
+ +

+concat

+
+public Buffer concat(Buffer rhs)
+
+
Concatenate a Buffer onto this value and return the result + using rules of lua string concatenation including metatag processing. +

+ Only strings and numbers as represented can be concatenated, meaning + each operand must derive from LuaString or LuaNumber. +

+

+
Parameters:
rhs - The right-hand-side Buffer to perform the operation with +
Returns:
LuaString resulting from concatenation of (this .. rhs) +
Throws: +
LuaError - if either operand is not of an appropriate type, + such as nil or a table
+
+
+
+ +

+concatmt

+
+public LuaValue concatmt(LuaValue rhs)
+
+
Perform metatag processing for concatenation operations. +

+ Finds the CONCAT metatag value and invokes it, + or throws LuaError if it doesn't exist. +

+

+
Parameters:
rhs - The right-hand-side value to perform the operation with +
Returns:
LuaValue resulting from metatag processing for CONCAT metatag. +
Throws: +
LuaError - if metatag was not defined for either operand
+
+
+
+ +

+and

+
+public LuaValue and(LuaValue rhs)
+
+
Perform boolean and with another operand, based on lua rules for boolean evaluation. + This returns either this or rhs depending on the boolean value for this. +

+

+
Parameters:
rhs - The right-hand-side value to perform the operation with +
Returns:
this if this.toboolean() is false, rhs otherwise.
+
+
+
+ +

+or

+
+public LuaValue or(LuaValue rhs)
+
+
Perform boolean or with another operand, based on lua rules for boolean evaluation. + This returns either this or rhs depending on the boolean value for this. +

+

+
Parameters:
rhs - The right-hand-side value to perform the operation with +
Returns:
this if this.toboolean() is true, rhs otherwise.
+
+
+
+ +

+testfor_b

+
+public boolean testfor_b(LuaValue limit,
+                         LuaValue step)
+
+
Perform end-condition test in for-loop processing. +

+ Used in lua-bytecode to Java-bytecode conversion. +

+

+
Parameters:
limit - the numerical limit to complete the for loop
step - the numberical step size to use. +
Returns:
true if limit has not been reached, false otherwise.
+
+
+
+ +

+strvalue

+
+public LuaString strvalue()
+
+
Convert this value to a string if it is a LuaString or LuaNumber, + or throw a LuaError if it is not +

+

+ +
Returns:
LuaString corresponding to the value if a string or number +
Throws: +
LuaError - if not a string or number
+
+
+
+ +

+strongkey

+
+public LuaValue strongkey()
+
+
Return the key part of this value if it is a weak table entry, or NIL if it was weak and is no longer referenced. +

+

+ +
Returns:
LuaValue key, or NIL if it was weak and is no longer referenced.
See Also:
WeakTable
+
+
+
+ +

+strongvalue

+
+public LuaValue strongvalue()
+
+
Return this value as a strong reference, or NIL if it was weak and is no longer referenced. +

+

+ +
Returns:
LuaValue referred to, or NIL if it was weak and is no longer referenced.
See Also:
WeakTable
+
+
+
+ +

+isweaknil

+
+public boolean isweaknil()
+
+
Test if this is a weak reference and its value no longer is referenced. +

+

+ +
Returns:
true if this is a weak reference whose value no longer is referenced
See Also:
WeakTable
+
+
+
+ +

+valueOf

+
+public static LuaBoolean valueOf(boolean b)
+
+
Convert java boolean to a LuaValue. +

+

+
Parameters:
b - boolean value to convert +
Returns:
TRUE if not or FALSE if false
+
+
+
+ +

+valueOf

+
+public static LuaInteger valueOf(int i)
+
+
Convert java int to a LuaValue. +

+

+
Parameters:
i - int value to convert +
Returns:
LuaInteger instance, possibly pooled, whose value is i
+
+
+
+ +

+valueOf

+
+public static LuaNumber valueOf(double d)
+
+
Convert java double to a LuaValue. + This may return a LuaInteger or LuaDouble depending + on the value supplied. +

+

+
Parameters:
d - double value to convert +
Returns:
LuaNumber instance, possibly pooled, whose value is d
+
+
+
+ +

+valueOf

+
+public static LuaString valueOf(java.lang.String s)
+
+
Convert java string to a LuaValue. +

+

+
Parameters:
s - String value to convert +
Returns:
LuaString instance, possibly pooled, whose value is s
+
+
+
+ +

+valueOf

+
+public static LuaString valueOf(byte[] bytes)
+
+
Convert bytes in an array to a LuaValue. +

+

+
Parameters:
bytes - byte array to convert +
Returns:
LuaString instance, possibly pooled, whose bytes are those in the supplied array
+
+
+
+ +

+valueOf

+
+public static LuaString valueOf(byte[] bytes,
+                                int off,
+                                int len)
+
+
Convert bytes in an array to a LuaValue. +

+

+
Parameters:
bytes - byte array to convert
off - offset into the byte array, starting at 0
len - number of bytes to include in the LuaString +
Returns:
LuaString instance, possibly pooled, whose bytes are those in the supplied array
+
+
+
+ +

+tableOf

+
+public static LuaTable tableOf()
+
+
Construct an empty LuaTable. +

+

+ +
Returns:
new LuaTable instance with no values and no metatable.
+
+
+
+ +

+tableOf

+
+public static LuaTable tableOf(Varargs varargs,
+                               int firstarg)
+
+
Construct a LuaTable initialized with supplied array values. +

+

+
Parameters:
varargs - Varargs containing the values to use in initialization
firstarg - the index of the first argument to use from the varargs, 1 being the first. +
Returns:
new LuaTable instance with sequential elements coming from the varargs.
+
+
+
+ +

+tableOf

+
+public static LuaTable tableOf(int narray,
+                               int nhash)
+
+
Construct an empty LuaTable preallocated to hold array and hashed elements +

+

+
Parameters:
narray - Number of array elements to preallocate
nhash - Number of hash elements to preallocate +
Returns:
new LuaTable instance with no values and no metatable, but preallocated for array and hashed elements.
+
+
+
+ +

+listOf

+
+public static LuaTable listOf(LuaValue[] unnamedValues)
+
+
Construct a LuaTable initialized with supplied array values. +

+

+
Parameters:
unnamedValues - array of LuaValue containing the values to use in initialization +
Returns:
new LuaTable instance with sequential elements coming from the array.
+
+
+
+ +

+listOf

+
+public static LuaTable listOf(LuaValue[] unnamedValues,
+                              Varargs lastarg)
+
+
Construct a LuaTable initialized with supplied array values. +

+

+
Parameters:
unnamedValues - array of LuaValue containing the first values to use in initialization
lastarg - Varargs containing additional values to use in initialization + to be put after the last unnamedValues element +
Returns:
new LuaTable instance with sequential elements coming from the array and varargs.
+
+
+
+ +

+tableOf

+
+public static LuaTable tableOf(LuaValue[] namedValues)
+
+
Construct a LuaTable initialized with supplied named values. +

+

+
Parameters:
namedValues - array of LuaValue containing the keys and values to use in initialization + in order {key-a, value-a, key-b, value-b, ...} +
Returns:
new LuaTable instance with non-sequential keys coming from the supplied array.
+
+
+
+ +

+tableOf

+
+public static LuaTable tableOf(LuaValue[] namedValues,
+                               LuaValue[] unnamedValues)
+
+
Construct a LuaTable initialized with supplied named values and sequential elements. + The named values will be assigned first, and the sequential elements will be assigned later, + possibly overwriting named values at the same slot if there are conflicts. +

+

+
Parameters:
namedValues - array of LuaValue containing the keys and values to use in initialization + in order {key-a, value-a, key-b, value-b, ...}
unnamedValues - array of LuaValue containing the sequenctial elements to use in initialization + in order {value-1, value-2, ...} , or null if there are none +
Returns:
new LuaTable instance with named and sequential values supplied.
+
+
+
+ +

+tableOf

+
+public static LuaTable tableOf(LuaValue[] namedValues,
+                               LuaValue[] unnamedValues,
+                               Varargs lastarg)
+
+
Construct a LuaTable initialized with supplied named values and sequential elements in an array part and as varargs. + The named values will be assigned first, and the sequential elements will be assigned later, + possibly overwriting named values at the same slot if there are conflicts. +

+

+
Parameters:
namedValues - array of LuaValue containing the keys and values to use in initialization + in order {key-a, value-a, key-b, value-b, ...}
unnamedValues - array of LuaValue containing the first sequenctial elements to use in initialization + in order {value-1, value-2, ...} , or null if there are none
lastarg - Varargs containing additional values to use in the sequential part of the initialization, + to be put after the last unnamedValues element +
Returns:
new LuaTable instance with named and sequential values supplied.
+
+
+
+ +

+userdataOf

+
+public static LuaUserdata userdataOf(java.lang.Object o)
+
+
Construct a LuaUserdata for an object. +

+

+
Parameters:
o - The java instance to be wrapped as userdata +
Returns:
LuaUserdata value wrapping the java instance.
+
+
+
+ +

+userdataOf

+
+public static LuaUserdata userdataOf(java.lang.Object o,
+                                     LuaValue metatable)
+
+
Construct a LuaUserdata for an object with a user supplied metatable. +

+

+
Parameters:
o - The java instance to be wrapped as userdata
metatable - The metatble to associate with the userdata instance. +
Returns:
LuaUserdata value wrapping the java instance.
+
+
+
+ +

+gettable

+
+protected static LuaValue gettable(LuaValue t,
+                                   LuaValue key)
+
+
get value from metatable operations, or NIL if not defined by metatables +

+

+
+
+
+
+ +

+settable

+
+protected static boolean settable(LuaValue t,
+                                  LuaValue key,
+                                  LuaValue value)
+
+
Perform field assignment including metatag processing. +

+

+
Parameters:
t - LuaValue on which value is being set, typically a table or something with the metatag NEWINDEX defined
key - LuaValue naming the field to assign
value - LuaValue the new value to assign to key +
Returns:
true if assignment or metatag processing succeeded, false otherwise +
Throws: +
LuaError - if there is a loop in metatag processing
+
+
+
+ +

+metatag

+
+public LuaValue metatag(LuaValue tag)
+
+
Get particular metatag, or return NIL if it doesn't exist +

+

+
Parameters:
tag - Metatag name to look up, typically a string such as + INDEX or NEWINDEX
reason - Description of error when tag lookup fails. +
Returns:
LuaValue for tag reason, or NIL
+
+
+
+ +

+checkmetatag

+
+protected LuaValue checkmetatag(LuaValue tag,
+                                java.lang.String reason)
+
+
Get particular metatag, or throw LuaError if it doesn't exist +

+

+
Parameters:
tag - Metatag name to look up, typically a string such as + INDEX or NEWINDEX
reason - Description of error when tag lookup fails. +
Returns:
LuaValue that can be called +
Throws: +
LuaError - when the lookup fails.
+
+
+
+ +

+varargsOf

+
+public static Varargs varargsOf(LuaValue[] v)
+
+
Construct a Varargs around an array of LuaValues. +

+

+
Parameters:
v - The array of LuaValues
more - Varargs contain values to include at the end +
Returns:
Varargs wrapping the supplied values.
See Also:
varargsOf(LuaValue, Varargs), +varargsOf(LuaValue[], int, int)
+
+
+
+ +

+varargsOf

+
+public static Varargs varargsOf(LuaValue[] v,
+                                Varargs r)
+
+
Construct a Varargs around an array of LuaValues. +

+

+
Parameters:
v - The array of LuaValues
more - Varargs contain values to include at the end +
Returns:
Varargs wrapping the supplied values.
See Also:
varargsOf(LuaValue[]), +varargsOf(LuaValue[], int, int, Varargs)
+
+
+
+ +

+varargsOf

+
+public static Varargs varargsOf(LuaValue[] v,
+                                int offset,
+                                int length)
+
+
Construct a Varargs around an array of LuaValues. +

+

+
Parameters:
v - The array of LuaValues
offset - number of initial values to skip in the array
length - number of values to include from the array +
Returns:
Varargs wrapping the supplied values.
See Also:
varargsOf(LuaValue[]), +varargsOf(LuaValue[], int, int, Varargs)
+
+
+
+ +

+varargsOf

+
+public static Varargs varargsOf(LuaValue[] v,
+                                int offset,
+                                int length,
+                                Varargs more)
+
+
Construct a Varargs around an array of LuaValues. +

+

+
Parameters:
v - The array of LuaValues
offset - number of initial values to skip in the array
length - number of values to include from the array
more - Varargs contain values to include at the end +
Returns:
Varargs wrapping the supplied values.
See Also:
varargsOf(LuaValue[], Varargs), +varargsOf(LuaValue[], int, int)
+
+
+
+ +

+varargsOf

+
+public static Varargs varargsOf(LuaValue v,
+                                Varargs r)
+
+
Construct a Varargs around a set of 2 or more LuaValues. +

+ This can be used to wrap exactly 2 values, or a list consisting of 1 initial value + followed by another variable list of remaining values. +

+

+
Parameters:
v1 - First LuaValue in the Varargs
v2 - LuaValue supplying the 2rd value, + or Varargss supplying all values beyond the first +
Returns:
Varargs wrapping the supplied values.
+
+
+
+ +

+varargsOf

+
+public static Varargs varargsOf(LuaValue v1,
+                                LuaValue v2,
+                                Varargs v3)
+
+
Construct a Varargs around a set of 3 or more LuaValues. +

+ This can be used to wrap exactly 3 values, or a list consisting of 2 initial values + followed by another variable list of remaining values. +

+

+
Parameters:
v1 - First LuaValue in the Varargs
v2 - Second LuaValue in the Varargs
v3 - LuaValue supplying the 3rd value, + or Varargss supplying all values beyond the second +
Returns:
Varargs wrapping the supplied values.
+
+
+
+ +

+tailcallOf

+
+public static Varargs tailcallOf(LuaValue func,
+                                 Varargs args)
+
+
Construct a TailcallVarargs around a function and arguments. +

+ The tail call is not yet called or processing until the client invokes + TailcallVarargs.eval() which performs the tail call processing. +

+ This method is typically not used directly by client code. + Instead use one of the function invocation methods. +

+

+
Parameters:
func - LuaValue to be called as a tail call
args - Varargs containing the arguments to the call +
Returns:
TailcallVarargs to be used in tailcall oprocessing.
See Also:
call(), +invoke(), +method(LuaValue), +invokemethod(LuaValue)
+
+
+
+ +

+onInvoke

+
+public Varargs onInvoke(Varargs args)
+
+
Callback used during tail call processing to invoke the function once. +

+ This may return a TailcallVarargs to be evaluated by the client. +

+ This should not be called directly, instead use on of the call invocation functions. +

+

+
Parameters:
args - the arguments to the call invocation. +
Returns:
Varargs the return values, possible a TailcallVarargs.
See Also:
call(), +invoke(), +method(LuaValue), +invokemethod(LuaValue)
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/OrphanedThread.html b/luaj-2.0.3/docs/api/org/luaj/vm2/OrphanedThread.html new file mode 100644 index 0000000000..ceb24e5330 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/OrphanedThread.html @@ -0,0 +1,256 @@ + + + + + + +OrphanedThread (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class OrphanedThread

+
+java.lang.Object
+  extended by java.lang.Throwable
+      extended by java.lang.Error
+          extended by org.luaj.vm2.OrphanedThread
+
+
+
All Implemented Interfaces:
java.io.Serializable
+
+
+
+
public class OrphanedThread
extends java.lang.Error
+ + +

+Error sublcass that indicates a lua thread that is no + longer referenced has been detected. +

+ The java thread in which this is thrown should correspond to a + LuaThread being used as a coroutine that could not possibly be + resumed again because there are no more references to the LuaThread with + which it is associated. Rather than locking up resources forever, this error + is thrown, and should fall through all the way to the thread's Thread.run() method. +

+ Java code mixed with the luaj vm should not catch this error because it may + occur when the coroutine is not running, so any processing done during error + handling could break the thread-safety of the application because other lua + processing could be going on in a different thread. +

+ +

+

+
See Also:
Serialized Form
+
+ +

+ + + + + + + + + + + +
+Constructor Summary
OrphanedThread() + +
+           
+  + + + + + + + +
+Method Summary
+ + + + + + + +
Methods inherited from class java.lang.Throwable
fillInStackTrace, getCause, getLocalizedMessage, getMessage, getStackTrace, initCause, printStackTrace, printStackTrace, printStackTrace, setStackTrace, toString
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+OrphanedThread

+
+public OrphanedThread()
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/Print.html b/luaj-2.0.3/docs/api/org/luaj/vm2/Print.html new file mode 100644 index 0000000000..830afb0363 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/Print.html @@ -0,0 +1,451 @@ + + + + + + +Print (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class Print

+
+java.lang.Object
+  extended by org.luaj.vm2.Lua
+      extended by org.luaj.vm2.Print
+
+
+
+
public class Print
extends Lua
+ + +

+Debug helper class to pretty-print lua bytecodes. +

+ +

+

+
See Also:
Prototype, +LuaClosure
+
+ +

+ + + + + + + + + + + + + + + +
+Field Summary
+static java.lang.String[]OPNAMES + +
+           
+static java.io.PrintStreamps + +
+           
+ + + + + + + +
Fields inherited from class org.luaj.vm2.Lua
_VERSION, BITRK, iABC, iABx, iAsBx, LFIELDS_PER_FLUSH, LUA_MULTRET, luaP_opmodes, MASK_A, MASK_B, MASK_Bx, MASK_C, MASK_NOT_A, MASK_NOT_B, MASK_NOT_Bx, MASK_NOT_C, MASK_NOT_OP, MASK_OP, MAX_OP, MAXARG_A, MAXARG_B, MAXARG_Bx, MAXARG_C, MAXARG_sBx, MAXINDEXRK, NO_REG, NUM_OPCODES, OP_ADD, OP_AND, OP_CALL, OP_CLOSE, OP_CLOSURE, OP_CONCAT, OP_DIV, OP_EQ, OP_FORLOOP, OP_FORPREP, OP_GE, OP_GETGLOBAL, OP_GETTABLE, OP_GETUPVAL, OP_GT, OP_JMP, OP_LE, OP_LEN, OP_LOADBOOL, OP_LOADK, OP_LOADNIL, OP_LT, OP_MOD, OP_MOVE, OP_MUL, OP_NEQ, OP_NEWTABLE, OP_NOT, OP_OR, OP_POW, OP_RETURN, OP_SELF, OP_SETGLOBAL, OP_SETLIST, OP_SETTABLE, OP_SETUPVAL, OP_SUB, OP_TAILCALL, OP_TEST, OP_TESTSET, OP_TFORLOOP, OP_UNM, OP_VARARG, OpArgK, OpArgN, OpArgR, OpArgU, POS_A, POS_B, POS_Bx, POS_C, POS_OP, SIZE_A, SIZE_B, SIZE_Bx, SIZE_C, SIZE_OP, VARARG_HASARG, VARARG_ISVARARG, VARARG_NEEDSARG
+  + + + + + + + + + + +
+Constructor Summary
Print() + +
+           
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+static voidprint(Prototype p) + +
+           
+static voidprintCode(Prototype f) + +
+          Print the code in a prototype
+static voidprintFunction(Prototype f, + boolean full) + +
+           
+static voidprintOpCode(java.io.PrintStream ps, + Prototype f, + int pc) + +
+          Print an opcode in a prototype
+static voidprintOpCode(Prototype f, + int pc) + +
+          Print an opcode in a prototype
+static voidprintState(LuaClosure cl, + int pc, + LuaValue[] stack, + int top, + Varargs varargs) + +
+          Print the state of a LuaClosure that is being executed
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Lua
GET_OPCODE, GETARG_A, GETARG_B, GETARG_Bx, GETARG_C, GETARG_sBx, getBMode, getCMode, getOpMode, INDEXK, ISK, RKASK, testAMode, testTMode
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+ps

+
+public static java.io.PrintStream ps
+
+
+
+
+
+ +

+OPNAMES

+
+public static final java.lang.String[] OPNAMES
+
+
+
+
+ + + + + + + + +
+Constructor Detail
+ +

+Print

+
+public Print()
+
+
+ + + + + + + + +
+Method Detail
+ +

+printCode

+
+public static void printCode(Prototype f)
+
+
Print the code in a prototype +

+

+
Parameters:
f - the Prototype
+
+
+
+ +

+printOpCode

+
+public static void printOpCode(Prototype f,
+                               int pc)
+
+
Print an opcode in a prototype +

+

+
Parameters:
f - the Prototype
pc - the program counter to look up and print
+
+
+
+ +

+printOpCode

+
+public static void printOpCode(java.io.PrintStream ps,
+                               Prototype f,
+                               int pc)
+
+
Print an opcode in a prototype +

+

+
Parameters:
ps - the PrintStream to print to
f - the Prototype
pc - the program counter to look up and print
+
+
+
+ +

+print

+
+public static void print(Prototype p)
+
+
+
+
+
+
+ +

+printFunction

+
+public static void printFunction(Prototype f,
+                                 boolean full)
+
+
+
+
+
+
+ +

+printState

+
+public static void printState(LuaClosure cl,
+                              int pc,
+                              LuaValue[] stack,
+                              int top,
+                              Varargs varargs)
+
+
Print the state of a LuaClosure that is being executed +

+

+
Parameters:
cl - the LuaClosure
pc - the program counter
stack - the stack of LuaValue
top - the top of the stack
varargs - any Varargs value that may apply
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/Prototype.html b/luaj-2.0.3/docs/api/org/luaj/vm2/Prototype.html new file mode 100644 index 0000000000..cd4132d423 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/Prototype.html @@ -0,0 +1,543 @@ + + + + + + +Prototype (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class Prototype

+
+java.lang.Object
+  extended by org.luaj.vm2.Prototype
+
+
+
+
public class Prototype
extends java.lang.Object
+ + +

+Prototype representing compiled lua code. +

+ This is both a straight translation of the corresponding C type, + and the main data structure for execution of compiled lua bytecode. +

+ See documentatation on LuaClosure for information on how to load + and execute a Prototype. +

+ +

+

+
See Also:
LuaClosure
+
+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Field Summary
+ int[]code + +
+           
+ intis_vararg + +
+           
+ LuaValue[]k + +
+           
+ intlastlinedefined + +
+           
+ intlinedefined + +
+           
+ int[]lineinfo + +
+           
+ LocVars[]locvars + +
+           
+ intmaxstacksize + +
+           
+ intnumparams + +
+           
+ intnups + +
+           
+ Prototype[]p + +
+           
+ LuaStringsource + +
+           
+ LuaString[]upvalues + +
+           
+  + + + + + + + + + + +
+Constructor Summary
Prototype() + +
+           
+  + + + + + + + + + + + + + + + +
+Method Summary
+ LuaStringgetlocalname(int number, + int pc) + +
+          Get the name of a local variable.
+ java.lang.StringtoString() + +
+           
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+k

+
+public LuaValue[] k
+
+
+
+
+
+ +

+code

+
+public int[] code
+
+
+
+
+
+ +

+p

+
+public Prototype[] p
+
+
+
+
+
+ +

+lineinfo

+
+public int[] lineinfo
+
+
+
+
+
+ +

+locvars

+
+public LocVars[] locvars
+
+
+
+
+
+ +

+upvalues

+
+public LuaString[] upvalues
+
+
+
+
+
+ +

+source

+
+public LuaString source
+
+
+
+
+
+ +

+nups

+
+public int nups
+
+
+
+
+
+ +

+linedefined

+
+public int linedefined
+
+
+
+
+
+ +

+lastlinedefined

+
+public int lastlinedefined
+
+
+
+
+
+ +

+numparams

+
+public int numparams
+
+
+
+
+
+ +

+is_vararg

+
+public int is_vararg
+
+
+
+
+
+ +

+maxstacksize

+
+public int maxstacksize
+
+
+
+
+ + + + + + + + +
+Constructor Detail
+ +

+Prototype

+
+public Prototype()
+
+
+ + + + + + + + +
+Method Detail
+ +

+toString

+
+public java.lang.String toString()
+
+
+
Overrides:
toString in class java.lang.Object
+
+
+
+
+
+
+ +

+getlocalname

+
+public LuaString getlocalname(int number,
+                              int pc)
+
+
Get the name of a local variable. +

+

+
Parameters:
number - the local variable number to look up
pc - the program counter +
Returns:
the name, or null if not found
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/TailcallVarargs.html b/luaj-2.0.3/docs/api/org/luaj/vm2/TailcallVarargs.html new file mode 100644 index 0000000000..c8c7c5b377 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/TailcallVarargs.html @@ -0,0 +1,416 @@ + + + + + + +TailcallVarargs (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class TailcallVarargs

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.TailcallVarargs
+
+
+
+
public class TailcallVarargs
extends Varargs
+ + +

+Subclass of Varargs that represents a lua tail call + in a Java library function execution environment. +

+ Since Java doesn't have direct support for tail calls, + any lua function whose Prototype contains the + Lua.OP_TAILCALL bytecode needs a mechanism + for tail calls when converting lua-bytecode to java-bytecode. +

+ The tail call holds the next function and arguments, + and the client a call to eval() executes the function + repeatedly until the tail calls are completed. +

+ Normally, users of luaj need not concern themselves with the + details of this mechanism, as it is built into the core + execution framework. +

+ +

+

+
See Also:
Prototype, +LuaJC
+
+ +

+ + + + + + + + + + + + + + +
+Constructor Summary
TailcallVarargs(LuaValue object, + LuaValue methodname, + Varargs args) + +
+           
TailcallVarargs(LuaValue f, + Varargs args) + +
+           
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ LuaValuearg(int i) + +
+          Get the n-th argument value (1-based).
+ LuaValuearg1() + +
+          Get the first argument in the list.
+ Varargseval() + +
+          Evaluate any pending tail call and return result.
+ booleanisTailcall() + +
+          Return true if this is a TailcallVarargs
+ intnarg() + +
+          Get the number of arguments, or 0 if there are none.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tojstring, tolong, toshort, toString, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+TailcallVarargs

+
+public TailcallVarargs(LuaValue f,
+                       Varargs args)
+
+
+
+ +

+TailcallVarargs

+
+public TailcallVarargs(LuaValue object,
+                       LuaValue methodname,
+                       Varargs args)
+
+
+ + + + + + + + +
+Method Detail
+ +

+isTailcall

+
+public boolean isTailcall()
+
+
Description copied from class: Varargs
+
Return true if this is a TailcallVarargs +

+

+
Overrides:
isTailcall in class Varargs
+
+
+ +
Returns:
true if a tail call, false otherwise
+
+
+
+ +

+eval

+
+public Varargs eval()
+
+
Description copied from class: Varargs
+
Evaluate any pending tail call and return result. +

+

+
Overrides:
eval in class Varargs
+
+
+ +
Returns:
the evaluated tail call result
+
+
+
+ +

+arg

+
+public LuaValue arg(int i)
+
+
Description copied from class: Varargs
+
Get the n-th argument value (1-based). +

+

+
Specified by:
arg in class Varargs
+
+
+
Parameters:
i - the index of the argument to get, 1 is the first argument +
Returns:
Value at position i, or LuaValue.NIL if there is none.
See Also:
Varargs.arg1(), +LuaValue.NIL
+
+
+
+ +

+arg1

+
+public LuaValue arg1()
+
+
Description copied from class: Varargs
+
Get the first argument in the list. +

+

+
Specified by:
arg1 in class Varargs
+
+
+ +
Returns:
LuaValue which is first in the list, or LuaValue.NIL if there are no values.
See Also:
Varargs.arg(int), +LuaValue.NIL
+
+
+
+ +

+narg

+
+public int narg()
+
+
Description copied from class: Varargs
+
Get the number of arguments, or 0 if there are none. +

+

+
Specified by:
narg in class Varargs
+
+
+ +
Returns:
number of arguments.
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/UpValue.html b/luaj-2.0.3/docs/api/org/luaj/vm2/UpValue.html new file mode 100644 index 0000000000..7b595fa568 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/UpValue.html @@ -0,0 +1,333 @@ + + + + + + +UpValue (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class UpValue

+
+java.lang.Object
+  extended by org.luaj.vm2.UpValue
+
+
+
+
public final class UpValue
extends java.lang.Object
+ + +

+Upvalue used with Closure formulation +

+

+ +

+

+
See Also:
LuaClosure, +Prototype
+
+ +

+ + + + + + + + + + + +
+Constructor Summary
UpValue(LuaValue[] stack, + int index) + +
+          Create an upvalue relative to a stack
+  + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ voidclose() + +
+          Close this upvalue so it is no longer on the stack
+ LuaValuegetValue() + +
+          Get the value of the upvalue
+ voidsetValue(LuaValue value) + +
+          Set the value of the upvalue
+ java.lang.Stringtojstring() + +
+          Convert this upvalue to a Java String
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+UpValue

+
+public UpValue(LuaValue[] stack,
+               int index)
+
+
Create an upvalue relative to a stack +

+

+
Parameters:
stack - the stack
index - the index on the stack for the upvalue
+
+ + + + + + + + +
+Method Detail
+ +

+tojstring

+
+public java.lang.String tojstring()
+
+
Convert this upvalue to a Java String +

+

+ +
Returns:
the Java String for this upvalue.
See Also:
LuaValue.tojstring()
+
+
+
+ +

+getValue

+
+public final LuaValue getValue()
+
+
Get the value of the upvalue +

+

+ +
Returns:
the LuaValue for this upvalue
+
+
+
+ +

+setValue

+
+public final void setValue(LuaValue value)
+
+
Set the value of the upvalue +

+

+
Parameters:
the - LuaValue to set it to
+
+
+
+ +

+close

+
+public final void close()
+
+
Close this upvalue so it is no longer on the stack +

+

+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/Varargs.html b/luaj-2.0.3/docs/api/org/luaj/vm2/Varargs.html new file mode 100644 index 0000000000..bc3a5b586f --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/Varargs.html @@ -0,0 +1,1743 @@ + + + + + + +Varargs (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class Varargs

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+
+
+
Direct Known Subclasses:
LuaValue, TailcallVarargs
+
+
+
+
public abstract class Varargs
extends java.lang.Object
+ + +

+Class to encapsulate varargs values, either as part of a variable argument list, or multiple return values. +

+ To construct varargs, use one of the static methods such as + LuaValue.varargsOf(LuaValue,LuaValue) +

+

+ Any LuaValue can be used as a stand-in for Varargs, for both calls and return values. + When doing so, nargs() will return 1 and arg1() or arg(1) will return this. + This simplifies the case when calling or implementing varargs functions with only + 1 argument or 1 return value. +

+ Varargs can also be derived from other varargs by appending to the front with a call + such as LuaValue.varargsOf(LuaValue,Varargs) + or by taking a portion of the args using Varargs.subargs(int start) +

+

+ +

+

+
See Also:
LuaValue.varargsOf(LuaValue[]), +LuaValue.varargsOf(LuaValue, Varargs), +LuaValue.varargsOf(LuaValue[], Varargs), +LuaValue.varargsOf(LuaValue, LuaValue, Varargs), +LuaValue.varargsOf(LuaValue[], int, int), +LuaValue.varargsOf(LuaValue[], int, int, Varargs), +subargs(int)
+
+ +

+ + + + + + + + + + + +
+Constructor Summary
Varargs() + +
+           
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+abstract  LuaValuearg(int i) + +
+          Get the n-th argument value (1-based).
+abstract  LuaValuearg1() + +
+          Get the first argument in the list.
+ voidargcheck(boolean test, + int i, + java.lang.String msg) + +
+          Return argument i as a LuaValue when a user-supplied assertion passes, or throw an error.
+ booleancheckboolean(int i) + +
+          Return argument i as a boolean value, or throw an error if any other type.
+ LuaClosurecheckclosure(int i) + +
+          Return argument i as a closure, or throw an error if any other type.
+ doublecheckdouble(int i) + +
+          Return argument i as a double, or throw an error if it cannot be converted to one.
+ LuaValuecheckfunction(int i) + +
+          Return argument i as a function, or throw an error if an incompatible type.
+ intcheckint(int i) + +
+          Return argument i as a java int value, discarding any fractional part, or throw an error if not a number.
+ LuaIntegercheckinteger(int i) + +
+          Return argument i as a java int value, or throw an error if not a number or is not representable by a java int.
+ java.lang.Stringcheckjstring(int i) + +
+          Return argument i as a java String if a string or number, or throw an error if any other type
+ longchecklong(int i) + +
+          Return argument i as a java long value, discarding any fractional part, or throw an error if not a number.
+ LuaValuechecknotnil(int i) + +
+          Return argument i as a LuaValue if it is not nil, or throw an error if it is nil.
+ LuaNumberchecknumber(int i) + +
+          Return argument i as a LuaNumber, or throw an error if not a number or string that can be converted to a number.
+ LuaStringcheckstring(int i) + +
+          Return argument i as a LuaString if a string or number, or throw an error if any other type
+ LuaTablechecktable(int i) + +
+          Return argument i as a LuaTable if a lua table, or throw an error if any other type.
+ LuaThreadcheckthread(int i) + +
+          Return argument i as a LuaThread if a lua thread, or throw an error if any other type.
+ java.lang.Objectcheckuserdata(int i) + +
+          Return argument i as a java Object if a userdata, or throw an error if any other type.
+ java.lang.Objectcheckuserdata(int i, + java.lang.Class c) + +
+          Return argument i as a java Object if it is a userdata whose instance Class c or a subclass, + or throw an error if any other type.
+ LuaValuecheckvalue(int i) + +
+          Return argument i as a LuaValue if it exists, or throw an error.
+ Varargseval() + +
+          Evaluate any pending tail call and return result.
+ booleanisfunction(int i) + +
+          Tests if argument i is a function.
+ booleanisnil(int i) + +
+          Tests if argument i is nil.
+ booleanisnoneornil(int i) + +
+          Return true if there is no argument or nil at argument i.
+ booleanisnumber(int i) + +
+          Tests if argument i is a number.
+ booleanisstring(int i) + +
+          Tests if argument i is a string.
+ booleanistable(int i) + +
+          Tests if argument i is a table.
+ booleanisTailcall() + +
+          Return true if this is a TailcallVarargs
+ booleanisthread(int i) + +
+          Tests if argument i is a thread.
+ booleanisuserdata(int i) + +
+          Tests if argument i is a userdata.
+ booleanisvalue(int i) + +
+          Tests if a value exists at argument i.
+abstract  intnarg() + +
+          Get the number of arguments, or 0 if there are none.
+ booleanoptboolean(int i, + boolean defval) + +
+          Return argument i as a boolean value, defval if nil, or throw a LuaError if any other type.
+ LuaClosureoptclosure(int i, + LuaClosure defval) + +
+          Return argument i as a closure, defval if nil, or throw a LuaError if any other type.
+ doubleoptdouble(int i, + double defval) + +
+          Return argument i as a double, defval if nil, or throw a LuaError if it cannot be converted to one.
+ LuaFunctionoptfunction(int i, + LuaFunction defval) + +
+          Return argument i as a function, defval if nil, or throw a LuaError if an incompatible type.
+ intoptint(int i, + int defval) + +
+          Return argument i as a java int value, discarding any fractional part, defval if nil, or throw a LuaError if not a number.
+ LuaIntegeroptinteger(int i, + LuaInteger defval) + +
+          Return argument i as a java int value, defval if nil, or throw a LuaError if not a number or is not representable by a java int.
+ java.lang.Stringoptjstring(int i, + java.lang.String defval) + +
+          Return argument i as a java String if a string or number, defval if nil, or throw a LuaError if any other type
+ longoptlong(int i, + long defval) + +
+          Return argument i as a java long value, discarding any fractional part, defval if nil, or throw a LuaError if not a number.
+ LuaNumberoptnumber(int i, + LuaNumber defval) + +
+          Return argument i as a LuaNumber, defval if nil, or throw a LuaError if not a number or string that can be converted to a number.
+ LuaStringoptstring(int i, + LuaString defval) + +
+          Return argument i as a LuaString if a string or number, defval if nil, or throw a LuaError if any other type
+ LuaTableopttable(int i, + LuaTable defval) + +
+          Return argument i as a LuaTable if a lua table, defval if nil, or throw a LuaError if any other type.
+ LuaThreadoptthread(int i, + LuaThread defval) + +
+          Return argument i as a LuaThread if a lua thread, defval if nil, or throw a LuaError if any other type.
+ java.lang.Objectoptuserdata(int i, + java.lang.Class c, + java.lang.Object defval) + +
+          Return argument i as a java Object if it is a userdata whose instance Class c or a subclass, + defval if nil, or throw a LuaError if any other type.
+ java.lang.Objectoptuserdata(int i, + java.lang.Object defval) + +
+          Return argument i as a java Object if a userdata, defval if nil, or throw a LuaError if any other type.
+ LuaValueoptvalue(int i, + LuaValue defval) + +
+          Return argument i as a LuaValue if it exists, or defval.
+ Varargssubargs(int start) + +
+          Create a Varargs instance containing arguments starting at index start
+ booleantoboolean(int i) + +
+          Convert argument i to java boolean based on lua rules for boolean evaluation.
+ bytetobyte(int i) + +
+          Return argument i as a java byte value, discarding any fractional part and truncating, + or 0 if not a number.
+ chartochar(int i) + +
+          Return argument i as a java char value, discarding any fractional part and truncating, + or 0 if not a number.
+ doubletodouble(int i) + +
+          Return argument i as a java double value or 0 if not a number.
+ floattofloat(int i) + +
+          Return argument i as a java float value, discarding excess fractional part and truncating, + or 0 if not a number.
+ inttoint(int i) + +
+          Return argument i as a java int value, discarding any fractional part and truncating, + or 0 if not a number.
+ java.lang.Stringtojstring() + +
+          Convert the list of varargs values to a human readable java String.
+ java.lang.Stringtojstring(int i) + +
+          Return argument i as a java String based on the type of the argument.
+ longtolong(int i) + +
+          Return argument i as a java long value, discarding any fractional part and truncating, + or 0 if not a number.
+ shorttoshort(int i) + +
+          Return argument i as a java short value, discarding any fractional part and truncating, + or 0 if not a number.
+ java.lang.StringtoString() + +
+          Convert the value or values to a java String using Varargs.tojstring()
+ java.lang.Objecttouserdata(int i) + +
+          Return argument i as a java Object if a userdata, or null.
+ java.lang.Objecttouserdata(int i, + java.lang.Class c) + +
+          Return argument i as a java Object if it is a userdata whose instance Class c or a subclass, or null.
+ inttype(int i) + +
+          Gets the type of argument i
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+Varargs

+
+public Varargs()
+
+
+ + + + + + + + +
+Method Detail
+ +

+arg

+
+public abstract LuaValue arg(int i)
+
+
Get the n-th argument value (1-based). +

+

+
Parameters:
i - the index of the argument to get, 1 is the first argument +
Returns:
Value at position i, or LuaValue.NIL if there is none.
See Also:
arg1(), +LuaValue.NIL
+
+
+
+ +

+narg

+
+public abstract int narg()
+
+
Get the number of arguments, or 0 if there are none. +

+

+ +
Returns:
number of arguments.
+
+
+
+ +

+arg1

+
+public abstract LuaValue arg1()
+
+
Get the first argument in the list. +

+

+ +
Returns:
LuaValue which is first in the list, or LuaValue.NIL if there are no values.
See Also:
arg(int), +LuaValue.NIL
+
+
+
+ +

+eval

+
+public Varargs eval()
+
+
Evaluate any pending tail call and return result. +

+

+ +
Returns:
the evaluated tail call result
+
+
+
+ +

+isTailcall

+
+public boolean isTailcall()
+
+
Return true if this is a TailcallVarargs +

+

+ +
Returns:
true if a tail call, false otherwise
+
+
+
+ +

+type

+
+public int type(int i)
+
+
Gets the type of argument i +

+

+
Parameters:
i - the index of the argument to convert, 1 is the first argument +
Returns:
int value corresponding to one of the LuaValue integer type values
See Also:
LuaValue.TNIL, +LuaValue.TBOOLEAN, +LuaValue.TNUMBER, +LuaValue.TSTRING, +LuaValue.TTABLE, +LuaValue.TFUNCTION, +LuaValue.TUSERDATA, +LuaValue.TTHREAD
+
+
+
+ +

+isnil

+
+public boolean isnil(int i)
+
+
Tests if argument i is nil. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
true if the argument is nil or does not exist, false otherwise
See Also:
LuaValue.TNIL
+
+
+
+ +

+isfunction

+
+public boolean isfunction(int i)
+
+
Tests if argument i is a function. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
true if the argument exists and is a function or closure, false otherwise
See Also:
LuaValue.TFUNCTION
+
+
+
+ +

+isnumber

+
+public boolean isnumber(int i)
+
+
Tests if argument i is a number. + Since anywhere a number is required, a string can be used that + is a number, this will return true for both numbers and + strings that can be interpreted as numbers. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
true if the argument exists and is a number or + string that can be interpreted as a number, false otherwise
See Also:
LuaValue.TNUMBER, +LuaValue.TSTRING
+
+
+
+ +

+isstring

+
+public boolean isstring(int i)
+
+
Tests if argument i is a string. + Since all lua numbers can be used where strings are used, + this will return true for both strings and numbers. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
true if the argument exists and is a string or number, false otherwise
See Also:
LuaValue.TNUMBER, +LuaValue.TSTRING
+
+
+
+ +

+istable

+
+public boolean istable(int i)
+
+
Tests if argument i is a table. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
true if the argument exists and is a lua table, false otherwise
See Also:
LuaValue.TTABLE
+
+
+
+ +

+isthread

+
+public boolean isthread(int i)
+
+
Tests if argument i is a thread. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
true if the argument exists and is a lua thread, false otherwise
See Also:
LuaValue.TTHREAD
+
+
+
+ +

+isuserdata

+
+public boolean isuserdata(int i)
+
+
Tests if argument i is a userdata. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
true if the argument exists and is a userdata, false otherwise
See Also:
LuaValue.TUSERDATA
+
+
+
+ +

+isvalue

+
+public boolean isvalue(int i)
+
+
Tests if a value exists at argument i. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
true if the argument exists, false otherwise
+
+
+
+ +

+optboolean

+
+public boolean optboolean(int i,
+                          boolean defval)
+
+
Return argument i as a boolean value, defval if nil, or throw a LuaError if any other type. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
true if argument i is boolean true, false if it is false, or defval if not supplied or nil +
Throws: +
LuaError - if the argument is not a lua boolean
+
+
+
+ +

+optclosure

+
+public LuaClosure optclosure(int i,
+                             LuaClosure defval)
+
+
Return argument i as a closure, defval if nil, or throw a LuaError if any other type. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
LuaClosure if argument i is a closure, or defval if not supplied or nil +
Throws: +
LuaError - if the argument is not a lua closure
+
+
+
+ +

+optdouble

+
+public double optdouble(int i,
+                        double defval)
+
+
Return argument i as a double, defval if nil, or throw a LuaError if it cannot be converted to one. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
java double value if argument i is a number or string that converts to a number, or defval if not supplied or nil +
Throws: +
LuaError - if the argument is not a number
+
+
+
+ +

+optfunction

+
+public LuaFunction optfunction(int i,
+                               LuaFunction defval)
+
+
Return argument i as a function, defval if nil, or throw a LuaError if an incompatible type. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
LuaValue that can be called if argument i is lua function or closure, or defval if not supplied or nil +
Throws: +
LuaError - if the argument is not a lua function or closure
+
+
+
+ +

+optint

+
+public int optint(int i,
+                  int defval)
+
+
Return argument i as a java int value, discarding any fractional part, defval if nil, or throw a LuaError if not a number. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
int value with fraction discarded and truncated if necessary if argument i is number, or defval if not supplied or nil +
Throws: +
LuaError - if the argument is not a number
+
+
+
+ +

+optinteger

+
+public LuaInteger optinteger(int i,
+                             LuaInteger defval)
+
+
Return argument i as a java int value, defval if nil, or throw a LuaError if not a number or is not representable by a java int. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
LuaInteger value that fits in a java int without rounding, or defval if not supplied or nil +
Throws: +
LuaError - if the argument cannot be represented by a java int value
+
+
+
+ +

+optlong

+
+public long optlong(int i,
+                    long defval)
+
+
Return argument i as a java long value, discarding any fractional part, defval if nil, or throw a LuaError if not a number. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
long value with fraction discarded and truncated if necessary if argument i is number, or defval if not supplied or nil +
Throws: +
LuaError - if the argument is not a number
+
+
+
+ +

+optnumber

+
+public LuaNumber optnumber(int i,
+                           LuaNumber defval)
+
+
Return argument i as a LuaNumber, defval if nil, or throw a LuaError if not a number or string that can be converted to a number. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument, or defval if not supplied or nil +
Returns:
LuaNumber if argument i is number or can be converted to a number +
Throws: +
LuaError - if the argument is not a number
+
+
+
+ +

+optjstring

+
+public java.lang.String optjstring(int i,
+                                   java.lang.String defval)
+
+
Return argument i as a java String if a string or number, defval if nil, or throw a LuaError if any other type +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
String value if argument i is a string or number, or defval if not supplied or nil +
Throws: +
LuaError - if the argument is not a string or number
+
+
+
+ +

+optstring

+
+public LuaString optstring(int i,
+                           LuaString defval)
+
+
Return argument i as a LuaString if a string or number, defval if nil, or throw a LuaError if any other type +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
LuaString value if argument i is a string or number, or defval if not supplied or nil +
Throws: +
LuaError - if the argument is not a string or number
+
+
+
+ +

+opttable

+
+public LuaTable opttable(int i,
+                         LuaTable defval)
+
+
Return argument i as a LuaTable if a lua table, defval if nil, or throw a LuaError if any other type. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
LuaTable value if a table, or defval if not supplied or nil +
Throws: +
LuaError - if the argument is not a lua table
+
+
+
+ +

+optthread

+
+public LuaThread optthread(int i,
+                           LuaThread defval)
+
+
Return argument i as a LuaThread if a lua thread, defval if nil, or throw a LuaError if any other type. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
LuaThread value if a thread, or defval if not supplied or nil +
Throws: +
LuaError - if the argument is not a lua thread
+
+
+
+ +

+optuserdata

+
+public java.lang.Object optuserdata(int i,
+                                    java.lang.Object defval)
+
+
Return argument i as a java Object if a userdata, defval if nil, or throw a LuaError if any other type. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
java Object value if argument i is a userdata, or defval if not supplied or nil +
Throws: +
LuaError - if the argument is not a userdata
+
+
+
+ +

+optuserdata

+
+public java.lang.Object optuserdata(int i,
+                                    java.lang.Class c,
+                                    java.lang.Object defval)
+
+
Return argument i as a java Object if it is a userdata whose instance Class c or a subclass, + defval if nil, or throw a LuaError if any other type. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument
c - the class to which the userdata instance must be assignable +
Returns:
java Object value if argument i is a userdata whose instance Class c or a subclass, or defval if not supplied or nil +
Throws: +
LuaError - if the argument is not a userdata or from whose instance c is not assignable
+
+
+
+ +

+optvalue

+
+public LuaValue optvalue(int i,
+                         LuaValue defval)
+
+
Return argument i as a LuaValue if it exists, or defval. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
LuaValue value if the argument exists, defval if not +
Throws: +
LuaError - if the argument does not exist.
+
+
+
+ +

+checkboolean

+
+public boolean checkboolean(int i)
+
+
Return argument i as a boolean value, or throw an error if any other type. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
true if argument i is boolean true, false if it is false +
Throws: +
LuaError - if the argument is not a lua boolean
+
+
+
+ +

+checkclosure

+
+public LuaClosure checkclosure(int i)
+
+
Return argument i as a closure, or throw an error if any other type. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
LuaClosure if argument i is a closure. +
Throws: +
LuaError - if the argument is not a lua closure
+
+
+
+ +

+checkdouble

+
+public double checkdouble(int i)
+
+
Return argument i as a double, or throw an error if it cannot be converted to one. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
java double value if argument i is a number or string that converts to a number +
Throws: +
LuaError - if the argument is not a number
+
+
+
+ +

+checkfunction

+
+public LuaValue checkfunction(int i)
+
+
Return argument i as a function, or throw an error if an incompatible type. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
LuaValue that can be called if argument i is lua function or closure +
Throws: +
LuaError - if the argument is not a lua function or closure
+
+
+
+ +

+checkint

+
+public int checkint(int i)
+
+
Return argument i as a java int value, discarding any fractional part, or throw an error if not a number. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
int value with fraction discarded and truncated if necessary if argument i is number +
Throws: +
LuaError - if the argument is not a number
+
+
+
+ +

+checkinteger

+
+public LuaInteger checkinteger(int i)
+
+
Return argument i as a java int value, or throw an error if not a number or is not representable by a java int. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
LuaInteger value that fits in a java int without rounding +
Throws: +
LuaError - if the argument cannot be represented by a java int value
+
+
+
+ +

+checklong

+
+public long checklong(int i)
+
+
Return argument i as a java long value, discarding any fractional part, or throw an error if not a number. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
long value with fraction discarded and truncated if necessary if argument i is number +
Throws: +
LuaError - if the argument is not a number
+
+
+
+ +

+checknumber

+
+public LuaNumber checknumber(int i)
+
+
Return argument i as a LuaNumber, or throw an error if not a number or string that can be converted to a number. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
LuaNumber if argument i is number or can be converted to a number +
Throws: +
LuaError - if the argument is not a number
+
+
+
+ +

+checkjstring

+
+public java.lang.String checkjstring(int i)
+
+
Return argument i as a java String if a string or number, or throw an error if any other type +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
String value if argument i is a string or number +
Throws: +
LuaError - if the argument is not a string or number
+
+
+
+ +

+checkstring

+
+public LuaString checkstring(int i)
+
+
Return argument i as a LuaString if a string or number, or throw an error if any other type +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
LuaString value if argument i is a string or number +
Throws: +
LuaError - if the argument is not a string or number
+
+
+
+ +

+checktable

+
+public LuaTable checktable(int i)
+
+
Return argument i as a LuaTable if a lua table, or throw an error if any other type. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
LuaTable value if a table +
Throws: +
LuaError - if the argument is not a lua table
+
+
+
+ +

+checkthread

+
+public LuaThread checkthread(int i)
+
+
Return argument i as a LuaThread if a lua thread, or throw an error if any other type. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
LuaThread value if a thread +
Throws: +
LuaError - if the argument is not a lua thread
+
+
+
+ +

+checkuserdata

+
+public java.lang.Object checkuserdata(int i)
+
+
Return argument i as a java Object if a userdata, or throw an error if any other type. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
java Object value if argument i is a userdata +
Throws: +
LuaError - if the argument is not a userdata
+
+
+
+ +

+checkuserdata

+
+public java.lang.Object checkuserdata(int i,
+                                      java.lang.Class c)
+
+
Return argument i as a java Object if it is a userdata whose instance Class c or a subclass, + or throw an error if any other type. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument
c - the class to which the userdata instance must be assignable +
Returns:
java Object value if argument i is a userdata whose instance Class c or a subclass +
Throws: +
LuaError - if the argument is not a userdata or from whose instance c is not assignable
+
+
+
+ +

+checkvalue

+
+public LuaValue checkvalue(int i)
+
+
Return argument i as a LuaValue if it exists, or throw an error. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
LuaValue value if the argument exists +
Throws: +
LuaError - if the argument does not exist.
+
+
+
+ +

+checknotnil

+
+public LuaValue checknotnil(int i)
+
+
Return argument i as a LuaValue if it is not nil, or throw an error if it is nil. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
LuaValue value if the argument is not nil +
Throws: +
LuaError - if the argument doesn't exist or evaluates to nil.
+
+
+
+ +

+argcheck

+
+public void argcheck(boolean test,
+                     int i,
+                     java.lang.String msg)
+
+
Return argument i as a LuaValue when a user-supplied assertion passes, or throw an error. +

+

+
Parameters:
test - user supplied assertion to test against
i - the index to report in any error message
msg - the error message to use when the test fails +
Throws: +
LuaError - if the the value of test is false
+
+
+
+ +

+isnoneornil

+
+public boolean isnoneornil(int i)
+
+
Return true if there is no argument or nil at argument i. +

+

+
Parameters:
i - the index of the argument to test, 1 is the first argument +
Returns:
true if argument i contains either no argument or nil
+
+
+
+ +

+toboolean

+
+public boolean toboolean(int i)
+
+
Convert argument i to java boolean based on lua rules for boolean evaluation. +

+

+
Parameters:
i - the index of the argument to convert, 1 is the first argument +
Returns:
false if argument i is nil or false, otherwise true
+
+
+
+ +

+tobyte

+
+public byte tobyte(int i)
+
+
Return argument i as a java byte value, discarding any fractional part and truncating, + or 0 if not a number. +

+

+
Parameters:
i - the index of the argument to convert, 1 is the first argument +
Returns:
byte value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
+
+
+
+ +

+tochar

+
+public char tochar(int i)
+
+
Return argument i as a java char value, discarding any fractional part and truncating, + or 0 if not a number. +

+

+
Parameters:
i - the index of the argument to convert, 1 is the first argument +
Returns:
char value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
+
+
+
+ +

+todouble

+
+public double todouble(int i)
+
+
Return argument i as a java double value or 0 if not a number. +

+

+
Parameters:
i - the index of the argument to convert, 1 is the first argument +
Returns:
double value if argument i is number, otherwise 0
+
+
+
+ +

+tofloat

+
+public float tofloat(int i)
+
+
Return argument i as a java float value, discarding excess fractional part and truncating, + or 0 if not a number. +

+

+
Parameters:
i - the index of the argument to convert, 1 is the first argument +
Returns:
float value with excess fraction discarded and truncated if necessary if argument i is number, otherwise 0
+
+
+
+ +

+toint

+
+public int toint(int i)
+
+
Return argument i as a java int value, discarding any fractional part and truncating, + or 0 if not a number. +

+

+
Parameters:
i - the index of the argument to convert, 1 is the first argument +
Returns:
int value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
+
+
+
+ +

+tolong

+
+public long tolong(int i)
+
+
Return argument i as a java long value, discarding any fractional part and truncating, + or 0 if not a number. +

+

+
Parameters:
i - the index of the argument to convert, 1 is the first argument +
Returns:
long value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
+
+
+
+ +

+tojstring

+
+public java.lang.String tojstring(int i)
+
+
Return argument i as a java String based on the type of the argument. +

+

+
Parameters:
i - the index of the argument to convert, 1 is the first argument +
Returns:
String value representing the type
+
+
+
+ +

+toshort

+
+public short toshort(int i)
+
+
Return argument i as a java short value, discarding any fractional part and truncating, + or 0 if not a number. +

+

+
Parameters:
i - the index of the argument to convert, 1 is the first argument +
Returns:
short value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
+
+
+
+ +

+touserdata

+
+public java.lang.Object touserdata(int i)
+
+
Return argument i as a java Object if a userdata, or null. +

+

+
Parameters:
i - the index of the argument to convert, 1 is the first argument +
Returns:
java Object value if argument i is a userdata, otherwise null
+
+
+
+ +

+touserdata

+
+public java.lang.Object touserdata(int i,
+                                   java.lang.Class c)
+
+
Return argument i as a java Object if it is a userdata whose instance Class c or a subclass, or null. +

+

+
Parameters:
i - the index of the argument to convert, 1 is the first argument
c - the class to which the userdata instance must be assignable +
Returns:
java Object value if argument i is a userdata whose instance Class c or a subclass, otherwise null
+
+
+
+ +

+tojstring

+
+public java.lang.String tojstring()
+
+
Convert the list of varargs values to a human readable java String. +

+

+ +
Returns:
String value in human readable form such as {1,2}.
+
+
+
+ +

+toString

+
+public java.lang.String toString()
+
+
Convert the value or values to a java String using Varargs.tojstring() +

+

+
Overrides:
toString in class java.lang.Object
+
+
+ +
Returns:
String value in human readable form.
See Also:
tojstring()
+
+
+
+ +

+subargs

+
+public Varargs subargs(int start)
+
+
Create a Varargs instance containing arguments starting at index start +

+

+
Parameters:
start - the index from which to include arguments, where 1 is the first argument. +
Returns:
Varargs containing argument { start, start+1, ... , narg-start-1 }
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/WeakTable.html b/luaj-2.0.3/docs/api/org/luaj/vm2/WeakTable.html new file mode 100644 index 0000000000..6077686915 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/WeakTable.html @@ -0,0 +1,733 @@ + + + + + + +WeakTable (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2 +
+Class WeakTable

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaTable
+              extended by org.luaj.vm2.WeakTable
+
+
+
+
public class WeakTable
extends LuaTable
+ + +

+Subclass of LuaTable that provides weak key and weak value semantics. +

+ Normally these are not created directly, but indirectly when changing the mode + of a LuaTable as lua script executes. +

+ However, calling the constructors directly when weak tables are required from + Java will reduce overhead. +

+ +

+


+ +

+ + + + + + + +
+Field Summary
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaTable
array, hashEntries, hashKeys, hashValues, m_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + + + + + + + + + + +
+Constructor Summary
+ WeakTable(boolean weakkeys, + boolean weakvalues) + +
+          Construct a table with weak keys, weak values, or both
+protected WeakTable(boolean weakkeys, + boolean weakvalues, + int narray, + int nhash) + +
+          Construct a table with weak keys, weak values, or both, and an initial capacity
+protected WeakTable(boolean weakkeys, + boolean weakvalues, + LuaTable source) + +
+          Construct a table with weak keys, weak values, or both, and a source of initial data
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+protected  LuaTablechangemode(boolean weakkeys, + boolean weakvalues) + +
+          Change the mode of a table
+protected  intgetArrayLength() + +
+          Get the length of the array part of the table.
+protected  intgetHashLength() + +
+          Get the length of the hash part of the table.
+ inthashFindSlot(LuaValue key) + +
+          Find the hashtable slot to use
+protected  LuaValuehashget(LuaValue key) + +
+          Get the hash value for a key + key the key to look up
+ intmaxn() + +
+          Return table.maxn() as defined by lua 5.0.
+ Varargsnext(LuaValue key) + +
+          Get the next element after a particular key in the table
+ voidpresize(int narray) + +
+          Preallocate the array part of a table to be a certain size,
+ voidpresize(int narray, + int nhash) + +
+          Presize capacity of both array and hash parts.
+ LuaValuerawget(int key) + +
+          Get a value in a table without metatag processing.
+ LuaValuerawget(LuaValue key) + +
+          Get a value in a table without metatag processing.
+ voidrawset(int key, + LuaValue value) + +
+          Set a value in a table without metatag processing.
+ voidrawset(LuaValue key, + LuaValue value) + +
+          caller must ensure key is not nil
+ voidsort(LuaValue comparator) + +
+          Sort the table using a comparator.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaTable
checktable, concat, eq_b, eq, foreach, foreachi, get, get, getmetatable, getn, hashClearSlot, hashset, inext, insert, istable, keyCount, keys, len, length, opttable, remove, set, set, setmetatable, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, call, call, call, call, callmt, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eqmtcall, equals, error, get, getfenv, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, invoke, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isfunction, isint, isinttype, islong, isnil, isnumber, isstring, isthread, isuserdata, isuserdata, isweaknil, lenerror, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, not, onInvoke, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, raweq, raweq, raweq, raweq, raweq, rawget, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, setfenv, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+WeakTable

+
+public WeakTable(boolean weakkeys,
+                 boolean weakvalues)
+
+
Construct a table with weak keys, weak values, or both +

+

+
Parameters:
weakkeys - true to let the table have weak keys
weakvalues - true to let the table have weak values
+
+
+ +

+WeakTable

+
+protected WeakTable(boolean weakkeys,
+                    boolean weakvalues,
+                    int narray,
+                    int nhash)
+
+
Construct a table with weak keys, weak values, or both, and an initial capacity +

+

+
Parameters:
weakkeys - true to let the table have weak keys
weakvalues - true to let the table have weak values
narray - capacity of array part
nhash - capacity of hash part
+
+
+ +

+WeakTable

+
+protected WeakTable(boolean weakkeys,
+                    boolean weakvalues,
+                    LuaTable source)
+
+
Construct a table with weak keys, weak values, or both, and a source of initial data +

+

+
Parameters:
weakkeys - true to let the table have weak keys
weakvalues - true to let the table have weak values
source - LuaTable containing the initial elements
+
+ + + + + + + + +
+Method Detail
+ +

+presize

+
+public void presize(int narray)
+
+
Description copied from class: LuaValue
+
Preallocate the array part of a table to be a certain size, +

+ Primarily used internally in response to a SETLIST bytecode. +

+

+
Overrides:
presize in class LuaTable
+
+
+
Parameters:
narray - the number of array slots to preallocate in the table.
+
+
+
+ +

+presize

+
+public void presize(int narray,
+                    int nhash)
+
+
Presize capacity of both array and hash parts. +

+

+
Overrides:
presize in class LuaTable
+
+
+
Parameters:
narray - capacity of array part
nhash - capacity of hash part
+
+
+
+ +

+getArrayLength

+
+protected int getArrayLength()
+
+
Description copied from class: LuaTable
+
Get the length of the array part of the table. +

+

+
Overrides:
getArrayLength in class LuaTable
+
+
+ +
Returns:
length of the array part, does not relate to count of objects in the table.
+
+
+
+ +

+getHashLength

+
+protected int getHashLength()
+
+
Description copied from class: LuaTable
+
Get the length of the hash part of the table. +

+

+
Overrides:
getHashLength in class LuaTable
+
+
+ +
Returns:
length of the hash part, does not relate to count of objects in the table.
+
+
+
+ +

+changemode

+
+protected LuaTable changemode(boolean weakkeys,
+                              boolean weakvalues)
+
+
Description copied from class: LuaTable
+
Change the mode of a table +

+

+
Overrides:
changemode in class LuaTable
+
+
+
Parameters:
weakkeys - true to make the table have weak keys going forward
weakvalues - true to make the table have weak values going forward +
Returns:
this or a new WeakTable if the mode change requires copying.
+
+
+
+ +

+rawset

+
+public void rawset(int key,
+                   LuaValue value)
+
+
Description copied from class: LuaValue
+
Set a value in a table without metatag processing. +

+

+
Overrides:
rawset in class LuaTable
+
+
+
Parameters:
key - the key to use
value - the value to use, can be NIL, must not be null
+
+
+
+ +

+rawset

+
+public void rawset(LuaValue key,
+                   LuaValue value)
+
+
Description copied from class: LuaTable
+
caller must ensure key is not nil +

+

+
Overrides:
rawset in class LuaTable
+
+
+
Parameters:
key - the key to use, must not be NIL or null
value - the value to use, can be NIL, must not be null
+
+
+
+ +

+rawget

+
+public LuaValue rawget(int key)
+
+
Description copied from class: LuaValue
+
Get a value in a table without metatag processing. +

+

+
Overrides:
rawget in class LuaTable
+
+
+
Parameters:
key - the key to look up +
Returns:
LuaValue for that key, or NIL if not found
+
+
+
+ +

+rawget

+
+public LuaValue rawget(LuaValue key)
+
+
Description copied from class: LuaValue
+
Get a value in a table without metatag processing. +

+

+
Overrides:
rawget in class LuaTable
+
+
+
Parameters:
key - the key to look up, must not be NIL or null +
Returns:
LuaValue for that key, or NIL if not found
+
+
+
+ +

+hashget

+
+protected LuaValue hashget(LuaValue key)
+
+
Get the hash value for a key + key the key to look up +

+

+
Overrides:
hashget in class LuaTable
+
+
+
+
+
+
+ +

+hashFindSlot

+
+public int hashFindSlot(LuaValue key)
+
+
Description copied from class: LuaTable
+
Find the hashtable slot to use +

+

+
Overrides:
hashFindSlot in class LuaTable
+
+
+
Parameters:
key - key to look for +
Returns:
slot to use
+
+
+
+ +

+maxn

+
+public int maxn()
+
+
Description copied from class: LuaTable
+
Return table.maxn() as defined by lua 5.0. +

+ Provided for compatibility, not a scalable operation. +

+

+
Overrides:
maxn in class LuaTable
+
+
+ +
Returns:
value for maxn
+
+
+
+ +

+next

+
+public Varargs next(LuaValue key)
+
+
Get the next element after a particular key in the table +

+

+
Overrides:
next in class LuaTable
+
+
+
Parameters:
key - LuaInteger value identifying a key to start from, + or NIL to start at the beginning +
Returns:
key,value or nil
See Also:
LuaTable, +#inext(), +LuaValue.valueOf(int), +Varargs.arg1(), +Varargs.arg(int), +LuaValue.isnil()
+
+
+
+ +

+sort

+
+public void sort(LuaValue comparator)
+
+
Description copied from class: LuaTable
+
Sort the table using a comparator. +

+

+
Overrides:
sort in class LuaTable
+
+
+
Parameters:
comparator - LuaValue to be called to compare elements.
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/Buffer.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/Buffer.html new file mode 100644 index 0000000000..a2839392e1 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/Buffer.html @@ -0,0 +1,311 @@ + + + + + + +Uses of Class org.luaj.vm2.Buffer (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.Buffer

+
+ + + + + + + + + +
+Packages that use Buffer
org.luaj.vm2  
+  +

+ + + + + +
+Uses of Buffer in org.luaj.vm2
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 that return Buffer
+ BufferBuffer.append(byte b) + +
+          Append a single byte to the buffer.
+ BufferBuffer.append(LuaString str) + +
+          Append a LuaString to the buffer.
+ BufferBuffer.append(LuaValue val) + +
+          Append a LuaValue to the buffer.
+ BufferBuffer.append(java.lang.String str) + +
+          Append a Java String to the buffer.
+ BufferLuaValue.buffer() + +
+          Convert the value to a Buffer for more efficient concatenation of + multiple strings.
+ BufferLuaNumber.concat(Buffer rhs) + +
+           
+ BufferLuaString.concat(Buffer rhs) + +
+           
+ BufferLuaValue.concat(Buffer rhs) + +
+          Concatenate a Buffer onto this value and return the result + using rules of lua string concatenation including metatag processing.
+ BufferBuffer.concatTo(LuaNumber lhs) + +
+          Concatenate this buffer onto a LuaNumber
+ BufferBuffer.concatTo(LuaString lhs) + +
+          Concatenate this buffer onto a LuaString
+ BufferBuffer.concatTo(LuaValue lhs) + +
+          Concatenate this buffer onto a LuaValue
+ BufferBuffer.prepend(LuaString s) + +
+          Concatenate bytes from a LuaString onto the front of this buffer
+ BufferBuffer.setvalue(LuaValue value) + +
+          Set buffer contents as a LuaValue
+  +

+ + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 with parameters of type Buffer
+ BufferLuaNumber.concat(Buffer rhs) + +
+           
+ BufferLuaString.concat(Buffer rhs) + +
+           
+ BufferLuaValue.concat(Buffer rhs) + +
+          Concatenate a Buffer onto this value and return the result + using rules of lua string concatenation including metatag processing.
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LoadState.LuaCompiler.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LoadState.LuaCompiler.html new file mode 100644 index 0000000000..9546b35cbe --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LoadState.LuaCompiler.html @@ -0,0 +1,239 @@ + + + + + + +Uses of Interface org.luaj.vm2.LoadState.LuaCompiler (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Interface
org.luaj.vm2.LoadState.LuaCompiler

+
+ + + + + + + + + + + + + + + + + +
+Packages that use LoadState.LuaCompiler
org.luaj.vm2  
org.luaj.vm2.compiler  
org.luaj.vm2.luajc  
+  +

+ + + + + +
+Uses of LoadState.LuaCompiler in org.luaj.vm2
+  +

+ + + + + + + + + +
Fields in org.luaj.vm2 declared as LoadState.LuaCompiler
+static LoadState.LuaCompilerLoadState.compiler + +
+          Compiler instance, if installed
+  +

+ + + + + +
+Uses of LoadState.LuaCompiler in org.luaj.vm2.compiler
+  +

+ + + + + + + + + +
Classes in org.luaj.vm2.compiler that implement LoadState.LuaCompiler
+ classLuaC + +
+          Compiler for Lua.
+  +

+ + + + + +
+Uses of LoadState.LuaCompiler in org.luaj.vm2.luajc
+  +

+ + + + + + + + + +
Classes in org.luaj.vm2.luajc that implement LoadState.LuaCompiler
+ classLuaJC + +
+          Implementation of LoadState.LuaCompiler which does direct + lua-to-java-bytecode compiling.
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LoadState.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LoadState.html new file mode 100644 index 0000000000..15fd443d30 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LoadState.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.LoadState (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.LoadState

+
+No usage of org.luaj.vm2.LoadState +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LocVars.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LocVars.html new file mode 100644 index 0000000000..0e74db19f9 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LocVars.html @@ -0,0 +1,180 @@ + + + + + + +Uses of Class org.luaj.vm2.LocVars (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.LocVars

+
+ + + + + + + + + +
+Packages that use LocVars
org.luaj.vm2  
+  +

+ + + + + +
+Uses of LocVars in org.luaj.vm2
+  +

+ + + + + + + + + +
Fields in org.luaj.vm2 declared as LocVars
+ LocVars[]Prototype.locvars + +
+           
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/Lua.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/Lua.html new file mode 100644 index 0000000000..67bcb52730 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/Lua.html @@ -0,0 +1,209 @@ + + + + + + +Uses of Class org.luaj.vm2.Lua (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.Lua

+
+ + + + + + + + + + + + + +
+Packages that use Lua
org.luaj.vm2  
org.luaj.vm2.compiler  
+  +

+ + + + + +
+Uses of Lua in org.luaj.vm2
+  +

+ + + + + + + + + +
Subclasses of Lua in org.luaj.vm2
+ classPrint + +
+          Debug helper class to pretty-print lua bytecodes.
+  +

+ + + + + +
+Uses of Lua in org.luaj.vm2.compiler
+  +

+ + + + + + + + + +
Subclasses of Lua in org.luaj.vm2.compiler
+ classLuaC + +
+          Compiler for Lua.
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaBoolean.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaBoolean.html new file mode 100644 index 0000000000..38046045f4 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaBoolean.html @@ -0,0 +1,204 @@ + + + + + + +Uses of Class org.luaj.vm2.LuaBoolean (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.LuaBoolean

+
+ + + + + + + + + +
+Packages that use LuaBoolean
org.luaj.vm2  
+  +

+ + + + + +
+Uses of LuaBoolean in org.luaj.vm2
+  +

+ + + + + + + + + + + + + +
Fields in org.luaj.vm2 declared as LuaBoolean
+static LuaBooleanLuaValue.FALSE + +
+          LuaBoolean constant corresponding to lua false
+static LuaBooleanLuaValue.TRUE + +
+          LuaBoolean constant corresponding to lua true
+  +

+ + + + + + + + + +
Methods in org.luaj.vm2 that return LuaBoolean
+static LuaBooleanLuaValue.valueOf(boolean b) + +
+          Convert java boolean to a LuaValue.
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaClosure.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaClosure.html new file mode 100644 index 0000000000..9c334fb4a1 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaClosure.html @@ -0,0 +1,283 @@ + + + + + + +Uses of Class org.luaj.vm2.LuaClosure (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.LuaClosure

+
+ + + + + + + + + +
+Packages that use LuaClosure
org.luaj.vm2  
+  +

+ + + + + +
+Uses of LuaClosure in org.luaj.vm2
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 that return LuaClosure
+ LuaClosureLuaClosure.checkclosure() + +
+           
+ LuaClosureLuaValue.checkclosure() + +
+          Check that the value is a LuaClosure , + or throw LuaError if not
+ LuaClosureVarargs.checkclosure(int i) + +
+          Return argument i as a closure, or throw an error if any other type.
+ LuaClosureVarargs.optclosure(int i, + LuaClosure defval) + +
+          Return argument i as a closure, defval if nil, or throw a LuaError if any other type.
+ LuaClosureLuaClosure.optclosure(LuaClosure defval) + +
+           
+ LuaClosureLuaNil.optclosure(LuaClosure defval) + +
+           
+ LuaClosureLuaValue.optclosure(LuaClosure defval) + +
+          Check that optional argument is a closure and return as LuaClosure
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 with parameters of type LuaClosure
+ LuaClosureVarargs.optclosure(int i, + LuaClosure defval) + +
+          Return argument i as a closure, defval if nil, or throw a LuaError if any other type.
+ LuaClosureLuaClosure.optclosure(LuaClosure defval) + +
+           
+ LuaClosureLuaNil.optclosure(LuaClosure defval) + +
+           
+ LuaClosureLuaValue.optclosure(LuaClosure defval) + +
+          Check that optional argument is a closure and return as LuaClosure
+static voidPrint.printState(LuaClosure cl, + int pc, + LuaValue[] stack, + int top, + Varargs varargs) + +
+          Print the state of a LuaClosure that is being executed
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaDouble.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaDouble.html new file mode 100644 index 0000000000..5b6c715fee --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaDouble.html @@ -0,0 +1,196 @@ + + + + + + +Uses of Class org.luaj.vm2.LuaDouble (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.LuaDouble

+
+ + + + + + + + + +
+Packages that use LuaDouble
org.luaj.vm2  
+  +

+ + + + + +
+Uses of LuaDouble in org.luaj.vm2
+  +

+ + + + + + + + + + + + + + + + + +
Fields in org.luaj.vm2 declared as LuaDouble
+static LuaDoubleLuaDouble.NAN + +
+          Constant LuaDouble representing NaN (not a number)
+static LuaDoubleLuaDouble.NEGINF + +
+          Constant LuaDouble representing negative infinity
+static LuaDoubleLuaDouble.POSINF + +
+          Constant LuaDouble representing positive infinity
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaError.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaError.html new file mode 100644 index 0000000000..544b73db77 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaError.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.LuaError (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.LuaError

+
+No usage of org.luaj.vm2.LuaError +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaFunction.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaFunction.html new file mode 100644 index 0000000000..81557ff932 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaFunction.html @@ -0,0 +1,651 @@ + + + + + + +Uses of Class org.luaj.vm2.LuaFunction (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.LuaFunction

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Packages that use LuaFunction
org.luaj.vm2  
org.luaj.vm2.compiler  
org.luaj.vm2.lib  
org.luaj.vm2.lib.jme  
org.luaj.vm2.lib.jse  
org.luaj.vm2.luajc  
+  +

+ + + + + +
+Uses of LuaFunction in org.luaj.vm2
+  +

+ + + + + + + + + +
Subclasses of LuaFunction in org.luaj.vm2
+ classLuaClosure + +
+          Extension of LuaFunction which executes lua bytecode.
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 that return LuaFunction
+static LuaFunctionLuaThread.getCallstackFunction(int level) + +
+          Get the function called as a specific location on the stack.
+static LuaFunctionLoadState.load(java.io.InputStream stream, + java.lang.String name, + LuaValue env) + +
+          Load lua in either binary or text form from an input stream.
+ LuaFunctionLoadState.LuaCompiler.load(java.io.InputStream stream, + java.lang.String filename, + LuaValue env) + +
+          Load into a Closure or LuaFunction from a Stream and initializes the environment
+ LuaFunctionVarargs.optfunction(int i, + LuaFunction defval) + +
+          Return argument i as a function, defval if nil, or throw a LuaError if an incompatible type.
+ LuaFunctionLuaFunction.optfunction(LuaFunction defval) + +
+           
+ LuaFunctionLuaNil.optfunction(LuaFunction defval) + +
+           
+ LuaFunctionLuaValue.optfunction(LuaFunction defval) + +
+          Check that optional argument is a function and return as LuaFunction
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 with parameters of type LuaFunction
+static LuaThread.CallStackLuaThread.onCall(LuaFunction function) + +
+          Callback used at the beginning of a call to prepare for possible getfenv/setfenv calls
+ LuaFunctionVarargs.optfunction(int i, + LuaFunction defval) + +
+          Return argument i as a function, defval if nil, or throw a LuaError if an incompatible type.
+ LuaFunctionLuaFunction.optfunction(LuaFunction defval) + +
+           
+ LuaFunctionLuaNil.optfunction(LuaFunction defval) + +
+           
+ LuaFunctionLuaValue.optfunction(LuaFunction defval) + +
+          Check that optional argument is a function and return as LuaFunction
+  +

+ + + + + +
+Uses of LuaFunction in org.luaj.vm2.compiler
+  +

+ + + + + + + + + + + + + +
Methods in org.luaj.vm2.compiler that return LuaFunction
+ LuaFunctionLuaC.load(java.io.InputStream stream, + java.lang.String name, + LuaValue env) + +
+          Load into a Closure or LuaFunction, with the supplied initial environment
+ LuaFunctionLuaC.load(Prototype p, + java.lang.String filename, + LuaValue env) + +
+           
+  +

+ + + + + +
+Uses of LuaFunction in org.luaj.vm2.lib
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Subclasses of LuaFunction in org.luaj.vm2.lib
+ classBaseLib + +
+          Subclass of LibFunction which implements the lua basic library functions.
+ classCoroutineLib + +
+          Subclass of LibFunction which implements the lua standard coroutine + library.
+ classDebugLib + +
+          Subclass of LibFunction which implements the lua standard debug + library.
+ classIoLib + +
+          Abstract base class extending LibFunction which implements the + core of the lua standard io library.
+ classLibFunction + +
+          Subclass of LuaFunction common to Java functions exposed to lua.
+ classMathLib + +
+          Subclass of LibFunction which implements the lua standard math + library.
+ classOneArgFunction + +
+          Abstract base class for Java function implementations that take one argument and + return one value.
+ classOsLib + +
+          Subclass of LibFunction which implements the standard lua os library.
+ classPackageLib + +
+          Subclass of LibFunction which implements the lua standard package and module + library functions.
+ classStringLib + +
+          Subclass of LibFunction which implements the lua standard string + library.
+ classTableLib + +
+          Subclass of LibFunction which implements the lua standard table + library.
+ classThreeArgFunction + +
+          Abstract base class for Java function implementations that take two arguments and + return one value.
+ classTwoArgFunction + +
+          Abstract base class for Java function implementations that take two arguments and + return one value.
+ classVarArgFunction + +
+          Abstract base class for Java function implementations that takes varaiable arguments and + returns multiple return values.
+ classZeroArgFunction + +
+          Abstract base class for Java function implementations that take no arguments and + return one value.
+  +

+ + + + + + + + + +
Methods in org.luaj.vm2.lib with parameters of type LuaFunction
+static voidDebugLib.debugOnCall(LuaThread thread, + int calls, + LuaFunction func) + +
+          Called by Closures and recursing java functions on entry
+  +

+ + + + + +
+Uses of LuaFunction in org.luaj.vm2.lib.jme
+  +

+ + + + + + + + + +
Subclasses of LuaFunction in org.luaj.vm2.lib.jme
+ classJmeIoLib + +
+          Subclass of IoLib and therefore LibFunction which implements the lua standard io + library for the JSE platform.
+  +

+ + + + + +
+Uses of LuaFunction in org.luaj.vm2.lib.jse
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Subclasses of LuaFunction in org.luaj.vm2.lib.jse
+ classJseBaseLib + +
+          Subclass of BaseLib and LibFunction which implements the lua basic library functions + and provides a directory based ResourceFinder as the BaseLib.FINDER.
+ classJseIoLib + +
+          Subclass of IoLib and therefore LibFunction which implements the lua standard io + library for the JSE platform.
+ classJseMathLib + +
+          Subclass of LibFunction which implements the lua standard math + library.
+static classJseMathLib.JseMathLib1 + +
+           
+static classJseMathLib.JseMathLib2 + +
+           
+ classJseOsLib + +
+          Subclass of LibFunction which implements the standard lua os library.
+ classLuajavaLib + +
+          Subclass of LibFunction which implements the features of the luajava package.
+  +

+ + + + + +
+Uses of LuaFunction in org.luaj.vm2.luajc
+  +

+ + + + + + + + + +
Methods in org.luaj.vm2.luajc that return LuaFunction
+ LuaFunctionLuaJC.load(java.io.InputStream stream, + java.lang.String name, + LuaValue env) + +
+           
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaInteger.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaInteger.html new file mode 100644 index 0000000000..4db91e4ef7 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaInteger.html @@ -0,0 +1,334 @@ + + + + + + +Uses of Class org.luaj.vm2.LuaInteger (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.LuaInteger

+
+ + + + + + + + + +
+Packages that use LuaInteger
org.luaj.vm2  
+  +

+ + + + + +
+Uses of LuaInteger in org.luaj.vm2
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 that return LuaInteger
+ LuaIntegerLuaDouble.checkinteger() + +
+           
+ LuaIntegerLuaInteger.checkinteger() + +
+           
+ LuaIntegerLuaString.checkinteger() + +
+           
+ LuaIntegerLuaValue.checkinteger() + +
+          Check that the value is numeric, and convert and cast value to int, or throw LuaError if not numeric
+ LuaIntegerVarargs.checkinteger(int i) + +
+          Return argument i as a java int value, or throw an error if not a number or is not representable by a java int.
+ LuaIntegerVarargs.optinteger(int i, + LuaInteger defval) + +
+          Return argument i as a java int value, defval if nil, or throw a LuaError if not a number or is not representable by a java int.
+ LuaIntegerLuaDouble.optinteger(LuaInteger defval) + +
+           
+ LuaIntegerLuaInteger.optinteger(LuaInteger defval) + +
+           
+ LuaIntegerLuaNil.optinteger(LuaInteger defval) + +
+           
+ LuaIntegerLuaString.optinteger(LuaInteger defval) + +
+           
+ LuaIntegerLuaValue.optinteger(LuaInteger defval) + +
+          Check that optional argument is a number or string convertible to number and return as LuaInteger
+static LuaIntegerLuaInteger.valueOf(int i) + +
+           
+static LuaIntegerLuaValue.valueOf(int i) + +
+          Convert java int to a LuaValue.
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 with parameters of type LuaInteger
+ LuaIntegerVarargs.optinteger(int i, + LuaInteger defval) + +
+          Return argument i as a java int value, defval if nil, or throw a LuaError if not a number or is not representable by a java int.
+ LuaIntegerLuaDouble.optinteger(LuaInteger defval) + +
+           
+ LuaIntegerLuaInteger.optinteger(LuaInteger defval) + +
+           
+ LuaIntegerLuaNil.optinteger(LuaInteger defval) + +
+           
+ LuaIntegerLuaString.optinteger(LuaInteger defval) + +
+           
+ LuaIntegerLuaValue.optinteger(LuaInteger defval) + +
+          Check that optional argument is a number or string convertible to number and return as LuaInteger
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaNil.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaNil.html new file mode 100644 index 0000000000..07766381ed --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaNil.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.LuaNil (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.LuaNil

+
+No usage of org.luaj.vm2.LuaNil +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaNumber.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaNumber.html new file mode 100644 index 0000000000..0d5c2ae7f5 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaNumber.html @@ -0,0 +1,457 @@ + + + + + + +Uses of Class org.luaj.vm2.LuaNumber (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.LuaNumber

+
+ + + + + + + + + +
+Packages that use LuaNumber
org.luaj.vm2  
+  +

+ + + + + +
+Uses of LuaNumber in org.luaj.vm2
+  +

+ + + + + + + + + + + + + +
Subclasses of LuaNumber in org.luaj.vm2
+ classLuaDouble + +
+          Extension of LuaNumber which can hold a Java double as its value.
+ classLuaInteger + +
+          Extension of LuaNumber which can hold a Java int as its value.
+  +

+ + + + + + + + + + + + + + + + + +
Fields in org.luaj.vm2 declared as LuaNumber
+static LuaNumberLuaValue.MINUSONE + +
+          LuaValue number constant equal to -1
+static LuaNumberLuaValue.ONE + +
+          LuaValue number constant equal to 1
+static LuaNumberLuaValue.ZERO + +
+          LuaValue number constant equal to 0
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 that return LuaNumber
+ LuaNumberLuaDouble.checknumber() + +
+           
+ LuaNumberLuaNumber.checknumber() + +
+           
+ LuaNumberLuaString.checknumber() + +
+           
+ LuaNumberLuaValue.checknumber() + +
+          Check that the value is numeric, and return as a LuaNumber if so, or throw LuaError
+ LuaNumberVarargs.checknumber(int i) + +
+          Return argument i as a LuaNumber, or throw an error if not a number or string that can be converted to a number.
+ LuaNumberLuaNumber.checknumber(java.lang.String errmsg) + +
+           
+ LuaNumberLuaString.checknumber(java.lang.String msg) + +
+           
+ LuaNumberLuaValue.checknumber(java.lang.String msg) + +
+          Check that the value is numeric, and return as a LuaNumber if so, or throw LuaError
+ LuaNumberVarargs.optnumber(int i, + LuaNumber defval) + +
+          Return argument i as a LuaNumber, defval if nil, or throw a LuaError if not a number or string that can be converted to a number.
+ LuaNumberLuaDouble.optnumber(LuaNumber defval) + +
+           
+ LuaNumberLuaNil.optnumber(LuaNumber defval) + +
+           
+ LuaNumberLuaNumber.optnumber(LuaNumber defval) + +
+           
+ LuaNumberLuaString.optnumber(LuaNumber defval) + +
+           
+ LuaNumberLuaValue.optnumber(LuaNumber defval) + +
+          Check that optional argument is a number or string convertible to number and return as LuaNumber
+static LuaNumberLuaDouble.valueOf(double d) + +
+           
+static LuaNumberLuaValue.valueOf(double d) + +
+          Convert java double to a LuaValue.
+static LuaNumberLuaInteger.valueOf(long l) + +
+          Return a LuaNumber that represents the value provided
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 with parameters of type LuaNumber
+ BufferBuffer.concatTo(LuaNumber lhs) + +
+          Concatenate this buffer onto a LuaNumber
+ LuaValueLuaNumber.concatTo(LuaNumber lhs) + +
+           
+ LuaValueLuaString.concatTo(LuaNumber lhs) + +
+           
+ LuaValueLuaValue.concatTo(LuaNumber lhs) + +
+          Reverse-concatenation: concatenate this value onto another value + known to be a LuaNumber + and return the result using rules of lua string concatenation including + metatag processing.
+ LuaNumberVarargs.optnumber(int i, + LuaNumber defval) + +
+          Return argument i as a LuaNumber, defval if nil, or throw a LuaError if not a number or string that can be converted to a number.
+ LuaNumberLuaDouble.optnumber(LuaNumber defval) + +
+           
+ LuaNumberLuaNil.optnumber(LuaNumber defval) + +
+           
+ LuaNumberLuaNumber.optnumber(LuaNumber defval) + +
+           
+ LuaNumberLuaString.optnumber(LuaNumber defval) + +
+           
+ LuaNumberLuaValue.optnumber(LuaNumber defval) + +
+          Check that optional argument is a number or string convertible to number and return as LuaNumber
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaString.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaString.html new file mode 100644 index 0000000000..514bde44ee --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaString.html @@ -0,0 +1,855 @@ + + + + + + +Uses of Class org.luaj.vm2.LuaString (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.LuaString

+
+ + + + + + + + + + + + + + + + + +
+Packages that use LuaString
org.luaj.vm2  
org.luaj.vm2.compiler  
org.luaj.vm2.lib  
+  +

+ + + + + +
+Uses of LuaString in org.luaj.vm2
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Fields in org.luaj.vm2 declared as LuaString
+static LuaStringLuaValue.ADD + +
+          LuaString constant with value "__add" for use as metatag
+static LuaStringLuaValue.CALL + +
+          LuaString constant with value "__call" for use as metatag
+static LuaStringLuaValue.CONCAT + +
+          LuaString constant with value "__concat" for use as metatag
+static LuaStringLuaValue.DIV + +
+          LuaString constant with value "__div" for use as metatag
+static LuaStringLuaValue.EMPTYSTRING + +
+          LuaString constant with value ""
+static LuaStringLuaValue.EQ + +
+          LuaString constant with value "__eq" for use as metatag
+static LuaStringLuaValue.INDEX + +
+          LuaString constant with value "__index" for use as metatag
+static LuaStringLuaValue.LE + +
+          LuaString constant with value "__le" for use as metatag
+static LuaStringLuaValue.LEN + +
+          LuaString constant with value "__len" for use as metatag
+static LuaStringLuaValue.LT + +
+          LuaString constant with value "__lt" for use as metatag
+static LuaStringLuaValue.METATABLE + +
+          LuaString constant with value "__metatable" for use as metatag
+static LuaStringLuaValue.MOD + +
+          LuaString constant with value "__mod" for use as metatag
+static LuaStringLuaValue.MODE + +
+          LuaString constant with value "__mode" for use as metatag
+static LuaStringLuaValue.MUL + +
+          LuaString constant with value "__mul" for use as metatag
+static LuaStringLuaValue.NEWINDEX + +
+          LuaString constant with value "__newindex" for use as metatag
+static LuaStringLuaValue.POW + +
+          LuaString constant with value "__pow" for use as metatag
+ LuaStringPrototype.source + +
+           
+static LuaStringLuaValue.SUB + +
+          LuaString constant with value "__sub" for use as metatag
+static LuaStringLuaValue.TOSTRING + +
+          LuaString constant with value "__tostring" for use as metatag
+static LuaStringLuaValue.UNM + +
+          LuaString constant with value "__unm" for use as metatag
+ LuaString[]Prototype.upvalues + +
+           
+ LuaStringLocVars.varname + +
+          The local variable name
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 that return LuaString
+ LuaStringLuaDouble.checkstring() + +
+           
+ LuaStringLuaInteger.checkstring() + +
+           
+ LuaStringLuaString.checkstring() + +
+           
+ LuaStringLuaValue.checkstring() + +
+          Check that this is a lua string, or throw LuaError if it is not.
+ LuaStringVarargs.checkstring(int i) + +
+          Return argument i as a LuaString if a string or number, or throw an error if any other type
+ LuaStringPrototype.getlocalname(int number, + int pc) + +
+          Get the name of a local variable.
+ LuaStringVarargs.optstring(int i, + LuaString defval) + +
+          Return argument i as a LuaString if a string or number, defval if nil, or throw a LuaError if any other type
+ LuaStringLuaDouble.optstring(LuaString defval) + +
+           
+ LuaStringLuaInteger.optstring(LuaString defval) + +
+           
+ LuaStringLuaNil.optstring(LuaString defval) + +
+           
+ LuaStringLuaString.optstring(LuaString defval) + +
+           
+ LuaStringLuaValue.optstring(LuaString defval) + +
+          Check that optional argument is a string or number and return as LuaString
+ LuaStringLuaDouble.strvalue() + +
+           
+ LuaStringLuaInteger.strvalue() + +
+           
+ LuaStringLuaString.strvalue() + +
+           
+ LuaStringLuaValue.strvalue() + +
+          Convert this value to a string if it is a LuaString or LuaNumber, + or throw a LuaError if it is not
+ LuaStringLuaString.substring(int beginIndex, + int endIndex) + +
+           
+ LuaStringBuffer.tostring() + +
+          Convert the buffer to a LuaString
+static LuaStringLuaString.valueOf(byte[] bytes) + +
+          Construct a LuaString around a byte array without copying the contents.
+static LuaStringLuaValue.valueOf(byte[] bytes) + +
+          Convert bytes in an array to a LuaValue.
+static LuaStringLuaString.valueOf(byte[] bytes, + int off, + int len) + +
+          Construct a LuaString around a byte array without copying the contents.
+static LuaStringLuaValue.valueOf(byte[] bytes, + int off, + int len) + +
+          Convert bytes in an array to a LuaValue.
+static LuaStringLuaString.valueOf(char[] bytes) + +
+          Construct a LuaString using the supplied characters as byte values.
+static LuaStringLuaString.valueOf(java.lang.String string) + +
+          Get a LuaString instance whose bytes match + the supplied Java String using the UTF8 encoding.
+static LuaStringLuaValue.valueOf(java.lang.String s) + +
+          Convert java string to a LuaValue.
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 with parameters of type LuaString
+ BufferBuffer.append(LuaString str) + +
+          Append a LuaString to the buffer.
+ LuaValueLuaTable.concat(LuaString sep, + int i, + int j) + +
+          Concatenate the contents of a table efficiently, using Buffer
+ BufferBuffer.concatTo(LuaString lhs) + +
+          Concatenate this buffer onto a LuaString
+ LuaValueLuaNumber.concatTo(LuaString lhs) + +
+           
+ LuaValueLuaString.concatTo(LuaString lhs) + +
+           
+ LuaValueLuaValue.concatTo(LuaString lhs) + +
+          Reverse-concatenation: concatenate this value onto another value + known to be a LuaString + and return the result using rules of lua string concatenation including + metatag processing.
+static booleanLuaString.equals(LuaString a, + int i, + LuaString b, + int j, + int n) + +
+           
+ intLuaString.indexOf(LuaString s, + int start) + +
+          Find the index of a string starting at a point in this string
+ intLuaString.indexOfAny(LuaString accept) + +
+          Java version of strpbrk - find index of any byte that in an accept string.
+ intLuaString.lastIndexOf(LuaString s) + +
+          Find the last index of a string in this string
+ PrototypeLoadState.loadFunction(LuaString p) + +
+          Load a function prototype from the input stream
+ LuaStringVarargs.optstring(int i, + LuaString defval) + +
+          Return argument i as a LuaString if a string or number, defval if nil, or throw a LuaError if any other type
+ LuaStringLuaDouble.optstring(LuaString defval) + +
+           
+ LuaStringLuaInteger.optstring(LuaString defval) + +
+           
+ LuaStringLuaNil.optstring(LuaString defval) + +
+           
+ LuaStringLuaString.optstring(LuaString defval) + +
+           
+ LuaStringLuaValue.optstring(LuaString defval) + +
+          Check that optional argument is a string or number and return as LuaString
+ BufferBuffer.prepend(LuaString s) + +
+          Concatenate bytes from a LuaString onto the front of this buffer
+ booleanLuaString.raweq(LuaString s) + +
+           
+ booleanLuaValue.raweq(LuaString val) + +
+          Equals: Perform direct equality comparison with a LuaString value + without metatag processing.
+ intLuaDouble.strcmp(LuaString rhs) + +
+           
+ intLuaInteger.strcmp(LuaString rhs) + +
+           
+ intLuaString.strcmp(LuaString rhs) + +
+           
+ intLuaValue.strcmp(LuaString rhs) + +
+          Perform string comparison with another value + known to be a LuaString + using string comparison based on byte values.
+  +

+ + + + + + + + +
Constructors in org.luaj.vm2 with parameters of type LuaString
LocVars(LuaString varname, + int startpc, + int endpc) + +
+          Construct a LocVars instance.
+  +

+ + + + + +
+Uses of LuaString in org.luaj.vm2.compiler
+  +

+ + + + + + + + + +
Methods in org.luaj.vm2.compiler that return LuaString
+ LuaStringLuaC.newTString(byte[] bytes, + int offset, + int len) + +
+           
+  +

+ + + + + +
+Uses of LuaString in org.luaj.vm2.lib
+  +

+ + + + + + + + + +
Methods in org.luaj.vm2.lib with parameters of type LuaString
+abstract  voidIoLib.File.write(LuaString string) + +
+           
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaTable.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaTable.html new file mode 100644 index 0000000000..bd1e3d87df --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaTable.html @@ -0,0 +1,535 @@ + + + + + + +Uses of Class org.luaj.vm2.LuaTable (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.LuaTable

+
+ + + + + + + + + + + + + + + + + + + + + +
+Packages that use LuaTable
org.luaj.vm2  
org.luaj.vm2.lib  
org.luaj.vm2.lib.jme  
org.luaj.vm2.lib.jse  
+  +

+ + + + + +
+Uses of LuaTable in org.luaj.vm2
+  +

+ + + + + + + + + +
Subclasses of LuaTable in org.luaj.vm2
+ classWeakTable + +
+          Subclass of LuaTable that provides weak key and weak value semantics.
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 that return LuaTable
+protected  LuaTableLuaTable.changemode(boolean weakkeys, + boolean weakvalues) + +
+          Change the mode of a table
+protected  LuaTableWeakTable.changemode(boolean weakkeys, + boolean weakvalues) + +
+           
+ LuaTableLuaTable.checktable() + +
+           
+ LuaTableLuaValue.checktable() + +
+          Check that this is a LuaTable, or throw LuaError if it is not
+ LuaTableVarargs.checktable(int i) + +
+          Return argument i as a LuaTable if a lua table, or throw an error if any other type.
+static LuaTableLuaValue.listOf(LuaValue[] unnamedValues) + +
+          Construct a LuaTable initialized with supplied array values.
+static LuaTableLuaValue.listOf(LuaValue[] unnamedValues, + Varargs lastarg) + +
+          Construct a LuaTable initialized with supplied array values.
+ LuaTableVarargs.opttable(int i, + LuaTable defval) + +
+          Return argument i as a LuaTable if a lua table, defval if nil, or throw a LuaError if any other type.
+ LuaTableLuaNil.opttable(LuaTable defval) + +
+           
+ LuaTableLuaTable.opttable(LuaTable defval) + +
+           
+ LuaTableLuaValue.opttable(LuaTable defval) + +
+          Check that optional argument is a table and return as LuaTable
+static LuaTableLuaValue.tableOf() + +
+          Construct an empty LuaTable.
+static LuaTableLuaValue.tableOf(int narray, + int nhash) + +
+          Construct an empty LuaTable preallocated to hold array and hashed elements
+static LuaTableLuaValue.tableOf(LuaValue[] namedValues) + +
+          Construct a LuaTable initialized with supplied named values.
+static LuaTableLuaValue.tableOf(LuaValue[] namedValues, + LuaValue[] unnamedValues) + +
+          Construct a LuaTable initialized with supplied named values and sequential elements.
+static LuaTableLuaValue.tableOf(LuaValue[] namedValues, + LuaValue[] unnamedValues, + Varargs lastarg) + +
+          Construct a LuaTable initialized with supplied named values and sequential elements in an array part and as varargs.
+static LuaTableLuaValue.tableOf(Varargs varargs, + int firstarg) + +
+          Construct a LuaTable initialized with supplied array values.
+  +

+ + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 with parameters of type LuaTable
+ LuaTableVarargs.opttable(int i, + LuaTable defval) + +
+          Return argument i as a LuaTable if a lua table, defval if nil, or throw a LuaError if any other type.
+ LuaTableLuaNil.opttable(LuaTable defval) + +
+           
+ LuaTableLuaTable.opttable(LuaTable defval) + +
+           
+ LuaTableLuaValue.opttable(LuaTable defval) + +
+          Check that optional argument is a table and return as LuaTable
+  +

+ + + + + + + + +
Constructors in org.luaj.vm2 with parameters of type LuaTable
WeakTable(boolean weakkeys, + boolean weakvalues, + LuaTable source) + +
+          Construct a table with weak keys, weak values, or both, and a source of initial data
+  +

+ + + + + +
+Uses of LuaTable in org.luaj.vm2.lib
+  +

+ + + + + + + + + + + + + + + + + +
Fields in org.luaj.vm2.lib declared as LuaTable
+static LuaTableStringLib.instance + +
+           
+ LuaTablePackageLib.LOADED + +
+           
+ LuaTablePackageLib.PACKAGE + +
+           
+  +

+ + + + + + + + + + + + + +
Methods in org.luaj.vm2.lib with parameters of type LuaTable
+ voidPackageLib.setIsLoaded(java.lang.String name, + LuaTable value) + +
+          Allow packages to mark themselves as loaded
+protected  longOsLib.time(LuaTable table) + +
+          Returns the current time when called without arguments, + or a time representing the date and time specified by the given table.
+  +

+ + + + + +
+Uses of LuaTable in org.luaj.vm2.lib.jme
+  +

+ + + + + + + + + + + + + +
Methods in org.luaj.vm2.lib.jme that return LuaTable
+static LuaTableJmePlatform.debugGlobals() + +
+          Create standard globals including the debug library.
+static LuaTableJmePlatform.standardGlobals() + +
+          Create a standard set of globals for JME including all the libraries.
+  +

+ + + + + +
+Uses of LuaTable in org.luaj.vm2.lib.jse
+  +

+ + + + + + + + + + + + + +
Methods in org.luaj.vm2.lib.jse that return LuaTable
+static LuaTableJsePlatform.debugGlobals() + +
+          Create standard globals including the debug library.
+static LuaTableJsePlatform.standardGlobals() + +
+          Create a standard set of globals for JSE including all the libraries.
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaThread.CallStack.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaThread.CallStack.html new file mode 100644 index 0000000000..880e121d92 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaThread.CallStack.html @@ -0,0 +1,180 @@ + + + + + + +Uses of Class org.luaj.vm2.LuaThread.CallStack (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.LuaThread.CallStack

+
+ + + + + + + + + +
+Packages that use LuaThread.CallStack
org.luaj.vm2  
+  +

+ + + + + +
+Uses of LuaThread.CallStack in org.luaj.vm2
+  +

+ + + + + + + + + +
Methods in org.luaj.vm2 that return LuaThread.CallStack
+static LuaThread.CallStackLuaThread.onCall(LuaFunction function) + +
+          Callback used at the beginning of a call to prepare for possible getfenv/setfenv calls
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaThread.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaThread.html new file mode 100644 index 0000000000..ded0484032 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaThread.html @@ -0,0 +1,335 @@ + + + + + + +Uses of Class org.luaj.vm2.LuaThread (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.LuaThread

+
+ + + + + + + + + + + + + +
+Packages that use LuaThread
org.luaj.vm2  
org.luaj.vm2.lib  
+  +

+ + + + + +
+Uses of LuaThread in org.luaj.vm2
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 that return LuaThread
+ LuaThreadLuaThread.checkthread() + +
+           
+ LuaThreadLuaValue.checkthread() + +
+          Check that this is a LuaThread, or throw LuaError if it is not
+ LuaThreadVarargs.checkthread(int i) + +
+          Return argument i as a LuaThread if a lua thread, or throw an error if any other type.
+static LuaThreadLuaThread.getRunning() + +
+          Get the currently running thread.
+ LuaThreadVarargs.optthread(int i, + LuaThread defval) + +
+          Return argument i as a LuaThread if a lua thread, defval if nil, or throw a LuaError if any other type.
+ LuaThreadLuaNil.optthread(LuaThread defval) + +
+           
+ LuaThreadLuaThread.optthread(LuaThread defval) + +
+           
+ LuaThreadLuaValue.optthread(LuaThread defval) + +
+          Check that optional argument is a thread and return as LuaThread
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 with parameters of type LuaThread
+static booleanLuaThread.isMainThread(LuaThread r) + +
+          Test if this is the main thread
+ LuaThreadVarargs.optthread(int i, + LuaThread defval) + +
+          Return argument i as a LuaThread if a lua thread, defval if nil, or throw a LuaError if any other type.
+ LuaThreadLuaNil.optthread(LuaThread defval) + +
+           
+ LuaThreadLuaThread.optthread(LuaThread defval) + +
+           
+ LuaThreadLuaValue.optthread(LuaThread defval) + +
+          Check that optional argument is a thread and return as LuaThread
+  +

+ + + + + +
+Uses of LuaThread in org.luaj.vm2.lib
+  +

+ + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2.lib with parameters of type LuaThread
+static voidDebugLib.debugOnCall(LuaThread thread, + int calls, + LuaFunction func) + +
+          Called by Closures and recursing java functions on entry
+static voidDebugLib.debugOnReturn(LuaThread thread, + int calls) + +
+          Called by Closures and recursing java functions on return
+static java.lang.StringDebugLib.traceback(LuaThread thread, + int level) + +
+          Get a traceback for a particular thread.
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaUserdata.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaUserdata.html new file mode 100644 index 0000000000..58514202a7 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaUserdata.html @@ -0,0 +1,214 @@ + + + + + + +Uses of Class org.luaj.vm2.LuaUserdata (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.LuaUserdata

+
+ + + + + + + + + +
+Packages that use LuaUserdata
org.luaj.vm2  
+  +

+ + + + + +
+Uses of LuaUserdata in org.luaj.vm2
+  +

+ + + + + + + + + + + + + +
Methods in org.luaj.vm2 that return LuaUserdata
+static LuaUserdataLuaValue.userdataOf(java.lang.Object o) + +
+          Construct a LuaUserdata for an object.
+static LuaUserdataLuaValue.userdataOf(java.lang.Object o, + LuaValue metatable) + +
+          Construct a LuaUserdata for an object with a user supplied metatable.
+  +

+ + + + + + + + + + + + + +
Methods in org.luaj.vm2 with parameters of type LuaUserdata
+ booleanLuaUserdata.raweq(LuaUserdata val) + +
+           
+ booleanLuaValue.raweq(LuaUserdata val) + +
+          Equals: Perform direct equality comparison with a LuaUserdata value + without metatag processing.
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaValue.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaValue.html new file mode 100644 index 0000000000..a35b0775b6 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/LuaValue.html @@ -0,0 +1,5645 @@ + + + + + + +Uses of Class org.luaj.vm2.LuaValue (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.LuaValue

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Packages that use LuaValue
org.luaj.vm2  
org.luaj.vm2.compiler  
org.luaj.vm2.lib  
org.luaj.vm2.lib.jme  
org.luaj.vm2.lib.jse  
org.luaj.vm2.luajc  
+  +

+ + + + + +
+Uses of LuaValue in org.luaj.vm2
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Subclasses of LuaValue in org.luaj.vm2
+ classLuaBoolean + +
+          Extension of LuaValue which can hold a Java boolean as its value.
+ classLuaClosure + +
+          Extension of LuaFunction which executes lua bytecode.
+ classLuaDouble + +
+          Extension of LuaNumber which can hold a Java double as its value.
+ classLuaFunction + +
+          Base class for functions implemented in Java.
+ classLuaInteger + +
+          Extension of LuaNumber which can hold a Java int as its value.
+ classLuaNil + +
+          Class to encapsulate behavior of the singleton instance nil
+ classLuaNumber + +
+          Base class for representing numbers as lua values directly.
+ classLuaString + +
+          Subclass of LuaValue for representing lua strings.
+ classLuaTable + +
+          Subclass of LuaValue for representing lua tables.
+ classLuaThread + +
+          Subclass of LuaValue that implements + a lua coroutine thread using Java Threads.
+ classLuaUserdata + +
+           
+ classWeakTable + +
+          Subclass of LuaTable that provides weak key and weak value semantics.
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Fields in org.luaj.vm2 declared as LuaValue
+protected  LuaValue[]LuaTable.array + +
+          the array values
+protected  LuaValueLuaFunction.env + +
+           
+ LuaValueLuaThread.err + +
+          Field to hold state of error condition during debug hook function calls.
+protected  LuaValue[]LuaTable.hashKeys + +
+          the hash keys
+protected  LuaValue[]LuaTable.hashValues + +
+          the hash values
+ LuaValue[]Prototype.k + +
+           
+protected  LuaValueLuaTable.m_metatable + +
+          metatable for this table, or null
+ LuaValueLuaUserdata.m_metatable + +
+           
+static LuaValueLuaValue.NIL + +
+          LuaValue constant corresponding to lua nil
+static LuaValue[]LuaValue.NILS + +
+          Array of NIL values to optimize filling stacks using System.arraycopy().
+static LuaValueLuaValue.NONE + +
+          LuaValue constant corresponding to a Varargs list of no values
+static LuaValue[]LuaValue.NOVALS + +
+          LuaValue array constant with no values
+static LuaValueLuaBoolean.s_metatable + +
+          Shared static metatable for boolean values represented in lua.
+static LuaValueLuaFunction.s_metatable + +
+          Shared static metatable for all functions and closures.
+static LuaValueLuaNil.s_metatable + +
+           
+static LuaValueLuaNumber.s_metatable + +
+          Shared static metatable for all number values represented in lua.
+static LuaValueLuaString.s_metatable + +
+          The singleton instance representing lua true
+static LuaValueLuaThread.s_metatable + +
+           
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 that return LuaValue
+ LuaValueLuaDouble.add(double lhs) + +
+           
+ LuaValueLuaInteger.add(double lhs) + +
+           
+ LuaValueLuaString.add(double rhs) + +
+           
+ LuaValueLuaValue.add(double rhs) + +
+          Add: Perform numeric add operation with another value + of double type with metatag processing
+ LuaValueLuaInteger.add(int lhs) + +
+           
+ LuaValueLuaString.add(int rhs) + +
+           
+ LuaValueLuaValue.add(int rhs) + +
+          Add: Perform numeric add operation with another value + of int type with metatag processing
+ LuaValueLuaDouble.add(LuaValue rhs) + +
+           
+ LuaValueLuaInteger.add(LuaValue rhs) + +
+           
+ LuaValueLuaString.add(LuaValue rhs) + +
+           
+ LuaValueLuaValue.add(LuaValue rhs) + +
+          Add: Perform numeric add operation with another value + including metatag processing.
+ LuaValueLuaValue.and(LuaValue rhs) + +
+          Perform boolean and with another operand, based on lua rules for boolean evaluation.
+ LuaValueLuaValue.arg(int index) + +
+           
+ LuaValueTailcallVarargs.arg(int i) + +
+           
+abstract  LuaValueVarargs.arg(int i) + +
+          Get the n-th argument value (1-based).
+ LuaValueLuaValue.arg1() + +
+           
+ LuaValueTailcallVarargs.arg1() + +
+           
+abstract  LuaValueVarargs.arg1() + +
+          Get the first argument in the list.
+static LuaValueLuaValue.argerror(int iarg, + java.lang.String msg) + +
+          Throw a LuaError indicating an invalid argument was supplied to a function
+protected  LuaValueLuaValue.argerror(java.lang.String expected) + +
+          Throw a LuaError indicating an invalid argument was supplied to a function
+protected  LuaValueLuaValue.aritherror() + +
+          Throw a LuaError based on an arithmetic error such as add, or pow, + typically due to an invalid operand type
+protected  LuaValueLuaValue.aritherror(java.lang.String fun) + +
+          Throw a LuaError based on an arithmetic error such as add, or pow, + typically due to an invalid operand type
+protected  LuaValueLuaValue.arithmt(LuaValue tag, + LuaValue op2) + +
+          Perform metatag processing for arithmetic operations.
+protected  LuaValueLuaValue.arithmtwith(LuaValue tag, + double op1) + +
+          Perform metatag processing for arithmetic operations when the left-hand-side is a number.
+ LuaValueLuaClosure.call() + +
+           
+ LuaValueLuaValue.call() + +
+          Call this with 0 arguments, including metatag processing, + and return only the first return value.
+ LuaValueLuaClosure.call(LuaValue arg) + +
+           
+ LuaValueLuaValue.call(LuaValue arg) + +
+          Call this with 1 argument, including metatag processing, + and return only the first return value.
+ LuaValueLuaClosure.call(LuaValue arg1, + LuaValue arg2) + +
+           
+ LuaValueLuaValue.call(LuaValue arg1, + LuaValue arg2) + +
+          Call this with 2 arguments, including metatag processing, + and return only the first return value.
+ LuaValueLuaClosure.call(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+           
+ LuaValueLuaValue.call(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+          Call this with 3 arguments, including metatag processing, + and return only the first return value.
+protected  LuaValueLuaValue.callmt() + +
+          Get the metatag value for the CALL metatag, if it exists.
+ LuaValueLuaFunction.checkfunction() + +
+           
+ LuaValueLuaValue.checkfunction() + +
+          Check that the value is a function , or throw LuaError if not
+ LuaValueVarargs.checkfunction(int i) + +
+          Return argument i as a function, or throw an error if an incompatible type.
+protected  LuaValueLuaValue.checkmetatag(LuaValue tag, + java.lang.String reason) + +
+          Get particular metatag, or throw LuaError if it doesn't exist
+ LuaValueLuaNil.checknotnil() + +
+           
+ LuaValueLuaValue.checknotnil() + +
+          Check that this is not the value NIL, or throw LuaError if it is
+ LuaValueVarargs.checknotnil(int i) + +
+          Return argument i as a LuaValue if it is not nil, or throw an error if it is nil.
+ LuaValueLuaDouble.checkvalidkey() + +
+           
+ LuaValueLuaNil.checkvalidkey() + +
+           
+ LuaValueLuaValue.checkvalidkey() + +
+          Check that this is a valid key in a table index operation, or throw LuaError if not
+ LuaValueVarargs.checkvalue(int i) + +
+          Return argument i as a LuaValue if it exists, or throw an error.
+protected  LuaValueLuaValue.compareerror(LuaValue rhs) + +
+          Throw a LuaError based on a comparison error such as greater-than or less-than, + typically due to an invalid operand type
+protected  LuaValueLuaValue.compareerror(java.lang.String rhs) + +
+          Throw a LuaError based on a comparison error such as greater-than or less-than, + typically due to an invalid operand type
+ LuaValueLuaValue.comparemt(LuaValue tag, + LuaValue op1) + +
+          Perform metatag processing for comparison operations.
+ LuaValueLuaTable.concat(LuaString sep, + int i, + int j) + +
+          Concatenate the contents of a table efficiently, using Buffer
+ LuaValueLuaNumber.concat(LuaValue rhs) + +
+           
+ LuaValueLuaString.concat(LuaValue rhs) + +
+           
+ LuaValueLuaValue.concat(LuaValue rhs) + +
+          Concatenate another value onto this value and return the result + using rules of lua string concatenation including metatag processing.
+ LuaValueLuaValue.concatmt(LuaValue rhs) + +
+          Perform metatag processing for concatenation operations.
+ LuaValueLuaNumber.concatTo(LuaNumber lhs) + +
+           
+ LuaValueLuaString.concatTo(LuaNumber lhs) + +
+           
+ LuaValueLuaValue.concatTo(LuaNumber lhs) + +
+          Reverse-concatenation: concatenate this value onto another value + known to be a LuaNumber + and return the result using rules of lua string concatenation including + metatag processing.
+ LuaValueLuaNumber.concatTo(LuaString lhs) + +
+           
+ LuaValueLuaString.concatTo(LuaString lhs) + +
+           
+ LuaValueLuaValue.concatTo(LuaString lhs) + +
+          Reverse-concatenation: concatenate this value onto another value + known to be a LuaString + and return the result using rules of lua string concatenation including + metatag processing.
+ LuaValueLuaValue.concatTo(LuaValue lhs) + +
+          Reverse-concatenation: concatenate this value onto another value + whose type is unknwon + and return the result using rules of lua string concatenation including + metatag processing.
+static LuaValueLuaDouble.ddiv(double lhs, + double rhs) + +
+          Divide two double numbers according to lua math, and return a LuaValue result.
+ LuaValueLuaDouble.div(double rhs) + +
+           
+ LuaValueLuaInteger.div(double rhs) + +
+           
+ LuaValueLuaString.div(double rhs) + +
+           
+ LuaValueLuaValue.div(double rhs) + +
+          Divide: Perform numeric divide operation by another value + of double type without metatag processing
+ LuaValueLuaDouble.div(int rhs) + +
+           
+ LuaValueLuaInteger.div(int rhs) + +
+           
+ LuaValueLuaString.div(int rhs) + +
+           
+ LuaValueLuaValue.div(int rhs) + +
+          Divide: Perform numeric divide operation by another value + of int type without metatag processing
+ LuaValueLuaDouble.div(LuaValue rhs) + +
+           
+ LuaValueLuaInteger.div(LuaValue rhs) + +
+           
+ LuaValueLuaString.div(LuaValue rhs) + +
+           
+ LuaValueLuaValue.div(LuaValue rhs) + +
+          Divide: Perform numeric divide operation by another value + of unknown type, + including metatag processing.
+ LuaValueLuaDouble.divInto(double lhs) + +
+           
+ LuaValueLuaInteger.divInto(double lhs) + +
+           
+ LuaValueLuaString.divInto(double lhs) + +
+           
+ LuaValueLuaValue.divInto(double lhs) + +
+          Reverse-divide: Perform numeric divide operation into another value + with metatag processing
+static LuaValueLuaDouble.dmod(double lhs, + double rhs) + +
+          Take modulo double numbers according to lua math, and return a LuaValue result.
+ LuaValueLuaDouble.eq(LuaValue val) + +
+           
+ LuaValueLuaInteger.eq(LuaValue val) + +
+           
+ LuaValueLuaString.eq(LuaValue val) + +
+           
+ LuaValueLuaTable.eq(LuaValue val) + +
+           
+ LuaValueLuaUserdata.eq(LuaValue val) + +
+           
+ LuaValueLuaValue.eq(LuaValue val) + +
+          Equals: Perform equality comparison with another value + including metatag processing using EQ.
+static LuaValueLuaValue.error(java.lang.String message) + +
+          Throw a LuaError with a particular message
+ LuaValueLuaTable.foreach(LuaValue func) + +
+          Call the supplied function once for each key-value pair
+ LuaValueLuaTable.foreachi(LuaValue func) + +
+          Call the supplied function once for each key-value pair + in the contiguous array part
+ LuaValueLuaTable.get(int key) + +
+           
+ LuaValueLuaValue.get(int key) + +
+          Get a value in a table including metatag processing using INDEX.
+ LuaValueLuaString.get(LuaValue key) + +
+           
+ LuaValueLuaTable.get(LuaValue key) + +
+           
+ LuaValueLuaUserdata.get(LuaValue key) + +
+           
+ LuaValueLuaValue.get(LuaValue key) + +
+          Get a value in a table including metatag processing using INDEX.
+ LuaValueLuaValue.get(java.lang.String key) + +
+          Get a value in a table including metatag processing using INDEX.
+ LuaValueLuaFunction.getfenv() + +
+           
+ LuaValueLuaThread.getfenv() + +
+           
+ LuaValueLuaValue.getfenv() + +
+          Get the environemnt for an instance.
+static LuaValueLuaThread.getGlobals() + +
+          Get the current thread's environment
+ LuaValueLuaBoolean.getmetatable() + +
+           
+ LuaValueLuaClosure.getmetatable() + +
+           
+ LuaValueLuaFunction.getmetatable() + +
+           
+ LuaValueLuaNil.getmetatable() + +
+           
+ LuaValueLuaNumber.getmetatable() + +
+           
+ LuaValueLuaString.getmetatable() + +
+           
+ LuaValueLuaTable.getmetatable() + +
+           
+ LuaValueLuaThread.getmetatable() + +
+           
+ LuaValueLuaUserdata.getmetatable() + +
+           
+ LuaValueLuaValue.getmetatable() + +
+          Get the metatable for this LuaValue
+ LuaValueLuaTable.getn() + +
+           
+ LuaValueLuaValue.getn() + +
+          Implementation of lua 5.0 getn() function.
+protected static LuaValueLuaValue.gettable(LuaValue t, + LuaValue key) + +
+          get value from metatable operations, or NIL if not defined by metatables
+protected  LuaValueLuaClosure.getUpvalue(int i) + +
+           
+ LuaValueUpValue.getValue() + +
+          Get the value of the upvalue
+ LuaValueLuaDouble.gt(double rhs) + +
+           
+ LuaValueLuaInteger.gt(double rhs) + +
+           
+ LuaValueLuaValue.gt(double rhs) + +
+          Greater than: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue.
+ LuaValueLuaDouble.gt(int rhs) + +
+           
+ LuaValueLuaInteger.gt(int rhs) + +
+           
+ LuaValueLuaValue.gt(int rhs) + +
+          Greater than: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue.
+ LuaValueLuaDouble.gt(LuaValue rhs) + +
+           
+ LuaValueLuaInteger.gt(LuaValue rhs) + +
+           
+ LuaValueLuaString.gt(LuaValue rhs) + +
+           
+ LuaValueLuaValue.gt(LuaValue rhs) + +
+          Greater than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ LuaValueLuaDouble.gteq(double rhs) + +
+           
+ LuaValueLuaInteger.gteq(double rhs) + +
+           
+ LuaValueLuaValue.gteq(double rhs) + +
+          Greater than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue.
+ LuaValueLuaDouble.gteq(int rhs) + +
+           
+ LuaValueLuaInteger.gteq(int rhs) + +
+           
+ LuaValueLuaValue.gteq(int rhs) + +
+          Greater than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue.
+ LuaValueLuaDouble.gteq(LuaValue rhs) + +
+           
+ LuaValueLuaInteger.gteq(LuaValue rhs) + +
+           
+ LuaValueLuaString.gteq(LuaValue rhs) + +
+           
+ LuaValueLuaValue.gteq(LuaValue rhs) + +
+          Greater than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+protected  LuaValueLuaTable.hashget(LuaValue key) + +
+           
+protected  LuaValueWeakTable.hashget(LuaValue key) + +
+          Get the hash value for a key + key the key to look up
+protected  LuaValueLuaValue.illegal(java.lang.String op, + java.lang.String typename) + +
+          Throw a LuaError indicating an illegal operation occurred, + typically involved in managing weak references
+ LuaValue[]LuaTable.keys() + +
+          This may be deprecated in a future release.
+ LuaValueLuaString.len() + +
+           
+ LuaValueLuaTable.len() + +
+           
+ LuaValueLuaValue.len() + +
+          Length operator: return lua length of object (#this) including metatag processing as java int
+protected  LuaValueLuaValue.lenerror() + +
+          Throw a LuaError based on the len operator, + typically due to an invalid operand type
+ LuaValueLuaValue.load(LuaValue library) + +
+          Load a library instance by setting its environment to this + and calling it, which should iniitalize the library instance and + install itself into this instance.
+static LuaValueLoadState.longBitsToLuaNumber(long bits) + +
+          Convert bits in a long value to a LuaValue.
+ LuaValueLuaDouble.lt(double rhs) + +
+           
+ LuaValueLuaInteger.lt(double rhs) + +
+           
+ LuaValueLuaValue.lt(double rhs) + +
+          Less than: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue.
+ LuaValueLuaDouble.lt(int rhs) + +
+           
+ LuaValueLuaInteger.lt(int rhs) + +
+           
+ LuaValueLuaValue.lt(int rhs) + +
+          Less than: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue.
+ LuaValueLuaDouble.lt(LuaValue rhs) + +
+           
+ LuaValueLuaInteger.lt(LuaValue rhs) + +
+           
+ LuaValueLuaString.lt(LuaValue rhs) + +
+           
+ LuaValueLuaValue.lt(LuaValue rhs) + +
+          Less than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ LuaValueLuaDouble.lteq(double rhs) + +
+           
+ LuaValueLuaInteger.lteq(double rhs) + +
+           
+ LuaValueLuaValue.lteq(double rhs) + +
+          Less than or equals: Perform numeric comparison with another value + of double type, + including metatag processing, and returning LuaValue.
+ LuaValueLuaDouble.lteq(int rhs) + +
+           
+ LuaValueLuaInteger.lteq(int rhs) + +
+           
+ LuaValueLuaValue.lteq(int rhs) + +
+          Less than or equals: Perform numeric comparison with another value + of int type, + including metatag processing, and returning LuaValue.
+ LuaValueLuaDouble.lteq(LuaValue rhs) + +
+           
+ LuaValueLuaInteger.lteq(LuaValue rhs) + +
+           
+ LuaValueLuaString.lteq(LuaValue rhs) + +
+           
+ LuaValueLuaValue.lteq(LuaValue rhs) + +
+          Less than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ LuaValueLuaValue.metatag(LuaValue tag) + +
+          Get particular metatag, or return NIL if it doesn't exist
+ LuaValueLuaValue.method(LuaValue name) + +
+          Call named method on this with 0 arguments, including metatag processing, + and return only the first return value.
+ LuaValueLuaValue.method(LuaValue name, + LuaValue arg) + +
+          Call named method on this with 1 argument, including metatag processing, + and return only the first return value.
+ LuaValueLuaValue.method(LuaValue name, + LuaValue arg1, + LuaValue arg2) + +
+          Call named method on this with 2 arguments, including metatag processing, + and return only the first return value.
+ LuaValueLuaValue.method(java.lang.String name) + +
+          Call named method on this with 0 arguments, including metatag processing, + and return only the first return value.
+ LuaValueLuaValue.method(java.lang.String name, + LuaValue arg) + +
+          Call named method on this with 1 argument, including metatag processing, + and return only the first return value.
+ LuaValueLuaValue.method(java.lang.String name, + LuaValue arg1, + LuaValue arg2) + +
+          Call named method on this with 2 arguments, including metatag processing, + and return only the first return value.
+ LuaValueLuaDouble.mod(double rhs) + +
+           
+ LuaValueLuaInteger.mod(double rhs) + +
+           
+ LuaValueLuaString.mod(double rhs) + +
+           
+ LuaValueLuaValue.mod(double rhs) + +
+          Modulo: Perform numeric modulo operation with another value + of double type without metatag processing
+ LuaValueLuaDouble.mod(int rhs) + +
+           
+ LuaValueLuaInteger.mod(int rhs) + +
+           
+ LuaValueLuaString.mod(int rhs) + +
+           
+ LuaValueLuaValue.mod(int rhs) + +
+          Modulo: Perform numeric modulo operation with another value + of int type without metatag processing
+ LuaValueLuaDouble.mod(LuaValue rhs) + +
+           
+ LuaValueLuaInteger.mod(LuaValue rhs) + +
+           
+ LuaValueLuaString.mod(LuaValue rhs) + +
+           
+ LuaValueLuaValue.mod(LuaValue rhs) + +
+          Modulo: Perform numeric modulo operation with another value + of unknown type, + including metatag processing.
+ LuaValueLuaDouble.modFrom(double lhs) + +
+           
+ LuaValueLuaInteger.modFrom(double lhs) + +
+           
+ LuaValueLuaString.modFrom(double lhs) + +
+           
+ LuaValueLuaValue.modFrom(double lhs) + +
+          Reverse-modulo: Perform numeric modulo operation from another value + with metatag processing
+ LuaValueLuaDouble.mul(double lhs) + +
+           
+ LuaValueLuaInteger.mul(double lhs) + +
+           
+ LuaValueLuaString.mul(double rhs) + +
+           
+ LuaValueLuaValue.mul(double rhs) + +
+          Multiply: Perform numeric multiply operation with another value + of double type with metatag processing
+ LuaValueLuaDouble.mul(int lhs) + +
+           
+ LuaValueLuaInteger.mul(int lhs) + +
+           
+ LuaValueLuaString.mul(int rhs) + +
+           
+ LuaValueLuaValue.mul(int rhs) + +
+          Multiply: Perform numeric multiply operation with another value + of int type with metatag processing
+ LuaValueLuaDouble.mul(LuaValue rhs) + +
+           
+ LuaValueLuaInteger.mul(LuaValue rhs) + +
+           
+ LuaValueLuaString.mul(LuaValue rhs) + +
+           
+ LuaValueLuaValue.mul(LuaValue rhs) + +
+          Multiply: Perform numeric multiply operation with another value + of unknown type, + including metatag processing.
+ LuaValueLuaDouble.neg() + +
+           
+ LuaValueLuaInteger.neg() + +
+           
+ LuaValueLuaString.neg() + +
+           
+ LuaValueLuaValue.neg() + +
+          Unary minus: return negative value (-this) as defined by lua unary minus operator
+ LuaValueLuaValue.neq(LuaValue val) + +
+          Notquals: Perform inequality comparison with another value + including metatag processing using EQ.
+ LuaValueLuaBoolean.not() + +
+           
+ LuaValueLuaNil.not() + +
+           
+ LuaValueLuaValue.not() + +
+          Unary not: return inverse boolean value (~this) as defined by lua not operator
+ LuaValueVarargs.optvalue(int i, + LuaValue defval) + +
+          Return argument i as a LuaValue if it exists, or defval.
+ LuaValueLuaNil.optvalue(LuaValue defval) + +
+           
+ LuaValueLuaValue.optvalue(LuaValue defval) + +
+          Perform argument check that this is not nil or none.
+ LuaValueLuaValue.or(LuaValue rhs) + +
+          Perform boolean or with another operand, based on lua rules for boolean evaluation.
+ LuaValueLuaDouble.pow(double rhs) + +
+           
+ LuaValueLuaInteger.pow(double rhs) + +
+           
+ LuaValueLuaString.pow(double rhs) + +
+           
+ LuaValueLuaValue.pow(double rhs) + +
+          Raise to power: Raise this value to a power + of double type with metatag processing
+ LuaValueLuaDouble.pow(int rhs) + +
+           
+ LuaValueLuaInteger.pow(int rhs) + +
+           
+ LuaValueLuaString.pow(int rhs) + +
+           
+ LuaValueLuaValue.pow(int rhs) + +
+          Raise to power: Raise this value to a power + of int type with metatag processing
+ LuaValueLuaDouble.pow(LuaValue rhs) + +
+           
+ LuaValueLuaInteger.pow(LuaValue rhs) + +
+           
+ LuaValueLuaString.pow(LuaValue rhs) + +
+           
+ LuaValueLuaValue.pow(LuaValue rhs) + +
+          Raise to power: Raise this value to a power + including metatag processing.
+ LuaValueLuaDouble.powWith(double lhs) + +
+           
+ LuaValueLuaInteger.powWith(double lhs) + +
+           
+ LuaValueLuaString.powWith(double lhs) + +
+           
+ LuaValueLuaValue.powWith(double lhs) + +
+          Reverse-raise to power: Raise another value of double type to this power + with metatag processing
+ LuaValueLuaDouble.powWith(int lhs) + +
+           
+ LuaValueLuaInteger.powWith(int lhs) + +
+           
+ LuaValueLuaString.powWith(int lhs) + +
+           
+ LuaValueLuaValue.powWith(int lhs) + +
+          Reverse-raise to power: Raise another value of double type to this power + with metatag processing
+ LuaValueLuaTable.rawget(int key) + +
+           
+ LuaValueLuaValue.rawget(int key) + +
+          Get a value in a table without metatag processing.
+ LuaValueWeakTable.rawget(int key) + +
+           
+ LuaValueLuaTable.rawget(LuaValue key) + +
+           
+ LuaValueLuaValue.rawget(LuaValue key) + +
+          Get a value in a table without metatag processing.
+ LuaValueWeakTable.rawget(LuaValue key) + +
+           
+ LuaValueLuaValue.rawget(java.lang.String key) + +
+          Get a value in a table without metatag processing.
+ LuaValueLuaTable.remove(int pos) + +
+          Remove the element at a position in a list-table
+static LuaValueLuaThread.setErrorFunc(LuaValue errfunc) + +
+          Replace the error function of the currently running thread.
+ LuaValueLuaTable.setmetatable(LuaValue metatable) + +
+           
+ LuaValueLuaUserdata.setmetatable(LuaValue metatable) + +
+           
+ LuaValueLuaValue.setmetatable(LuaValue metatable) + +
+          Set the metatable for this LuaValue
+ LuaValueLuaValue.strongkey() + +
+          Return the key part of this value if it is a weak table entry, or NIL if it was weak and is no longer referenced.
+ LuaValueLuaValue.strongvalue() + +
+          Return this value as a strong reference, or NIL if it was weak and is no longer referenced.
+ LuaValueLuaDouble.sub(double rhs) + +
+           
+ LuaValueLuaInteger.sub(double rhs) + +
+           
+ LuaValueLuaString.sub(double rhs) + +
+           
+ LuaValueLuaValue.sub(double rhs) + +
+          Subtract: Perform numeric subtract operation with another value + of double type with metatag processing
+ LuaValueLuaDouble.sub(int rhs) + +
+           
+ LuaValueLuaInteger.sub(int rhs) + +
+           
+ LuaValueLuaString.sub(int rhs) + +
+           
+ LuaValueLuaValue.sub(int rhs) + +
+          Subtract: Perform numeric subtract operation with another value + of int type with metatag processing
+ LuaValueLuaDouble.sub(LuaValue rhs) + +
+           
+ LuaValueLuaInteger.sub(LuaValue rhs) + +
+           
+ LuaValueLuaString.sub(LuaValue rhs) + +
+           
+ LuaValueLuaValue.sub(LuaValue rhs) + +
+          Subtract: Perform numeric subtract operation with another value + of unknown type, + including metatag processing.
+ LuaValueLuaDouble.subFrom(double lhs) + +
+           
+ LuaValueLuaInteger.subFrom(double lhs) + +
+           
+ LuaValueLuaString.subFrom(double lhs) + +
+           
+ LuaValueLuaValue.subFrom(double lhs) + +
+          Reverse-subtract: Perform numeric subtract operation from an int value + with metatag processing
+ LuaValueLuaInteger.subFrom(int lhs) + +
+           
+ LuaValueLuaValue.subFrom(int lhs) + +
+          Reverse-subtract: Perform numeric subtract operation from a double value + without metatag processing
+ LuaValueLuaDouble.tonumber() + +
+           
+ LuaValueLuaNumber.tonumber() + +
+           
+ LuaValueLuaString.tonumber() + +
+           
+ LuaValueLuaValue.tonumber() + +
+          Conditionally convert to lua number without throwing errors.
+ LuaValueLuaString.tonumber(int base) + +
+          convert to a number using a supplied base, or NIL if it can't be converted
+ LuaValueLuaDouble.tostring() + +
+           
+ LuaValueLuaInteger.tostring() + +
+           
+ LuaValueLuaString.tostring() + +
+           
+ LuaValueLuaValue.tostring() + +
+          Conditionally convert to lua string without throwing errors.
+protected  LuaValueLuaValue.typerror(java.lang.String expected) + +
+          Throw a LuaError indicating an invalid type was supplied to a function
+protected  LuaValueLuaValue.unimplemented(java.lang.String fun) + +
+          Throw a LuaError indicating an operation is not implemented
+ LuaValueBuffer.value() + +
+          Get buffer contents as a LuaValue
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 with parameters of type LuaValue
+ LuaValueLuaDouble.add(LuaValue rhs) + +
+           
+ LuaValueLuaInteger.add(LuaValue rhs) + +
+           
+ LuaValueLuaString.add(LuaValue rhs) + +
+           
+ LuaValueLuaValue.add(LuaValue rhs) + +
+          Add: Perform numeric add operation with another value + including metatag processing.
+ LuaValueLuaValue.and(LuaValue rhs) + +
+          Perform boolean and with another operand, based on lua rules for boolean evaluation.
+ BufferBuffer.append(LuaValue val) + +
+          Append a LuaValue to the buffer.
+protected  LuaValueLuaValue.arithmt(LuaValue tag, + LuaValue op2) + +
+          Perform metatag processing for arithmetic operations.
+protected  LuaValueLuaValue.arithmtwith(LuaValue tag, + double op1) + +
+          Perform metatag processing for arithmetic operations when the left-hand-side is a number.
+ LuaValueLuaClosure.call(LuaValue arg) + +
+           
+ LuaValueLuaValue.call(LuaValue arg) + +
+          Call this with 1 argument, including metatag processing, + and return only the first return value.
+ LuaValueLuaClosure.call(LuaValue arg1, + LuaValue arg2) + +
+           
+ LuaValueLuaValue.call(LuaValue arg1, + LuaValue arg2) + +
+          Call this with 2 arguments, including metatag processing, + and return only the first return value.
+ LuaValueLuaClosure.call(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+           
+ LuaValueLuaValue.call(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+          Call this with 3 arguments, including metatag processing, + and return only the first return value.
+protected  LuaValueLuaValue.checkmetatag(LuaValue tag, + java.lang.String reason) + +
+          Get particular metatag, or throw LuaError if it doesn't exist
+protected  LuaValueLuaValue.compareerror(LuaValue rhs) + +
+          Throw a LuaError based on a comparison error such as greater-than or less-than, + typically due to an invalid operand type
+ LuaValueLuaValue.comparemt(LuaValue tag, + LuaValue op1) + +
+          Perform metatag processing for comparison operations.
+ LuaValueLuaNumber.concat(LuaValue rhs) + +
+           
+ LuaValueLuaString.concat(LuaValue rhs) + +
+           
+ LuaValueLuaValue.concat(LuaValue rhs) + +
+          Concatenate another value onto this value and return the result + using rules of lua string concatenation including metatag processing.
+ LuaValueLuaValue.concatmt(LuaValue rhs) + +
+          Perform metatag processing for concatenation operations.
+ BufferBuffer.concatTo(LuaValue lhs) + +
+          Concatenate this buffer onto a LuaValue
+ LuaValueLuaValue.concatTo(LuaValue lhs) + +
+          Reverse-concatenation: concatenate this value onto another value + whose type is unknwon + and return the result using rules of lua string concatenation including + metatag processing.
+ LuaValueLuaDouble.div(LuaValue rhs) + +
+           
+ LuaValueLuaInteger.div(LuaValue rhs) + +
+           
+ LuaValueLuaString.div(LuaValue rhs) + +
+           
+ LuaValueLuaValue.div(LuaValue rhs) + +
+          Divide: Perform numeric divide operation by another value + of unknown type, + including metatag processing.
+ booleanLuaDouble.eq_b(LuaValue val) + +
+           
+ booleanLuaInteger.eq_b(LuaValue val) + +
+           
+ booleanLuaString.eq_b(LuaValue val) + +
+           
+ booleanLuaTable.eq_b(LuaValue val) + +
+           
+ booleanLuaUserdata.eq_b(LuaValue val) + +
+           
+ booleanLuaValue.eq_b(LuaValue val) + +
+          Equals: Perform equality comparison with another value + including metatag processing using EQ, + and return java boolean
+ LuaValueLuaDouble.eq(LuaValue val) + +
+           
+ LuaValueLuaInteger.eq(LuaValue val) + +
+           
+ LuaValueLuaString.eq(LuaValue val) + +
+           
+ LuaValueLuaTable.eq(LuaValue val) + +
+           
+ LuaValueLuaUserdata.eq(LuaValue val) + +
+           
+ LuaValueLuaValue.eq(LuaValue val) + +
+          Equals: Perform equality comparison with another value + including metatag processing using EQ.
+ booleanLuaUserdata.eqmt(LuaValue val) + +
+           
+static booleanLuaValue.eqmtcall(LuaValue lhs, + LuaValue lhsmt, + LuaValue rhs, + LuaValue rhsmt) + +
+          Perform equality testing metatag processing
+protected  VarargsLuaClosure.execute(LuaValue[] stack, + Varargs varargs) + +
+           
+ LuaValueLuaTable.foreach(LuaValue func) + +
+          Call the supplied function once for each key-value pair
+ LuaValueLuaTable.foreachi(LuaValue func) + +
+          Call the supplied function once for each key-value pair + in the contiguous array part
+ LuaValueLuaString.get(LuaValue key) + +
+           
+ LuaValueLuaTable.get(LuaValue key) + +
+           
+ LuaValueLuaUserdata.get(LuaValue key) + +
+           
+ LuaValueLuaValue.get(LuaValue key) + +
+          Get a value in a table including metatag processing using INDEX.
+protected static LuaValueLuaValue.gettable(LuaValue t, + LuaValue key) + +
+          get value from metatable operations, or NIL if not defined by metatables
+ booleanLuaDouble.gt_b(LuaValue rhs) + +
+           
+ booleanLuaInteger.gt_b(LuaValue rhs) + +
+           
+ booleanLuaString.gt_b(LuaValue rhs) + +
+           
+ booleanLuaValue.gt_b(LuaValue rhs) + +
+          Greater than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ LuaValueLuaDouble.gt(LuaValue rhs) + +
+           
+ LuaValueLuaInteger.gt(LuaValue rhs) + +
+           
+ LuaValueLuaString.gt(LuaValue rhs) + +
+           
+ LuaValueLuaValue.gt(LuaValue rhs) + +
+          Greater than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ booleanLuaDouble.gteq_b(LuaValue rhs) + +
+           
+ booleanLuaInteger.gteq_b(LuaValue rhs) + +
+           
+ booleanLuaString.gteq_b(LuaValue rhs) + +
+           
+ booleanLuaValue.gteq_b(LuaValue rhs) + +
+          Greater than or equals: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ LuaValueLuaDouble.gteq(LuaValue rhs) + +
+           
+ LuaValueLuaInteger.gteq(LuaValue rhs) + +
+           
+ LuaValueLuaString.gteq(LuaValue rhs) + +
+           
+ LuaValueLuaValue.gteq(LuaValue rhs) + +
+          Greater than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ intLuaTable.hashFindSlot(LuaValue key) + +
+          Find the hashtable slot to use
+ intWeakTable.hashFindSlot(LuaValue key) + +
+           
+protected  LuaValueLuaTable.hashget(LuaValue key) + +
+           
+protected  LuaValueWeakTable.hashget(LuaValue key) + +
+          Get the hash value for a key + key the key to look up
+ voidLuaTable.hashset(LuaValue key, + LuaValue value) + +
+          Set a hashtable value
+ VarargsLuaTable.inext(LuaValue key) + +
+          Get the next element after a particular key in the + contiguous array part of a table
+ VarargsLuaValue.inext(LuaValue index) + +
+          Find the next integer-key,value pair if this is a table, + return NIL if there are no more, or throw a LuaError if not a table.
+ voidLuaTable.insert(int pos, + LuaValue value) + +
+          Insert an element at a position in a list-table
+ VarargsLuaValue.invoke(LuaValue[] args) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invoke(LuaValue[] args, + Varargs varargs) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invoke(LuaValue arg1, + LuaValue arg2, + Varargs varargs) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invoke(LuaValue arg, + Varargs varargs) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invokemethod(LuaValue name) + +
+          Call named method on this with 0 arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invokemethod(LuaValue name, + LuaValue[] args) + +
+          Call named method on this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invokemethod(LuaValue name, + LuaValue[] args) + +
+          Call named method on this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invokemethod(LuaValue name, + Varargs args) + +
+          Call named method on this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invokemethod(java.lang.String name, + LuaValue[] args) + +
+          Call named method on this with 1 argument, including metatag processing, + and retain all return values in a Varargs.
+static LuaTableLuaValue.listOf(LuaValue[] unnamedValues) + +
+          Construct a LuaTable initialized with supplied array values.
+static LuaTableLuaValue.listOf(LuaValue[] unnamedValues, + Varargs lastarg) + +
+          Construct a LuaTable initialized with supplied array values.
+static LuaFunctionLoadState.load(java.io.InputStream stream, + java.lang.String name, + LuaValue env) + +
+          Load lua in either binary or text form from an input stream.
+ LuaFunctionLoadState.LuaCompiler.load(java.io.InputStream stream, + java.lang.String filename, + LuaValue env) + +
+          Load into a Closure or LuaFunction from a Stream and initializes the environment
+ LuaValueLuaValue.load(LuaValue library) + +
+          Load a library instance by setting its environment to this + and calling it, which should iniitalize the library instance and + install itself into this instance.
+ booleanLuaDouble.lt_b(LuaValue rhs) + +
+           
+ booleanLuaInteger.lt_b(LuaValue rhs) + +
+           
+ booleanLuaString.lt_b(LuaValue rhs) + +
+           
+ booleanLuaValue.lt_b(LuaValue rhs) + +
+          Less than: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ LuaValueLuaDouble.lt(LuaValue rhs) + +
+           
+ LuaValueLuaInteger.lt(LuaValue rhs) + +
+           
+ LuaValueLuaString.lt(LuaValue rhs) + +
+           
+ LuaValueLuaValue.lt(LuaValue rhs) + +
+          Less than: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ booleanLuaDouble.lteq_b(LuaValue rhs) + +
+           
+ booleanLuaInteger.lteq_b(LuaValue rhs) + +
+           
+ booleanLuaString.lteq_b(LuaValue rhs) + +
+           
+ booleanLuaValue.lteq_b(LuaValue rhs) + +
+          Less than or equals: Perform numeric or string comparison with another value + of unknown type, including metatag processing, + and returning java boolean.
+ LuaValueLuaDouble.lteq(LuaValue rhs) + +
+           
+ LuaValueLuaInteger.lteq(LuaValue rhs) + +
+           
+ LuaValueLuaString.lteq(LuaValue rhs) + +
+           
+ LuaValueLuaValue.lteq(LuaValue rhs) + +
+          Less than or equals: Perform numeric or string comparison with another value + of unknown type, + including metatag processing, and returning LuaValue.
+ LuaValueLuaValue.metatag(LuaValue tag) + +
+          Get particular metatag, or return NIL if it doesn't exist
+ LuaValueLuaValue.method(LuaValue name) + +
+          Call named method on this with 0 arguments, including metatag processing, + and return only the first return value.
+ LuaValueLuaValue.method(LuaValue name, + LuaValue arg) + +
+          Call named method on this with 1 argument, including metatag processing, + and return only the first return value.
+ LuaValueLuaValue.method(LuaValue name, + LuaValue arg1, + LuaValue arg2) + +
+          Call named method on this with 2 arguments, including metatag processing, + and return only the first return value.
+ LuaValueLuaValue.method(java.lang.String name, + LuaValue arg) + +
+          Call named method on this with 1 argument, including metatag processing, + and return only the first return value.
+ LuaValueLuaValue.method(java.lang.String name, + LuaValue arg1, + LuaValue arg2) + +
+          Call named method on this with 2 arguments, including metatag processing, + and return only the first return value.
+ LuaValueLuaDouble.mod(LuaValue rhs) + +
+           
+ LuaValueLuaInteger.mod(LuaValue rhs) + +
+           
+ LuaValueLuaString.mod(LuaValue rhs) + +
+           
+ LuaValueLuaValue.mod(LuaValue rhs) + +
+          Modulo: Perform numeric modulo operation with another value + of unknown type, + including metatag processing.
+ LuaValueLuaDouble.mul(LuaValue rhs) + +
+           
+ LuaValueLuaInteger.mul(LuaValue rhs) + +
+           
+ LuaValueLuaString.mul(LuaValue rhs) + +
+           
+ LuaValueLuaValue.mul(LuaValue rhs) + +
+          Multiply: Perform numeric multiply operation with another value + of unknown type, + including metatag processing.
+ booleanLuaValue.neq_b(LuaValue val) + +
+          Notquals: Perform inequality comparison with another value + including metatag processing using EQ.
+ LuaValueLuaValue.neq(LuaValue val) + +
+          Notquals: Perform inequality comparison with another value + including metatag processing using EQ.
+ VarargsLuaTable.next(LuaValue key) + +
+          Get the next element after a particular key in the table
+ VarargsLuaValue.next(LuaValue index) + +
+          Find the next key,value pair if this is a table, + return NIL if there are no more, or throw a LuaError if not a table.
+ VarargsWeakTable.next(LuaValue key) + +
+          Get the next element after a particular key in the table
+ LuaValueVarargs.optvalue(int i, + LuaValue defval) + +
+          Return argument i as a LuaValue if it exists, or defval.
+ LuaValueLuaNil.optvalue(LuaValue defval) + +
+           
+ LuaValueLuaValue.optvalue(LuaValue defval) + +
+          Perform argument check that this is not nil or none.
+ LuaValueLuaValue.or(LuaValue rhs) + +
+          Perform boolean or with another operand, based on lua rules for boolean evaluation.
+ LuaValueLuaDouble.pow(LuaValue rhs) + +
+           
+ LuaValueLuaInteger.pow(LuaValue rhs) + +
+           
+ LuaValueLuaString.pow(LuaValue rhs) + +
+           
+ LuaValueLuaValue.pow(LuaValue rhs) + +
+          Raise to power: Raise this value to a power + including metatag processing.
+static voidPrint.printState(LuaClosure cl, + int pc, + LuaValue[] stack, + int top, + Varargs varargs) + +
+          Print the state of a LuaClosure that is being executed
+ booleanLuaDouble.raweq(LuaValue val) + +
+           
+ booleanLuaInteger.raweq(LuaValue val) + +
+           
+ booleanLuaString.raweq(LuaValue val) + +
+           
+ booleanLuaUserdata.raweq(LuaValue val) + +
+           
+ booleanLuaValue.raweq(LuaValue val) + +
+          Equals: Perform direct equality comparison with another value + without metatag processing.
+ LuaValueLuaTable.rawget(LuaValue key) + +
+           
+ LuaValueLuaValue.rawget(LuaValue key) + +
+          Get a value in a table without metatag processing.
+ LuaValueWeakTable.rawget(LuaValue key) + +
+           
+ voidLuaTable.rawset(int key, + LuaValue value) + +
+           
+ voidLuaValue.rawset(int key, + LuaValue value) + +
+          Set a value in a table without metatag processing.
+ voidWeakTable.rawset(int key, + LuaValue value) + +
+           
+ voidLuaTable.rawset(LuaValue key, + LuaValue value) + +
+          caller must ensure key is not nil
+ voidLuaValue.rawset(LuaValue key, + LuaValue value) + +
+          Set a value in a table without metatag processing.
+ voidWeakTable.rawset(LuaValue key, + LuaValue value) + +
+           
+ voidLuaValue.rawset(java.lang.String key, + LuaValue value) + +
+          Set a value in a table without metatag processing.
+ voidLuaTable.set(int key, + LuaValue value) + +
+           
+ voidLuaValue.set(int key, + LuaValue value) + +
+          Set a value in a table without metatag processing using NEWINDEX.
+ voidLuaTable.set(LuaValue key, + LuaValue value) + +
+          caller must ensure key is not nil
+ voidLuaUserdata.set(LuaValue key, + LuaValue value) + +
+           
+ voidLuaValue.set(LuaValue key, + LuaValue value) + +
+          Set a value in a table without metatag processing using NEWINDEX.
+ voidLuaValue.set(java.lang.String key, + LuaValue value) + +
+          Set a value in a table without metatag processing using NEWINDEX.
+static LuaValueLuaThread.setErrorFunc(LuaValue errfunc) + +
+          Replace the error function of the currently running thread.
+ voidLuaFunction.setfenv(LuaValue env) + +
+           
+ voidLuaThread.setfenv(LuaValue env) + +
+           
+ voidLuaValue.setfenv(LuaValue env) + +
+          Set the environment on an object.
+static voidLuaThread.setGlobals(LuaValue globals) + +
+          Set the globals of the current thread.
+ LuaValueLuaTable.setmetatable(LuaValue metatable) + +
+           
+ LuaValueLuaUserdata.setmetatable(LuaValue metatable) + +
+           
+ LuaValueLuaValue.setmetatable(LuaValue metatable) + +
+          Set the metatable for this LuaValue
+protected static booleanLuaValue.settable(LuaValue t, + LuaValue key, + LuaValue value) + +
+          Perform field assignment including metatag processing.
+protected  voidLuaClosure.setUpvalue(int i, + LuaValue v) + +
+           
+ BufferBuffer.setvalue(LuaValue value) + +
+          Set buffer contents as a LuaValue
+ voidUpValue.setValue(LuaValue value) + +
+          Set the value of the upvalue
+ voidLuaTable.sort(LuaValue comparator) + +
+          Sort the table using a comparator.
+ voidWeakTable.sort(LuaValue comparator) + +
+           
+ intLuaString.strcmp(LuaValue lhs) + +
+           
+ intLuaValue.strcmp(LuaValue rhs) + +
+          Perform string comparison with another value + of any type + using string comparison based on byte values.
+ LuaValueLuaDouble.sub(LuaValue rhs) + +
+           
+ LuaValueLuaInteger.sub(LuaValue rhs) + +
+           
+ LuaValueLuaString.sub(LuaValue rhs) + +
+           
+ LuaValueLuaValue.sub(LuaValue rhs) + +
+          Subtract: Perform numeric subtract operation with another value + of unknown type, + including metatag processing.
+static LuaTableLuaValue.tableOf(LuaValue[] namedValues) + +
+          Construct a LuaTable initialized with supplied named values.
+static LuaTableLuaValue.tableOf(LuaValue[] namedValues, + LuaValue[] unnamedValues) + +
+          Construct a LuaTable initialized with supplied named values and sequential elements.
+static LuaTableLuaValue.tableOf(LuaValue[] namedValues, + LuaValue[] unnamedValues) + +
+          Construct a LuaTable initialized with supplied named values and sequential elements.
+static LuaTableLuaValue.tableOf(LuaValue[] namedValues, + LuaValue[] unnamedValues, + Varargs lastarg) + +
+          Construct a LuaTable initialized with supplied named values and sequential elements in an array part and as varargs.
+static LuaTableLuaValue.tableOf(LuaValue[] namedValues, + LuaValue[] unnamedValues, + Varargs lastarg) + +
+          Construct a LuaTable initialized with supplied named values and sequential elements in an array part and as varargs.
+static VarargsLuaValue.tailcallOf(LuaValue func, + Varargs args) + +
+          Construct a TailcallVarargs around a function and arguments.
+ booleanLuaValue.testfor_b(LuaValue limit, + LuaValue step) + +
+          Perform end-condition test in for-loop processing.
+static LuaUserdataLuaValue.userdataOf(java.lang.Object o, + LuaValue metatable) + +
+          Construct a LuaUserdata for an object with a user supplied metatable.
+static VarargsLuaValue.varargsOf(LuaValue[] v) + +
+          Construct a Varargs around an array of LuaValues.
+static VarargsLuaValue.varargsOf(LuaValue[] v, + int offset, + int length) + +
+          Construct a Varargs around an array of LuaValues.
+static VarargsLuaValue.varargsOf(LuaValue[] v, + int offset, + int length, + Varargs more) + +
+          Construct a Varargs around an array of LuaValues.
+static VarargsLuaValue.varargsOf(LuaValue[] v, + Varargs r) + +
+          Construct a Varargs around an array of LuaValues.
+static VarargsLuaValue.varargsOf(LuaValue v1, + LuaValue v2, + Varargs v3) + +
+          Construct a Varargs around a set of 3 or more LuaValues.
+static VarargsLuaValue.varargsOf(LuaValue v, + Varargs r) + +
+          Construct a Varargs around a set of 2 or more LuaValues.
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Constructors in org.luaj.vm2 with parameters of type LuaValue
Buffer(LuaValue value) + +
+          Create buffer with specified initial value
LuaClosure(int nupvalues, + LuaValue env) + +
+           
LuaClosure(Prototype p, + LuaValue env) + +
+          Supply the initial environment
LuaFunction(LuaValue env) + +
+           
LuaTable(LuaValue[] named, + LuaValue[] unnamed, + Varargs lastarg) + +
+          Construct table with named and unnamed parts.
LuaTable(LuaValue[] named, + LuaValue[] unnamed, + Varargs lastarg) + +
+          Construct table with named and unnamed parts.
LuaThread(LuaValue func, + LuaValue env) + +
+          Create a LuaThread around a function and environment
LuaUserdata(java.lang.Object obj, + LuaValue metatable) + +
+           
TailcallVarargs(LuaValue object, + LuaValue methodname, + Varargs args) + +
+           
TailcallVarargs(LuaValue f, + Varargs args) + +
+           
UpValue(LuaValue[] stack, + int index) + +
+          Create an upvalue relative to a stack
+  +

+ + + + + +
+Uses of LuaValue in org.luaj.vm2.compiler
+  +

+ + + + + + + + + + + + + +
Methods in org.luaj.vm2.compiler with parameters of type LuaValue
+ LuaFunctionLuaC.load(java.io.InputStream stream, + java.lang.String name, + LuaValue env) + +
+          Load into a Closure or LuaFunction, with the supplied initial environment
+ LuaFunctionLuaC.load(Prototype p, + java.lang.String filename, + LuaValue env) + +
+           
+  +

+ + + + + +
+Uses of LuaValue in org.luaj.vm2.lib
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Subclasses of LuaValue in org.luaj.vm2.lib
+ classBaseLib + +
+          Subclass of LibFunction which implements the lua basic library functions.
+ classCoroutineLib + +
+          Subclass of LibFunction which implements the lua standard coroutine + library.
+ classDebugLib + +
+          Subclass of LibFunction which implements the lua standard debug + library.
+ classIoLib + +
+          Abstract base class extending LibFunction which implements the + core of the lua standard io library.
+protected  classIoLib.File + +
+           
+ classLibFunction + +
+          Subclass of LuaFunction common to Java functions exposed to lua.
+ classMathLib + +
+          Subclass of LibFunction which implements the lua standard math + library.
+ classOneArgFunction + +
+          Abstract base class for Java function implementations that take one argument and + return one value.
+ classOsLib + +
+          Subclass of LibFunction which implements the standard lua os library.
+ classPackageLib + +
+          Subclass of LibFunction which implements the lua standard package and module + library functions.
+ classStringLib + +
+          Subclass of LibFunction which implements the lua standard string + library.
+ classTableLib + +
+          Subclass of LibFunction which implements the lua standard table + library.
+ classThreeArgFunction + +
+          Abstract base class for Java function implementations that take two arguments and + return one value.
+ classTwoArgFunction + +
+          Abstract base class for Java function implementations that take two arguments and + return one value.
+ classVarArgFunction + +
+          Abstract base class for Java function implementations that takes varaiable arguments and + returns multiple return values.
+ classZeroArgFunction + +
+          Abstract base class for Java function implementations that take no arguments and + return one value.
+  +

+ + + + + + + + + + + + + + + + + +
Fields in org.luaj.vm2.lib declared as LuaValue
+ LuaValuePackageLib.java_loader + +
+          Loader that loads as a Java class.
+ LuaValuePackageLib.lua_loader + +
+          Loader that loads as a lua script using the LUA_PATH
+ LuaValuePackageLib.preload_loader + +
+          Loader that loads from preload table if found there
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2.lib that return LuaValue
+ LuaValueOneArgFunction.call() + +
+           
+ LuaValueThreeArgFunction.call() + +
+           
+ LuaValueTwoArgFunction.call() + +
+           
+ LuaValueVarArgFunction.call() + +
+           
+abstract  LuaValueZeroArgFunction.call() + +
+           
+ LuaValueBaseLib.call(LuaValue arg) + +
+           
+ LuaValueIoLib.call(LuaValue arg) + +
+           
+ LuaValueMathLib.call(LuaValue arg) + +
+           
+abstract  LuaValueOneArgFunction.call(LuaValue arg) + +
+           
+ LuaValuePackageLib.call(LuaValue arg) + +
+           
+ LuaValueStringLib.call(LuaValue arg) + +
+           
+ LuaValueTableLib.call(LuaValue arg) + +
+           
+ LuaValueThreeArgFunction.call(LuaValue arg) + +
+           
+ LuaValueTwoArgFunction.call(LuaValue arg) + +
+           
+ LuaValueVarArgFunction.call(LuaValue arg) + +
+           
+ LuaValueZeroArgFunction.call(LuaValue arg) + +
+           
+ LuaValueOneArgFunction.call(LuaValue arg1, + LuaValue arg2) + +
+           
+ LuaValueThreeArgFunction.call(LuaValue arg1, + LuaValue arg2) + +
+           
+abstract  LuaValueTwoArgFunction.call(LuaValue arg1, + LuaValue arg2) + +
+           
+ LuaValueVarArgFunction.call(LuaValue arg1, + LuaValue arg2) + +
+           
+ LuaValueZeroArgFunction.call(LuaValue arg1, + LuaValue arg2) + +
+           
+ LuaValueOneArgFunction.call(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+           
+abstract  LuaValueThreeArgFunction.call(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+           
+ LuaValueTwoArgFunction.call(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+           
+ LuaValueVarArgFunction.call(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+           
+ LuaValueZeroArgFunction.call(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+           
+static LuaValueMathLib.dpow(double a, + double b) + +
+          compute power using installed math library, or default if there is no math library installed
+static LuaValueIoLib.freadall(IoLib.File f) + +
+           
+static LuaValueIoLib.freadbytes(IoLib.File f, + int count) + +
+           
+static LuaValueIoLib.freadline(IoLib.File f) + +
+           
+static LuaValueIoLib.freadnumber(IoLib.File f) + +
+           
+static LuaValueIoLib.freaduntil(IoLib.File f, + boolean lineonly) + +
+           
+ LuaValueIoLib.File.get(LuaValue key) + +
+           
+ LuaValueOsLib.init() + +
+           
+protected static LuaValue[]LibFunction.newupe() + +
+          Java code generation utility to allocate storage for upvalue, leave it empty
+protected static LuaValue[]LibFunction.newupl(LuaValue v) + +
+          Java code generation utility to allocate storage for upvalue, initialize with value
+protected static LuaValue[]LibFunction.newupn() + +
+          Java code generation utility to allocate storage for upvalue, initialize with nil
+ LuaValuePackageLib.require(LuaValue arg) + +
+          require (modname) + + Loads the given module.
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2.lib with parameters of type LuaValue
+ VarargsIoLib._file_close(LuaValue file) + +
+           
+ VarargsIoLib._file_flush(LuaValue file) + +
+           
+ VarargsIoLib._file_lines(LuaValue file) + +
+           
+ VarargsIoLib._file_read(LuaValue file, + Varargs subargs) + +
+           
+ VarargsIoLib._file_seek(LuaValue file, + java.lang.String whence, + int offset) + +
+           
+ VarargsIoLib._file_setvbuf(LuaValue file, + java.lang.String mode, + int size) + +
+           
+ VarargsIoLib._file_write(LuaValue file, + Varargs subargs) + +
+           
+protected static VarargsDebugLib._getinfo(Varargs args, + LuaValue level0func) + +
+           
+ VarargsIoLib._io_close(LuaValue file) + +
+           
+ VarargsIoLib._io_index(LuaValue v) + +
+           
+ VarargsIoLib._io_input(LuaValue file) + +
+           
+ VarargsIoLib._io_output(LuaValue filename) + +
+           
+ VarargsIoLib._io_type(LuaValue obj) + +
+           
+ VarargsIoLib._lines_iter(LuaValue file) + +
+           
+protected  voidLibFunction.bind(LuaValue env, + java.lang.Class factory, + java.lang.String[] names) + +
+          Bind a set of library functions.
+protected  voidLibFunction.bind(LuaValue env, + java.lang.Class factory, + java.lang.String[] names, + int firstopcode) + +
+          Bind a set of library functions, with an offset
+ LuaValueBaseLib.call(LuaValue arg) + +
+           
+ LuaValueIoLib.call(LuaValue arg) + +
+           
+ LuaValueMathLib.call(LuaValue arg) + +
+           
+abstract  LuaValueOneArgFunction.call(LuaValue arg) + +
+           
+ LuaValuePackageLib.call(LuaValue arg) + +
+           
+ LuaValueStringLib.call(LuaValue arg) + +
+           
+ LuaValueTableLib.call(LuaValue arg) + +
+           
+ LuaValueThreeArgFunction.call(LuaValue arg) + +
+           
+ LuaValueTwoArgFunction.call(LuaValue arg) + +
+           
+ LuaValueVarArgFunction.call(LuaValue arg) + +
+           
+ LuaValueZeroArgFunction.call(LuaValue arg) + +
+           
+ LuaValueOneArgFunction.call(LuaValue arg1, + LuaValue arg2) + +
+           
+ LuaValueThreeArgFunction.call(LuaValue arg1, + LuaValue arg2) + +
+           
+abstract  LuaValueTwoArgFunction.call(LuaValue arg1, + LuaValue arg2) + +
+           
+ LuaValueVarArgFunction.call(LuaValue arg1, + LuaValue arg2) + +
+           
+ LuaValueZeroArgFunction.call(LuaValue arg1, + LuaValue arg2) + +
+           
+ LuaValueOneArgFunction.call(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+           
+abstract  LuaValueThreeArgFunction.call(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+           
+ LuaValueTwoArgFunction.call(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+           
+ LuaValueVarArgFunction.call(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+           
+ LuaValueZeroArgFunction.call(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+           
+static voidDebugLib.debugSetupCall(Varargs args, + LuaValue[] stack) + +
+          Called by Closures to set up stack and arguments to next call
+ LuaValueIoLib.File.get(LuaValue key) + +
+           
+protected static LuaValue[]LibFunction.newupl(LuaValue v) + +
+          Java code generation utility to allocate storage for upvalue, initialize with value
+static VarargsBaseLib.pcall(LuaValue func, + Varargs args, + LuaValue errfunc) + +
+           
+ LuaValuePackageLib.require(LuaValue arg) + +
+          require (modname) + + Loads the given module.
+  +

+ + + + + + + + + + + + + + + + + + + + +
Constructors in org.luaj.vm2.lib with parameters of type LuaValue
OneArgFunction(LuaValue env) + +
+          Constructor with specific environment
ThreeArgFunction(LuaValue env) + +
+          Constructor with specific environment
TwoArgFunction(LuaValue env) + +
+          Constructor with specific environment
VarArgFunction(LuaValue env) + +
+           
ZeroArgFunction(LuaValue env) + +
+          Constructor with specific environment
+  +

+ + + + + +
+Uses of LuaValue in org.luaj.vm2.lib.jme
+  +

+ + + + + + + + + +
Subclasses of LuaValue in org.luaj.vm2.lib.jme
+ classJmeIoLib + +
+          Subclass of IoLib and therefore LibFunction which implements the lua standard io + library for the JSE platform.
+  +

+ + + + + +
+Uses of LuaValue in org.luaj.vm2.lib.jse
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Subclasses of LuaValue in org.luaj.vm2.lib.jse
+ classJseBaseLib + +
+          Subclass of BaseLib and LibFunction which implements the lua basic library functions + and provides a directory based ResourceFinder as the BaseLib.FINDER.
+ classJseIoLib + +
+          Subclass of IoLib and therefore LibFunction which implements the lua standard io + library for the JSE platform.
+ classJseMathLib + +
+          Subclass of LibFunction which implements the lua standard math + library.
+static classJseMathLib.JseMathLib1 + +
+           
+static classJseMathLib.JseMathLib2 + +
+           
+ classJseOsLib + +
+          Subclass of LibFunction which implements the standard lua os library.
+ classLuajavaLib + +
+          Subclass of LibFunction which implements the features of the luajava package.
+  +

+ + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2.lib.jse that return LuaValue
+ LuaValueJseMathLib.call(LuaValue arg) + +
+           
+ LuaValueJseMathLib.JseMathLib1.call(LuaValue arg) + +
+           
+ LuaValueJseMathLib.JseMathLib2.call(LuaValue arg1, + LuaValue arg2) + +
+           
+static LuaValueCoerceJavaToLua.coerce(java.lang.Object o) + +
+          Coerse a Java object to a corresponding lua value.
+  +

+ + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2.lib.jse with parameters of type LuaValue
+ LuaValueJseMathLib.call(LuaValue arg) + +
+           
+ LuaValueJseMathLib.JseMathLib1.call(LuaValue arg) + +
+           
+ LuaValueJseMathLib.JseMathLib2.call(LuaValue arg1, + LuaValue arg2) + +
+           
+static java.lang.ObjectCoerceLuaToJava.coerce(LuaValue value, + java.lang.Class clazz) + +
+          Coerce a LuaValue value to a specified java class
+  +

+ + + + + +
+Uses of LuaValue in org.luaj.vm2.luajc
+  +

+ + + + + + + + + +
Methods in org.luaj.vm2.luajc with parameters of type LuaValue
+ LuaFunctionLuaJC.load(java.io.InputStream stream, + java.lang.String name, + LuaValue env) + +
+           
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/OrphanedThread.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/OrphanedThread.html new file mode 100644 index 0000000000..5c88139d74 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/OrphanedThread.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.OrphanedThread (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.OrphanedThread

+
+No usage of org.luaj.vm2.OrphanedThread +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/Print.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/Print.html new file mode 100644 index 0000000000..e3a2c99125 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/Print.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.Print (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.Print

+
+No usage of org.luaj.vm2.Print +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/Prototype.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/Prototype.html new file mode 100644 index 0000000000..4c88989f1e --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/Prototype.html @@ -0,0 +1,358 @@ + + + + + + +Uses of Class org.luaj.vm2.Prototype (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.Prototype

+
+ + + + + + + + + + + + + + + + + +
+Packages that use Prototype
org.luaj.vm2  
org.luaj.vm2.compiler  
org.luaj.vm2.lib  
+  +

+ + + + + +
+Uses of Prototype in org.luaj.vm2
+  +

+ + + + + + + + + + + + + +
Fields in org.luaj.vm2 declared as Prototype
+ PrototypeLuaClosure.p + +
+           
+ Prototype[]Prototype.p + +
+           
+  +

+ + + + + + + + + + + + + +
Methods in org.luaj.vm2 that return Prototype
+static PrototypeLoadState.loadBinaryChunk(int firstByte, + java.io.InputStream stream, + java.lang.String name) + +
+          Load lua thought to be a binary chunk from its first byte from an input stream.
+ PrototypeLoadState.loadFunction(LuaString p) + +
+          Load a function prototype from the input stream
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 with parameters of type Prototype
+static voidPrint.print(Prototype p) + +
+           
+static voidPrint.printCode(Prototype f) + +
+          Print the code in a prototype
+static voidPrint.printFunction(Prototype f, + boolean full) + +
+           
+static voidPrint.printOpCode(java.io.PrintStream ps, + Prototype f, + int pc) + +
+          Print an opcode in a prototype
+static voidPrint.printOpCode(Prototype f, + int pc) + +
+          Print an opcode in a prototype
+  +

+ + + + + + + + +
Constructors in org.luaj.vm2 with parameters of type Prototype
LuaClosure(Prototype p, + LuaValue env) + +
+          Supply the initial environment
+  +

+ + + + + +
+Uses of Prototype in org.luaj.vm2.compiler
+  +

+ + + + + + + + + +
Methods in org.luaj.vm2.compiler that return Prototype
+static PrototypeLuaC.compile(java.io.InputStream stream, + java.lang.String name) + +
+          Compile a prototype or load as a binary chunk
+  +

+ + + + + + + + + +
Methods in org.luaj.vm2.compiler with parameters of type Prototype
+ LuaFunctionLuaC.load(Prototype p, + java.lang.String filename, + LuaValue env) + +
+           
+  +

+ + + + + +
+Uses of Prototype in org.luaj.vm2.lib
+  +

+ + + + + + + + + +
Methods in org.luaj.vm2.lib with parameters of type Prototype
+static java.lang.StringDebugLib.sourceshort(Prototype p) + +
+           
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/TailcallVarargs.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/TailcallVarargs.html new file mode 100644 index 0000000000..7b29e0d333 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/TailcallVarargs.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.TailcallVarargs (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.TailcallVarargs

+
+No usage of org.luaj.vm2.TailcallVarargs +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/UpValue.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/UpValue.html new file mode 100644 index 0000000000..c8da51796a --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/UpValue.html @@ -0,0 +1,180 @@ + + + + + + +Uses of Class org.luaj.vm2.UpValue (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.UpValue

+
+ + + + + + + + + +
+Packages that use UpValue
org.luaj.vm2  
+  +

+ + + + + +
+Uses of UpValue in org.luaj.vm2
+  +

+ + + + + + + + + +
Fields in org.luaj.vm2 declared as UpValue
+ UpValue[]LuaClosure.upValues + +
+           
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/Varargs.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/Varargs.html new file mode 100644 index 0000000000..a5ab9be466 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/Varargs.html @@ -0,0 +1,1649 @@ + + + + + + +Uses of Class org.luaj.vm2.Varargs (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.Varargs

+
+ + + + + + + + + + + + + + + + + + + + + +
+Packages that use Varargs
org.luaj.vm2  
org.luaj.vm2.lib  
org.luaj.vm2.lib.jme  
org.luaj.vm2.lib.jse  
+  +

+ + + + + +
+Uses of Varargs in org.luaj.vm2
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Subclasses of Varargs in org.luaj.vm2
+ classLuaBoolean + +
+          Extension of LuaValue which can hold a Java boolean as its value.
+ classLuaClosure + +
+          Extension of LuaFunction which executes lua bytecode.
+ classLuaDouble + +
+          Extension of LuaNumber which can hold a Java double as its value.
+ classLuaFunction + +
+          Base class for functions implemented in Java.
+ classLuaInteger + +
+          Extension of LuaNumber which can hold a Java int as its value.
+ classLuaNil + +
+          Class to encapsulate behavior of the singleton instance nil
+ classLuaNumber + +
+          Base class for representing numbers as lua values directly.
+ classLuaString + +
+          Subclass of LuaValue for representing lua strings.
+ classLuaTable + +
+          Subclass of LuaValue for representing lua tables.
+ classLuaThread + +
+          Subclass of LuaValue that implements + a lua coroutine thread using Java Threads.
+ classLuaUserdata + +
+           
+ classLuaValue + +
+          Base class for all concrete lua type values.
+ classTailcallVarargs + +
+          Subclass of Varargs that represents a lua tail call + in a Java library function execution environment.
+ classWeakTable + +
+          Subclass of LuaTable that provides weak key and weak value semantics.
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 that return Varargs
+ VarargsTailcallVarargs.eval() + +
+           
+ VarargsVarargs.eval() + +
+          Evaluate any pending tail call and return result.
+protected  VarargsLuaClosure.execute(LuaValue[] stack, + Varargs varargs) + +
+           
+ VarargsLuaTable.inext(LuaValue key) + +
+          Get the next element after a particular key in the + contiguous array part of a table
+ VarargsLuaValue.inext(LuaValue index) + +
+          Find the next integer-key,value pair if this is a table, + return NIL if there are no more, or throw a LuaError if not a table.
+ VarargsLuaValue.invoke() + +
+          Call this with 0 arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invoke(LuaValue[] args) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invoke(LuaValue[] args, + Varargs varargs) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invoke(LuaValue arg1, + LuaValue arg2, + Varargs varargs) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invoke(LuaValue arg, + Varargs varargs) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaClosure.invoke(Varargs varargs) + +
+           
+ VarargsLuaValue.invoke(Varargs args) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invokemethod(LuaValue name) + +
+          Call named method on this with 0 arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invokemethod(LuaValue name, + LuaValue[] args) + +
+          Call named method on this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invokemethod(LuaValue name, + Varargs args) + +
+          Call named method on this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invokemethod(java.lang.String name) + +
+          Call named method on this with 0 arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invokemethod(java.lang.String name, + LuaValue[] args) + +
+          Call named method on this with 1 argument, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invokemethod(java.lang.String name, + Varargs args) + +
+          Call named method on this with 1 argument, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaTable.next(LuaValue key) + +
+          Get the next element after a particular key in the table
+ VarargsLuaValue.next(LuaValue index) + +
+          Find the next key,value pair if this is a table, + return NIL if there are no more, or throw a LuaError if not a table.
+ VarargsWeakTable.next(LuaValue key) + +
+          Get the next element after a particular key in the table
+ VarargsLuaClosure.onInvoke(Varargs varargs) + +
+           
+ VarargsLuaValue.onInvoke(Varargs args) + +
+          Callback used during tail call processing to invoke the function once.
+ VarargsLuaThread.resume(Varargs args) + +
+          Start or resume this thread
+ VarargsVarargs.subargs(int start) + +
+          Create a Varargs instance containing arguments starting at index start
+static VarargsLuaValue.tailcallOf(LuaValue func, + Varargs args) + +
+          Construct a TailcallVarargs around a function and arguments.
+static VarargsLuaValue.varargsOf(LuaValue[] v) + +
+          Construct a Varargs around an array of LuaValues.
+static VarargsLuaValue.varargsOf(LuaValue[] v, + int offset, + int length) + +
+          Construct a Varargs around an array of LuaValues.
+static VarargsLuaValue.varargsOf(LuaValue[] v, + int offset, + int length, + Varargs more) + +
+          Construct a Varargs around an array of LuaValues.
+static VarargsLuaValue.varargsOf(LuaValue[] v, + Varargs r) + +
+          Construct a Varargs around an array of LuaValues.
+static VarargsLuaValue.varargsOf(LuaValue v1, + LuaValue v2, + Varargs v3) + +
+          Construct a Varargs around a set of 3 or more LuaValues.
+static VarargsLuaValue.varargsOf(LuaValue v, + Varargs r) + +
+          Construct a Varargs around a set of 2 or more LuaValues.
+static VarargsLuaThread.yield(Varargs args) + +
+          Yield the current thread with arguments
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2 with parameters of type Varargs
+protected  VarargsLuaClosure.execute(LuaValue[] stack, + Varargs varargs) + +
+           
+ VarargsLuaValue.invoke(LuaValue[] args, + Varargs varargs) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invoke(LuaValue arg1, + LuaValue arg2, + Varargs varargs) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invoke(LuaValue arg, + Varargs varargs) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaClosure.invoke(Varargs varargs) + +
+           
+ VarargsLuaValue.invoke(Varargs args) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invokemethod(LuaValue name, + Varargs args) + +
+          Call named method on this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ VarargsLuaValue.invokemethod(java.lang.String name, + Varargs args) + +
+          Call named method on this with 1 argument, including metatag processing, + and retain all return values in a Varargs.
+static LuaTableLuaValue.listOf(LuaValue[] unnamedValues, + Varargs lastarg) + +
+          Construct a LuaTable initialized with supplied array values.
+ VarargsLuaClosure.onInvoke(Varargs varargs) + +
+           
+ VarargsLuaValue.onInvoke(Varargs args) + +
+          Callback used during tail call processing to invoke the function once.
+static voidPrint.printState(LuaClosure cl, + int pc, + LuaValue[] stack, + int top, + Varargs varargs) + +
+          Print the state of a LuaClosure that is being executed
+ voidLuaValue.rawsetlist(int key0, + Varargs values) + +
+          Set list values in a table without invoking metatag processing
+ VarargsLuaThread.resume(Varargs args) + +
+          Start or resume this thread
+static LuaTableLuaValue.tableOf(LuaValue[] namedValues, + LuaValue[] unnamedValues, + Varargs lastarg) + +
+          Construct a LuaTable initialized with supplied named values and sequential elements in an array part and as varargs.
+static LuaTableLuaValue.tableOf(Varargs varargs, + int firstarg) + +
+          Construct a LuaTable initialized with supplied array values.
+static VarargsLuaValue.tailcallOf(LuaValue func, + Varargs args) + +
+          Construct a TailcallVarargs around a function and arguments.
+static VarargsLuaValue.varargsOf(LuaValue[] v, + int offset, + int length, + Varargs more) + +
+          Construct a Varargs around an array of LuaValues.
+static VarargsLuaValue.varargsOf(LuaValue[] v, + Varargs r) + +
+          Construct a Varargs around an array of LuaValues.
+static VarargsLuaValue.varargsOf(LuaValue v1, + LuaValue v2, + Varargs v3) + +
+          Construct a Varargs around a set of 3 or more LuaValues.
+static VarargsLuaValue.varargsOf(LuaValue v, + Varargs r) + +
+          Construct a Varargs around a set of 2 or more LuaValues.
+static VarargsLuaThread.yield(Varargs args) + +
+          Yield the current thread with arguments
+  +

+ + + + + + + + + + + + + + + + + + + + +
Constructors in org.luaj.vm2 with parameters of type Varargs
LuaTable(LuaValue[] named, + LuaValue[] unnamed, + Varargs lastarg) + +
+          Construct table with named and unnamed parts.
LuaTable(Varargs varargs) + +
+          Construct table of unnamed elements.
LuaTable(Varargs varargs, + int firstarg) + +
+          Construct table of unnamed elements.
TailcallVarargs(LuaValue object, + LuaValue methodname, + Varargs args) + +
+           
TailcallVarargs(LuaValue f, + Varargs args) + +
+           
+  +

+ + + + + +
+Uses of Varargs in org.luaj.vm2.lib
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Subclasses of Varargs in org.luaj.vm2.lib
+ classBaseLib + +
+          Subclass of LibFunction which implements the lua basic library functions.
+ classCoroutineLib + +
+          Subclass of LibFunction which implements the lua standard coroutine + library.
+ classDebugLib + +
+          Subclass of LibFunction which implements the lua standard debug + library.
+ classIoLib + +
+          Abstract base class extending LibFunction which implements the + core of the lua standard io library.
+protected  classIoLib.File + +
+           
+ classLibFunction + +
+          Subclass of LuaFunction common to Java functions exposed to lua.
+ classMathLib + +
+          Subclass of LibFunction which implements the lua standard math + library.
+ classOneArgFunction + +
+          Abstract base class for Java function implementations that take one argument and + return one value.
+ classOsLib + +
+          Subclass of LibFunction which implements the standard lua os library.
+ classPackageLib + +
+          Subclass of LibFunction which implements the lua standard package and module + library functions.
+ classStringLib + +
+          Subclass of LibFunction which implements the lua standard string + library.
+ classTableLib + +
+          Subclass of LibFunction which implements the lua standard table + library.
+ classThreeArgFunction + +
+          Abstract base class for Java function implementations that take two arguments and + return one value.
+ classTwoArgFunction + +
+          Abstract base class for Java function implementations that take two arguments and + return one value.
+ classVarArgFunction + +
+          Abstract base class for Java function implementations that takes varaiable arguments and + returns multiple return values.
+ classZeroArgFunction + +
+          Abstract base class for Java function implementations that take no arguments and + return one value.
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2.lib that return Varargs
+ VarargsIoLib._file_close(LuaValue file) + +
+           
+ VarargsIoLib._file_flush(LuaValue file) + +
+           
+ VarargsIoLib._file_lines(LuaValue file) + +
+           
+ VarargsIoLib._file_read(LuaValue file, + Varargs subargs) + +
+           
+ VarargsIoLib._file_seek(LuaValue file, + java.lang.String whence, + int offset) + +
+           
+ VarargsIoLib._file_setvbuf(LuaValue file, + java.lang.String mode, + int size) + +
+           
+ VarargsIoLib._file_write(LuaValue file, + Varargs subargs) + +
+           
+protected static VarargsDebugLib._getinfo(Varargs args, + LuaValue level0func) + +
+           
+ VarargsIoLib._io_close(LuaValue file) + +
+           
+ VarargsIoLib._io_flush() + +
+           
+ VarargsIoLib._io_index(LuaValue v) + +
+           
+ VarargsIoLib._io_input(LuaValue file) + +
+           
+ VarargsIoLib._io_lines(java.lang.String filename) + +
+           
+ VarargsIoLib._io_open(java.lang.String filename, + java.lang.String mode) + +
+           
+ VarargsIoLib._io_output(LuaValue filename) + +
+           
+ VarargsIoLib._io_popen(java.lang.String prog, + java.lang.String mode) + +
+           
+ VarargsIoLib._io_read(Varargs args) + +
+           
+ VarargsIoLib._io_tmpfile() + +
+           
+ VarargsIoLib._io_type(LuaValue obj) + +
+           
+ VarargsIoLib._io_write(Varargs args) + +
+           
+ VarargsIoLib._lines_iter(LuaValue file) + +
+           
+static VarargsStringLib.char_(Varargs args) + +
+          string.char (...) + + Receives zero or more integers.
+ VarargsCoroutineLib.invoke(Varargs args) + +
+           
+ VarargsDebugLib.invoke(Varargs args) + +
+           
+ VarargsOneArgFunction.invoke(Varargs varargs) + +
+           
+ VarargsOsLib.invoke(Varargs args) + +
+           
+ VarargsThreeArgFunction.invoke(Varargs varargs) + +
+           
+ VarargsTwoArgFunction.invoke(Varargs varargs) + +
+           
+ VarargsVarArgFunction.invoke(Varargs args) + +
+          Override and implement for the best performance.
+ VarargsZeroArgFunction.invoke(Varargs varargs) + +
+           
+static VarargsBaseLib.loadFile(java.lang.String filename) + +
+          Load from a named file, returning the chunk or nil,error of can't load
+static VarargsPackageLib.loadlib(Varargs args) + +
+           
+static VarargsBaseLib.loadStream(java.io.InputStream is, + java.lang.String chunkname) + +
+           
+ VarargsPackageLib.module(Varargs args) + +
+          module (name [, ...]) + + Creates a module.
+ VarargsVarArgFunction.onInvoke(Varargs args) + +
+          Override to provide a call implementation that runs in an environment + that can participate in setfenv, and behaves as expected + when returning TailcallVarargs.
+static VarargsBaseLib.pcall(LuaValue func, + Varargs args, + LuaValue errfunc) + +
+           
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2.lib with parameters of type Varargs
+ VarargsIoLib._file_read(LuaValue file, + Varargs subargs) + +
+           
+ VarargsIoLib._file_write(LuaValue file, + Varargs subargs) + +
+           
+protected static VarargsDebugLib._getinfo(Varargs args, + LuaValue level0func) + +
+           
+ VarargsIoLib._io_read(Varargs args) + +
+           
+ VarargsIoLib._io_write(Varargs args) + +
+           
+static VarargsStringLib.char_(Varargs args) + +
+          string.char (...) + + Receives zero or more integers.
+static voidDebugLib.debugBytecode(int pc, + Varargs extras, + int top) + +
+          Called by Closures on bytecode execution
+static voidDebugLib.debugSetupCall(Varargs args, + LuaValue[] stack) + +
+          Called by Closures to set up stack and arguments to next call
+ VarargsCoroutineLib.invoke(Varargs args) + +
+           
+ VarargsDebugLib.invoke(Varargs args) + +
+           
+ VarargsOneArgFunction.invoke(Varargs varargs) + +
+           
+ VarargsOsLib.invoke(Varargs args) + +
+           
+ VarargsThreeArgFunction.invoke(Varargs varargs) + +
+           
+ VarargsTwoArgFunction.invoke(Varargs varargs) + +
+           
+ VarargsVarArgFunction.invoke(Varargs args) + +
+          Override and implement for the best performance.
+ VarargsZeroArgFunction.invoke(Varargs varargs) + +
+           
+static VarargsPackageLib.loadlib(Varargs args) + +
+           
+ VarargsPackageLib.module(Varargs args) + +
+          module (name [, ...]) + + Creates a module.
+ VarargsVarArgFunction.onInvoke(Varargs args) + +
+          Override to provide a call implementation that runs in an environment + that can participate in setfenv, and behaves as expected + when returning TailcallVarargs.
+static VarargsBaseLib.pcall(LuaValue func, + Varargs args, + LuaValue errfunc) + +
+           
+  +

+ + + + + +
+Uses of Varargs in org.luaj.vm2.lib.jme
+  +

+ + + + + + + + + +
Subclasses of Varargs in org.luaj.vm2.lib.jme
+ classJmeIoLib + +
+          Subclass of IoLib and therefore LibFunction which implements the lua standard io + library for the JSE platform.
+  +

+ + + + + +
+Uses of Varargs in org.luaj.vm2.lib.jse
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Subclasses of Varargs in org.luaj.vm2.lib.jse
+ classJseBaseLib + +
+          Subclass of BaseLib and LibFunction which implements the lua basic library functions + and provides a directory based ResourceFinder as the BaseLib.FINDER.
+ classJseIoLib + +
+          Subclass of IoLib and therefore LibFunction which implements the lua standard io + library for the JSE platform.
+ classJseMathLib + +
+          Subclass of LibFunction which implements the lua standard math + library.
+static classJseMathLib.JseMathLib1 + +
+           
+static classJseMathLib.JseMathLib2 + +
+           
+ classJseOsLib + +
+          Subclass of LibFunction which implements the standard lua os library.
+ classLuajavaLib + +
+          Subclass of LibFunction which implements the features of the luajava package.
+  +

+ + + + + + + + + +
Methods in org.luaj.vm2.lib.jse that return Varargs
+ VarargsLuajavaLib.invoke(Varargs args) + +
+           
+  +

+ + + + + + + + + +
Methods in org.luaj.vm2.lib.jse with parameters of type Varargs
+ VarargsLuajavaLib.invoke(Varargs args) + +
+           
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/WeakTable.html b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/WeakTable.html new file mode 100644 index 0000000000..5dc193e8f8 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/class-use/WeakTable.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.WeakTable (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.WeakTable

+
+No usage of org.luaj.vm2.WeakTable +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/compiler/LuaC.html b/luaj-2.0.3/docs/api/org/luaj/vm2/compiler/LuaC.html new file mode 100644 index 0000000000..ecf32c883f --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/compiler/LuaC.html @@ -0,0 +1,543 @@ + + + + + + +LuaC (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.compiler +
+Class LuaC

+
+java.lang.Object
+  extended by org.luaj.vm2.Lua
+      extended by org.luaj.vm2.compiler.LuaC
+
+
+
All Implemented Interfaces:
LoadState.LuaCompiler
+
+
+
+
public class LuaC
extends Lua
implements LoadState.LuaCompiler
+ + +

+Compiler for Lua. +

+ Compiles lua source files into lua bytecode within a Prototype, + loads lua binary files directly into aPrototype, + and optionaly instantiates a LuaClosure around the result + using a user-supplied environment. +

+ Implements the LoadState.LuaCompiler interface for loading + initialized chunks, which is an interface common to + lua bytecode compiling and java bytecode compiling. +

+ Teh LuaC compiler is installed by default by both the + JsePlatform and JmePlatform classes, + so in the following example, the default LuaC compiler + will be used: +

 LuaValue _G = JsePlatform.standardGlobals();
+ LoadState.load( new ByteArrayInputStream("print 'hello'".getBytes()), "main.lua", _G ).call();
+  
+

+ +

+

+
See Also:
LoadState.LuaCompiler, +LuaJC, +JsePlatform, +JmePlatform, +BaseLib, +LuaValue, +LoadState.LuaCompiler, +Prototype
+
+ +

+ + + + + + + + + + + + + + + + + + + +
+Field Summary
+static LuaCinstance + +
+           
+static intMAXSTACK + +
+           
+ intnCcalls + +
+           
+ + + + + + + +
Fields inherited from class org.luaj.vm2.Lua
_VERSION, BITRK, LFIELDS_PER_FLUSH, LUA_MULTRET, luaP_opmodes, MASK_A, MASK_B, MASK_Bx, MASK_C, MASK_NOT_A, MASK_NOT_B, MASK_NOT_Bx, MASK_NOT_C, MASK_NOT_OP, MASK_OP, MAX_OP, MAXARG_A, MAXARG_B, MAXARG_Bx, MAXARG_C, MAXARG_sBx, MAXINDEXRK, NUM_OPCODES, OP_ADD, OP_AND, OP_CALL, OP_CLOSE, OP_CLOSURE, OP_CONCAT, OP_DIV, OP_EQ, OP_FORLOOP, OP_FORPREP, OP_GE, OP_GETGLOBAL, OP_GETTABLE, OP_GETUPVAL, OP_GT, OP_JMP, OP_LE, OP_LEN, OP_LOADBOOL, OP_LOADK, OP_LOADNIL, OP_LT, OP_MOD, OP_MOVE, OP_MUL, OP_NEQ, OP_NEWTABLE, OP_NOT, OP_OR, OP_POW, OP_RETURN, OP_SELF, OP_SETGLOBAL, OP_SETLIST, OP_SETTABLE, OP_SETUPVAL, OP_SUB, OP_TAILCALL, OP_TEST, OP_TESTSET, OP_TFORLOOP, OP_UNM, OP_VARARG, POS_A, POS_B, POS_Bx, POS_C, POS_OP, SIZE_A, SIZE_B, SIZE_Bx, SIZE_C, SIZE_OP, VARARG_HASARG, VARARG_ISVARARG, VARARG_NEEDSARG
+  + + + + + + + + + + + +
+Constructor Summary
+protected LuaC() + +
+           
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+protected static void_assert(boolean b) + +
+           
+static Prototypecompile(java.io.InputStream stream, + java.lang.String name) + +
+          Compile a prototype or load as a binary chunk
+static voidinstall() + +
+          Install the compiler so that LoadState will first + try to use it when handed bytes that are + not already a compiled lua chunk.
+ LuaFunctionload(java.io.InputStream stream, + java.lang.String name, + LuaValue env) + +
+          Load into a Closure or LuaFunction, with the supplied initial environment
+ LuaFunctionload(Prototype p, + java.lang.String filename, + LuaValue env) + +
+           
+ LuaStringnewTString(byte[] bytes, + int offset, + int len) + +
+           
+ java.lang.Stringpushfstring(java.lang.String string) + +
+           
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Lua
GET_OPCODE, GETARG_A, GETARG_B, GETARG_Bx, GETARG_C, GETARG_sBx, getBMode, getCMode, getOpMode, INDEXK, ISK, RKASK, testAMode, testTMode
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+instance

+
+public static final LuaC instance
+
+
+
+
+
+ +

+MAXSTACK

+
+public static final int MAXSTACK
+
+
+
See Also:
Constant Field Values
+
+
+ +

+nCcalls

+
+public int nCcalls
+
+
+
+
+ + + + + + + + +
+Constructor Detail
+ +

+LuaC

+
+protected LuaC()
+
+
+ + + + + + + + +
+Method Detail
+ +

+install

+
+public static void install()
+
+
Install the compiler so that LoadState will first + try to use it when handed bytes that are + not already a compiled lua chunk. +

+

+
+
+
+
+
+
+
+ +

+_assert

+
+protected static void _assert(boolean b)
+
+
+
+
+
+
+
+
+
+ +

+load

+
+public LuaFunction load(java.io.InputStream stream,
+                        java.lang.String name,
+                        LuaValue env)
+                 throws java.io.IOException
+
+
Load into a Closure or LuaFunction, with the supplied initial environment +

+

+
Specified by:
load in interface LoadState.LuaCompiler
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+compile

+
+public static Prototype compile(java.io.InputStream stream,
+                                java.lang.String name)
+                         throws java.io.IOException
+
+
Compile a prototype or load as a binary chunk +

+

+
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+newTString

+
+public LuaString newTString(byte[] bytes,
+                            int offset,
+                            int len)
+
+
+
+
+
+
+
+
+
+ +

+pushfstring

+
+public java.lang.String pushfstring(java.lang.String string)
+
+
+
+
+
+
+
+
+
+ +

+load

+
+public LuaFunction load(Prototype p,
+                        java.lang.String filename,
+                        LuaValue env)
+
+
+
+
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/compiler/class-use/LuaC.html b/luaj-2.0.3/docs/api/org/luaj/vm2/compiler/class-use/LuaC.html new file mode 100644 index 0000000000..7244b9c3f2 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/compiler/class-use/LuaC.html @@ -0,0 +1,180 @@ + + + + + + +Uses of Class org.luaj.vm2.compiler.LuaC (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.compiler.LuaC

+
+ + + + + + + + + +
+Packages that use LuaC
org.luaj.vm2.compiler  
+  +

+ + + + + +
+Uses of LuaC in org.luaj.vm2.compiler
+  +

+ + + + + + + + + +
Fields in org.luaj.vm2.compiler declared as LuaC
+static LuaCLuaC.instance + +
+           
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/compiler/package-frame.html b/luaj-2.0.3/docs/api/org/luaj/vm2/compiler/package-frame.html new file mode 100644 index 0000000000..9ac829329a --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/compiler/package-frame.html @@ -0,0 +1,32 @@ + + + + + + +org.luaj.vm2.compiler (Luaj API) + + + + + + + + + + + +org.luaj.vm2.compiler + + + + +
+Classes  + +
+LuaC
+ + + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/compiler/package-summary.html b/luaj-2.0.3/docs/api/org/luaj/vm2/compiler/package-summary.html new file mode 100644 index 0000000000..4780abec06 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/compiler/package-summary.html @@ -0,0 +1,157 @@ + + + + + + +org.luaj.vm2.compiler (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+

+Package org.luaj.vm2.compiler +

+ + + + + + + + + +
+Class Summary
LuaCCompiler for Lua.
+  + +

+

+
+
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/compiler/package-tree.html b/luaj-2.0.3/docs/api/org/luaj/vm2/compiler/package-tree.html new file mode 100644 index 0000000000..83df8f8db2 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/compiler/package-tree.html @@ -0,0 +1,156 @@ + + + + + + +org.luaj.vm2.compiler Class Hierarchy (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Hierarchy For Package org.luaj.vm2.compiler +

+
+
+
Package Hierarchies:
All Packages
+
+

+Class Hierarchy +

+ +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/compiler/package-use.html b/luaj-2.0.3/docs/api/org/luaj/vm2/compiler/package-use.html new file mode 100644 index 0000000000..1f26caffdf --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/compiler/package-use.html @@ -0,0 +1,170 @@ + + + + + + +Uses of Package org.luaj.vm2.compiler (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Package
org.luaj.vm2.compiler

+
+ + + + + + + + + +
+Packages that use org.luaj.vm2.compiler
org.luaj.vm2.compiler  
+  +

+ + + + + + + + +
+Classes in org.luaj.vm2.compiler used by org.luaj.vm2.compiler
LuaC + +
+          Compiler for Lua.
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/BaseLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/BaseLib.html new file mode 100644 index 0000000000..98cf73c2a2 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/BaseLib.html @@ -0,0 +1,615 @@ + + + + + + +BaseLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib +
+Class BaseLib

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.OneArgFunction
+                      extended by org.luaj.vm2.lib.BaseLib
+
+
+
All Implemented Interfaces:
ResourceFinder
+
+
+
Direct Known Subclasses:
JseBaseLib
+
+
+
+
public class BaseLib
extends OneArgFunction
implements ResourceFinder
+ + +

+Subclass of LibFunction which implements the lua basic library functions. +

+ This contains all library functions listed as "basic functions" in the lua documentation for JME. + The functions dofile and loadfile use the + FINDER instance to find resource files. + Since JME has no file system by default, BaseLib implements + ResourceFinder using Class.getResource(String), + which is the closest equivalent on JME. + The default loader chain in PackageLib will use these as well. +

+ To use basic library functions that include a ResourceFinder based on + directory lookup, use JseBaseLib instead. +

+ Typically, this library is included as part of a call to either + JmePlatform#standardGlobals() +

+ To instantiate and use it directly, + link it into your globals table via LuaValue.load(LuaValue) using code such as: +

 LuaTable _G = new LuaTable();
+ LuaThread.setGlobals(_G);
+ _G.load(new BaseLib());
+ _G.get("print").call(LuaValue.valueOf("hello, world"));
+  
+ Doing so will ensure the library is properly initialized + and loaded into the globals table. +

+ This is a direct port of the corresponding library in C. +

+ +

+

+
See Also:
JseBaseLib, +ResourceFinder, +FINDER, +LibFunction, +JsePlatform, +JmePlatform, +http://www.lua.org/manual/5.1/manual.html#5.1
+
+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Field Summary
+static ResourceFinderFINDER + +
+          Singleton file opener for this Java ClassLoader realm.
+static BaseLibinstance + +
+           
+ java.io.PrintStreamSTDERR + +
+           
+ java.io.InputStreamSTDIN + +
+           
+ java.io.PrintStreamSTDOUT + +
+           
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + +
+Constructor Summary
BaseLib() + +
+          Construct a base libarary instance.
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ LuaValuecall(LuaValue arg) + +
+          Call this with 1 argument, including metatag processing, + and return only the first return value.
+ java.io.InputStreamfindResource(java.lang.String filename) + +
+          ResourceFinder implementation + + Tries to open the file as a resource, which can work for .
+static VarargsloadFile(java.lang.String filename) + +
+          Load from a named file, returning the chunk or nil,error of can't load
+static VarargsloadStream(java.io.InputStream is, + java.lang.String chunkname) + +
+           
+static Varargspcall(LuaValue func, + Varargs args, + LuaValue errfunc) + +
+           
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.OneArgFunction
call, call, call, invoke
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+instance

+
+public static BaseLib instance
+
+
+
+
+
+ +

+STDIN

+
+public java.io.InputStream STDIN
+
+
+
+
+
+ +

+STDOUT

+
+public java.io.PrintStream STDOUT
+
+
+
+
+
+ +

+STDERR

+
+public java.io.PrintStream STDERR
+
+
+
+
+
+ +

+FINDER

+
+public static ResourceFinder FINDER
+
+
Singleton file opener for this Java ClassLoader realm. + + Unless set or changed elsewhere, will be set by the BaseLib that is created. +

+

+
+
+ + + + + + + + +
+Constructor Detail
+ +

+BaseLib

+
+public BaseLib()
+
+
Construct a base libarary instance. +

+

+ + + + + + + + +
+Method Detail
+ +

+call

+
+public LuaValue call(LuaValue arg)
+
+
Description copied from class: LuaValue
+
Call this with 1 argument, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Specified by:
call in class OneArgFunction
+
+
+
Parameters:
arg - First argument to supply to the called function +
Returns:
First return value (this(arg)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue,LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue), +LuaValue.method(String,LuaValue), +LuaValue.method(LuaValue,LuaValue)
+
+
+
+ +

+findResource

+
+public java.io.InputStream findResource(java.lang.String filename)
+
+
ResourceFinder implementation + + Tries to open the file as a resource, which can work for . +

+

+
Specified by:
findResource in interface ResourceFinder
+
+
+ +
Returns:
InputStream, or null if not found.
See Also:
BaseLib, +JseBaseLib
+
+
+
+ +

+pcall

+
+public static Varargs pcall(LuaValue func,
+                            Varargs args,
+                            LuaValue errfunc)
+
+
+
+
+
+
+
+
+
+ +

+loadFile

+
+public static Varargs loadFile(java.lang.String filename)
+
+
Load from a named file, returning the chunk or nil,error of can't load +

+

+
+
+
+ +
Returns:
Varargs containing chunk, or NIL,error-text on error
+
+
+
+ +

+loadStream

+
+public static Varargs loadStream(java.io.InputStream is,
+                                 java.lang.String chunkname)
+
+
+
+
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/CoroutineLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/CoroutineLib.html new file mode 100644 index 0000000000..c3cd6f4734 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/CoroutineLib.html @@ -0,0 +1,383 @@ + + + + + + +CoroutineLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib +
+Class CoroutineLib

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.VarArgFunction
+                      extended by org.luaj.vm2.lib.CoroutineLib
+
+
+
+
public class CoroutineLib
extends VarArgFunction
+ + +

+Subclass of LibFunction which implements the lua standard coroutine + library. +

+ The coroutine library in luaj has the same behavior as the + coroutine library in C, but is implemented using Java Threads to maintain + the call state between invocations. Therefore it can be yielded from anywhere, + similar to the "Coco" yield-from-anywhere patch available for C-based lua. + However, coroutines that are yielded but never resumed to complete their execution + may not be collected by the garbage collector. +

+ Typically, this library is included as part of a call to either + JsePlatform#standardGlobals() or JmePlatform#standardGlobals() +

+ To instantiate and use it directly, + link it into your globals table via LuaValue.load(LuaValue) using code such as: +

 LuaTable _G = new LuaTable();
+ _G.load(new CoroutineLib());
+  
+ Doing so will ensure the library is properly initialized + and loaded into the globals table. +

+

+ +

+

+
See Also:
LibFunction, +JsePlatform, +JmePlatform, +http://www.lua.org/manual/5.1/manual.html#5.2
+
+ +

+ + + + + + + +
+Field Summary
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + +
+Constructor Summary
CoroutineLib() + +
+           
+  + + + + + + + + + + + +
+Method Summary
+ Varargsinvoke(Varargs args) + +
+          Override and implement for the best performance.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.VarArgFunction
call, call, call, call, onInvoke
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+CoroutineLib

+
+public CoroutineLib()
+
+
+ + + + + + + + +
+Method Detail
+ +

+invoke

+
+public Varargs invoke(Varargs args)
+
+
Description copied from class: VarArgFunction
+
Override and implement for the best performance. + May not have expected behavior for tail calls. + Should not be used if either: + - function needs to be used as a module + - function has a possibility of returning a TailcallVarargs +

+

+
Overrides:
invoke in class VarArgFunction
+
+
+
Parameters:
args - the arguments to the function call. +
Returns:
All return values as a Varargs instance.
See Also:
LuaValue.varargsOf(LuaValue[]), +LuaValue.call(LuaValue), +LuaValue.invoke(), +LuaValue.invoke(LuaValue,Varargs), +LuaValue.invokemethod(String,Varargs), +LuaValue.invokemethod(LuaValue,Varargs)
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/DebugLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/DebugLib.html new file mode 100644 index 0000000000..7860d1c50d --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/DebugLib.html @@ -0,0 +1,672 @@ + + + + + + +DebugLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib +
+Class DebugLib

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.VarArgFunction
+                      extended by org.luaj.vm2.lib.DebugLib
+
+
+
+
public class DebugLib
extends VarArgFunction
+ + +

+Subclass of LibFunction which implements the lua standard debug + library. +

+ The debug library in luaj tries to emulate the behavior of the corresponding C-based lua library. + To do this, it must maintain a separate stack of calls to LuaClosure and LibFunction + instances. + Especially when lua-to-java bytecode compiling is being used + via a LuaCompiler such as LuaJC, + this cannot be done in all cases. +

+ Typically, this library is included as part of a call to either + JsePlatform#debugGlobals() or JmePlatform#debugGlobals() +

+ To instantiate and use it directly, + link it into your globals table via LuaValue.load(LuaValue) using code such as: +

 LuaTable _G = new LuaTable();
+ _G.load(new DebugLib());
+  
+ Doing so will ensure the library is properly initialized + and loaded into the globals table. +

+

+ +

+

+
See Also:
LibFunction, +JsePlatform, +JmePlatform, +http://www.lua.org/manual/5.1/manual.html#5.9
+
+ +

+ + + + + + + + + + + + + + + + + + + +
+Field Summary
+static booleanCALLS + +
+           
+static booleanDEBUG_ENABLED + +
+           
+static booleanTRACE + +
+           
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + +
+Constructor Summary
DebugLib() + +
+           
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+protected static Varargs_getinfo(Varargs args, + LuaValue level0func) + +
+           
+static voiddebugBytecode(int pc, + Varargs extras, + int top) + +
+          Called by Closures on bytecode execution
+static voiddebugOnCall(LuaThread thread, + int calls, + LuaFunction func) + +
+          Called by Closures and recursing java functions on entry
+static voiddebugOnReturn(LuaThread thread, + int calls) + +
+          Called by Closures and recursing java functions on return
+static voiddebugSetupCall(Varargs args, + LuaValue[] stack) + +
+          Called by Closures to set up stack and arguments to next call
+static java.lang.Stringfileline() + +
+          Get file and line for the nearest calling closure.
+static java.lang.Stringfileline(int level) + +
+          Get file and line for a particular level, even if it is a java function.
+ Varargsinvoke(Varargs args) + +
+          Override and implement for the best performance.
+static java.lang.Stringsourceshort(Prototype p) + +
+           
+static java.lang.Stringtraceback(int level) + +
+          Get a traceback as a string for the current thread
+static java.lang.Stringtraceback(LuaThread thread, + int level) + +
+          Get a traceback for a particular thread.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.VarArgFunction
call, call, call, call, onInvoke
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+CALLS

+
+public static final boolean CALLS
+
+
+
+
+
+ +

+TRACE

+
+public static final boolean TRACE
+
+
+
+
+
+ +

+DEBUG_ENABLED

+
+public static boolean DEBUG_ENABLED
+
+
+
+
+ + + + + + + + +
+Constructor Detail
+ +

+DebugLib

+
+public DebugLib()
+
+
+ + + + + + + + +
+Method Detail
+ +

+invoke

+
+public Varargs invoke(Varargs args)
+
+
Description copied from class: VarArgFunction
+
Override and implement for the best performance. + May not have expected behavior for tail calls. + Should not be used if either: + - function needs to be used as a module + - function has a possibility of returning a TailcallVarargs +

+

+
Overrides:
invoke in class VarArgFunction
+
+
+
Parameters:
args - the arguments to the function call. +
Returns:
All return values as a Varargs instance.
See Also:
LuaValue.varargsOf(LuaValue[]), +LuaValue.call(LuaValue), +LuaValue.invoke(), +LuaValue.invoke(LuaValue,Varargs), +LuaValue.invokemethod(String,Varargs), +LuaValue.invokemethod(LuaValue,Varargs)
+
+
+
+ +

+debugSetupCall

+
+public static void debugSetupCall(Varargs args,
+                                  LuaValue[] stack)
+
+
Called by Closures to set up stack and arguments to next call +

+

+
+
+
+
+ +

+debugOnCall

+
+public static void debugOnCall(LuaThread thread,
+                               int calls,
+                               LuaFunction func)
+
+
Called by Closures and recursing java functions on entry +

+

+
Parameters:
thread - the thread for the call
calls - the number of calls in the call stack
func - the function called
+
+
+
+ +

+debugOnReturn

+
+public static void debugOnReturn(LuaThread thread,
+                                 int calls)
+
+
Called by Closures and recursing java functions on return +

+

+
Parameters:
thread - the thread for the call
calls - the number of calls in the call stack
+
+
+
+ +

+debugBytecode

+
+public static void debugBytecode(int pc,
+                                 Varargs extras,
+                                 int top)
+
+
Called by Closures on bytecode execution +

+

+
+
+
+
+ +

+_getinfo

+
+protected static Varargs _getinfo(Varargs args,
+                                  LuaValue level0func)
+
+
+
+
+
+
+ +

+sourceshort

+
+public static java.lang.String sourceshort(Prototype p)
+
+
+
+
+
+
+ +

+traceback

+
+public static java.lang.String traceback(int level)
+
+
Get a traceback as a string for the current thread +

+

+
+
+
+
+ +

+traceback

+
+public static java.lang.String traceback(LuaThread thread,
+                                         int level)
+
+
Get a traceback for a particular thread. +

+

+
Parameters:
thread - LuaThread to provide stack trace for
level - 0-based level to start reporting on +
Returns:
String containing the stack trace.
+
+
+
+ +

+fileline

+
+public static java.lang.String fileline()
+
+
Get file and line for the nearest calling closure. +

+

+ +
Returns:
String identifying the file and line of the nearest lua closure, + or the function name of the Java call if no closure is being called.
+
+
+
+ +

+fileline

+
+public static java.lang.String fileline(int level)
+
+
Get file and line for a particular level, even if it is a java function. +

+

+
Parameters:
level - 0-based index of level to get +
Returns:
String containing file and line info if available
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/IoLib.File.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/IoLib.File.html new file mode 100644 index 0000000000..e64b9dd52d --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/IoLib.File.html @@ -0,0 +1,643 @@ + + + + + + +IoLib.File (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib +
+Class IoLib.File

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.lib.IoLib.File
+
+
+
Enclosing class:
IoLib
+
+
+
+
protected abstract class IoLib.File
extends LuaValue
+ + +

+


+ +

+ + + + + + + +
+Field Summary
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + + +
+Constructor Summary
+protected IoLib.File() + +
+           
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+abstract  voidclose() + +
+           
+abstract  voidflush() + +
+           
+ LuaValueget(LuaValue key) + +
+          Get a value in a table including metatag processing using INDEX.
+abstract  booleanisclosed() + +
+           
+abstract  booleanisstdfile() + +
+           
+abstract  intpeek() + +
+           
+abstract  intread() + +
+           
+abstract  intread(byte[] bytes, + int offset, + int length) + +
+           
+abstract  intremaining() + +
+           
+abstract  intseek(java.lang.String option, + int bytecount) + +
+           
+abstract  voidsetvbuf(java.lang.String mode, + int size) + +
+           
+ java.lang.Stringtojstring() + +
+          Convert to human readable String for any type.
+ inttype() + +
+          Get the enumeration value for the type of this value.
+ java.lang.Stringtypename() + +
+          Get the String name of the type of this value.
+abstract  voidwrite(LuaString string) + +
+           
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, call, call, call, call, callmt, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, getfenv, getmetatable, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isfunction, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setfenv, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+IoLib.File

+
+protected IoLib.File()
+
+
+ + + + + + + + +
+Method Detail
+ +

+write

+
+public abstract void write(LuaString string)
+                    throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+flush

+
+public abstract void flush()
+                    throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+isstdfile

+
+public abstract boolean isstdfile()
+
+
+
+
+
+
+ +

+close

+
+public abstract void close()
+                    throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+isclosed

+
+public abstract boolean isclosed()
+
+
+
+
+
+
+ +

+seek

+
+public abstract int seek(java.lang.String option,
+                         int bytecount)
+                  throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+setvbuf

+
+public abstract void setvbuf(java.lang.String mode,
+                             int size)
+
+
+
+
+
+
+ +

+remaining

+
+public abstract int remaining()
+                       throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+peek

+
+public abstract int peek()
+                  throws java.io.IOException,
+                         java.io.EOFException
+
+
+ +
Throws: +
java.io.IOException +
java.io.EOFException
+
+
+
+ +

+read

+
+public abstract int read()
+                  throws java.io.IOException,
+                         java.io.EOFException
+
+
+ +
Throws: +
java.io.IOException +
java.io.EOFException
+
+
+
+ +

+read

+
+public abstract int read(byte[] bytes,
+                         int offset,
+                         int length)
+                  throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+get

+
+public LuaValue get(LuaValue key)
+
+
Description copied from class: LuaValue
+
Get a value in a table including metatag processing using INDEX. +

+

+
Overrides:
get in class LuaValue
+
+
+
Parameters:
key - the key to look up, must not be NIL or null +
Returns:
LuaValue for that key, or NIL if not found and no metatag
See Also:
LuaValue.get(int), +LuaValue.get(String), +LuaValue.rawget(LuaValue)
+
+
+
+ +

+type

+
+public int type()
+
+
Description copied from class: LuaValue
+
Get the enumeration value for the type of this value. +

+

+
Specified by:
type in class LuaValue
+
+
+ +
Returns:
value for this type, one of + TNIL, + TBOOLEAN, + TNUMBER, + TSTRING, + TTABLE, + TFUNCTION, + TUSERDATA, + TTHREAD
See Also:
LuaValue.typename()
+
+
+
+ +

+typename

+
+public java.lang.String typename()
+
+
Description copied from class: LuaValue
+
Get the String name of the type of this value. +

+

+

+
Specified by:
typename in class LuaValue
+
+
+ +
Returns:
name from type name list LuaValue.TYPE_NAMES + corresponding to the type of this value: + "nil", "boolean", "number", "string", + "table", "function", "userdata", "thread"
See Also:
LuaValue.type()
+
+
+
+ +

+tojstring

+
+public java.lang.String tojstring()
+
+
Description copied from class: LuaValue
+
Convert to human readable String for any type. +

+

+
Overrides:
tojstring in class LuaValue
+
+
+ +
Returns:
String for use by human readers based on type.
See Also:
LuaValue.tostring(), +LuaValue.optjstring(String), +LuaValue.checkjstring(), +LuaValue.isstring(), +TSTRING
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/IoLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/IoLib.html new file mode 100644 index 0000000000..c79f857d4e --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/IoLib.html @@ -0,0 +1,1150 @@ + + + + + + +IoLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib +
+Class IoLib

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.OneArgFunction
+                      extended by org.luaj.vm2.lib.IoLib
+
+
+
Direct Known Subclasses:
JmeIoLib, JseIoLib
+
+
+
+
public abstract class IoLib
extends OneArgFunction
+ + +

+Abstract base class extending LibFunction which implements the + core of the lua standard io library. +

+ It contains the implementation of the io library support that is common to + the JSE and JME platforms. + In practice on of the concrete IOLib subclasses is chosen: + JseIoLib for the JSE platform, and + JmeIoLib for the JME platform. +

+ The JSE implementation conforms almost completely to the C-based lua library, + while the JME implementation follows closely except in the area of random-access files, + which are difficult to support properly on JME. +

+ Typically, this library is included as part of a call to either + JsePlatform#standardGlobals() or JmePlatform#standardGlobals() +

+ To instantiate and use it directly, + link it into your globals table via LuaValue.load(LuaValue) using code such as: +

 LuaTable _G = new LuaTable();
+ _G.load(new JseIoLib());
+ LuaThread.setGlobals(_G);
+ _G.load(new JseBaseLib());
+ _G.load(new PackageLib());
+ _G.load(new JseIoLib());
+ _G.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
+  
+ Doing so will ensure the library is properly initialized + and loaded into the globals table. +

+ This has been implemented to match as closely as possible the behavior in the corresponding library in C. +

+ +

+

+
See Also:
LibFunction, +JsePlatform, +JmePlatform, +JseIoLib, +JmeIoLib, +http://www.lua.org/manual/5.1/manual.html#5.7
+
+ +

+ + + + + + + + + + + +
+Nested Class Summary
+protected  classIoLib.File + +
+           
+ + + + + + + + + + + + + + +
+Field Summary
+static java.lang.String[]FILE_NAMES + +
+           
+static java.lang.String[]IO_NAMES + +
+           
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + +
+Constructor Summary
IoLib() + +
+           
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ Varargs_file_close(LuaValue file) + +
+           
+ Varargs_file_flush(LuaValue file) + +
+           
+ Varargs_file_lines(LuaValue file) + +
+           
+ Varargs_file_read(LuaValue file, + Varargs subargs) + +
+           
+ Varargs_file_seek(LuaValue file, + java.lang.String whence, + int offset) + +
+           
+ Varargs_file_setvbuf(LuaValue file, + java.lang.String mode, + int size) + +
+           
+ Varargs_file_write(LuaValue file, + Varargs subargs) + +
+           
+ Varargs_io_close(LuaValue file) + +
+           
+ Varargs_io_flush() + +
+           
+ Varargs_io_index(LuaValue v) + +
+           
+ Varargs_io_input(LuaValue file) + +
+           
+ Varargs_io_lines(java.lang.String filename) + +
+           
+ Varargs_io_open(java.lang.String filename, + java.lang.String mode) + +
+           
+ Varargs_io_output(LuaValue filename) + +
+           
+ Varargs_io_popen(java.lang.String prog, + java.lang.String mode) + +
+           
+ Varargs_io_read(Varargs args) + +
+           
+ Varargs_io_tmpfile() + +
+           
+ Varargs_io_type(LuaValue obj) + +
+           
+ Varargs_io_write(Varargs args) + +
+           
+ Varargs_lines_iter(LuaValue file) + +
+           
+ LuaValuecall(LuaValue arg) + +
+          Call this with 1 argument, including metatag processing, + and return only the first return value.
+static LuaValuefreadall(IoLib.File f) + +
+           
+static LuaValuefreadbytes(IoLib.File f, + int count) + +
+           
+static LuaValuefreadline(IoLib.File f) + +
+           
+static LuaValuefreadnumber(IoLib.File f) + +
+           
+static LuaValuefreaduntil(IoLib.File f, + boolean lineonly) + +
+           
+protected abstract  IoLib.FileopenFile(java.lang.String filename, + boolean readMode, + boolean appendMode, + boolean updateMode, + boolean binaryMode) + +
+          Open a file in a particular mode.
+protected abstract  IoLib.FileopenProgram(java.lang.String prog, + java.lang.String mode) + +
+          Start a new process and return a file for input or output
+protected abstract  IoLib.FiletmpFile() + +
+          Open a temporary file.
+protected abstract  IoLib.FilewrapStdin() + +
+          Wrap the standard input.
+protected abstract  IoLib.FilewrapStdout() + +
+          Wrap the standard output.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.OneArgFunction
call, call, call, invoke
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+IO_NAMES

+
+public static final java.lang.String[] IO_NAMES
+
+
+
+
+
+ +

+FILE_NAMES

+
+public static final java.lang.String[] FILE_NAMES
+
+
+
+
+ + + + + + + + +
+Constructor Detail
+ +

+IoLib

+
+public IoLib()
+
+
+ + + + + + + + +
+Method Detail
+ +

+wrapStdin

+
+protected abstract IoLib.File wrapStdin()
+                                 throws java.io.IOException
+
+
Wrap the standard input. +

+

+ +
Returns:
File +
Throws: +
java.io.IOException
+
+
+
+ +

+wrapStdout

+
+protected abstract IoLib.File wrapStdout()
+                                  throws java.io.IOException
+
+
Wrap the standard output. +

+

+ +
Returns:
File +
Throws: +
java.io.IOException
+
+
+
+ +

+openFile

+
+protected abstract IoLib.File openFile(java.lang.String filename,
+                                       boolean readMode,
+                                       boolean appendMode,
+                                       boolean updateMode,
+                                       boolean binaryMode)
+                                throws java.io.IOException
+
+
Open a file in a particular mode. +

+

+
Parameters:
filename -
readMode - true if opening in read mode
appendMode - true if opening in append mode
updateMode - true if opening in update mode
binaryMode - true if opening in binary mode +
Returns:
File object if successful +
Throws: +
java.io.IOException - if could not be opened
+
+
+
+ +

+tmpFile

+
+protected abstract IoLib.File tmpFile()
+                               throws java.io.IOException
+
+
Open a temporary file. +

+

+ +
Returns:
File object if successful +
Throws: +
java.io.IOException - if could not be opened
+
+
+
+ +

+openProgram

+
+protected abstract IoLib.File openProgram(java.lang.String prog,
+                                          java.lang.String mode)
+                                   throws java.io.IOException
+
+
Start a new process and return a file for input or output +

+

+
Parameters:
prog - the program to execute
mode - "r" to read, "w" to write +
Returns:
File to read to or write from +
Throws: +
java.io.IOException - if an i/o exception occurs
+
+
+
+ +

+call

+
+public LuaValue call(LuaValue arg)
+
+
Description copied from class: LuaValue
+
Call this with 1 argument, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Specified by:
call in class OneArgFunction
+
+
+
Parameters:
arg - First argument to supply to the called function +
Returns:
First return value (this(arg)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue,LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue), +LuaValue.method(String,LuaValue), +LuaValue.method(LuaValue,LuaValue)
+
+
+
+ +

+_io_flush

+
+public Varargs _io_flush()
+                  throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+_io_tmpfile

+
+public Varargs _io_tmpfile()
+                    throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+_io_close

+
+public Varargs _io_close(LuaValue file)
+                  throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+_io_input

+
+public Varargs _io_input(LuaValue file)
+
+
+
+
+
+
+ +

+_io_output

+
+public Varargs _io_output(LuaValue filename)
+
+
+
+
+
+
+ +

+_io_type

+
+public Varargs _io_type(LuaValue obj)
+
+
+
+
+
+
+ +

+_io_popen

+
+public Varargs _io_popen(java.lang.String prog,
+                         java.lang.String mode)
+                  throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+_io_open

+
+public Varargs _io_open(java.lang.String filename,
+                        java.lang.String mode)
+                 throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+_io_lines

+
+public Varargs _io_lines(java.lang.String filename)
+
+
+
+
+
+
+ +

+_io_read

+
+public Varargs _io_read(Varargs args)
+                 throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+_io_write

+
+public Varargs _io_write(Varargs args)
+                  throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+_file_close

+
+public Varargs _file_close(LuaValue file)
+                    throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+_file_flush

+
+public Varargs _file_flush(LuaValue file)
+                    throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+_file_setvbuf

+
+public Varargs _file_setvbuf(LuaValue file,
+                             java.lang.String mode,
+                             int size)
+
+
+
+
+
+
+ +

+_file_lines

+
+public Varargs _file_lines(LuaValue file)
+
+
+
+
+
+
+ +

+_file_read

+
+public Varargs _file_read(LuaValue file,
+                          Varargs subargs)
+                   throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+_file_seek

+
+public Varargs _file_seek(LuaValue file,
+                          java.lang.String whence,
+                          int offset)
+                   throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+_file_write

+
+public Varargs _file_write(LuaValue file,
+                           Varargs subargs)
+                    throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+_io_index

+
+public Varargs _io_index(LuaValue v)
+
+
+
+
+
+
+ +

+_lines_iter

+
+public Varargs _lines_iter(LuaValue file)
+                    throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+freadbytes

+
+public static LuaValue freadbytes(IoLib.File f,
+                                  int count)
+                           throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+freaduntil

+
+public static LuaValue freaduntil(IoLib.File f,
+                                  boolean lineonly)
+                           throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+freadline

+
+public static LuaValue freadline(IoLib.File f)
+                          throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+freadall

+
+public static LuaValue freadall(IoLib.File f)
+                         throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+freadnumber

+
+public static LuaValue freadnumber(IoLib.File f)
+                            throws java.io.IOException
+
+
+ +
Throws: +
java.io.IOException
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/LibFunction.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/LibFunction.html new file mode 100644 index 0000000000..a91b746942 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/LibFunction.html @@ -0,0 +1,596 @@ + + + + + + +LibFunction (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib +
+Class LibFunction

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+
+
+
Direct Known Subclasses:
OneArgFunction, ThreeArgFunction, TwoArgFunction, VarArgFunction, ZeroArgFunction
+
+
+
+
public abstract class LibFunction
extends LuaFunction
+ + +

+Subclass of LuaFunction common to Java functions exposed to lua. +

+ To provide for common implementations in JME and JSE, + library functions are typically grouped on one or more library classes + and an opcode per library function is defined and used to key the switch + to the correct function within the library. +

+ Since lua functions can be called with too few or too many arguments, + and there are overloaded LuaValue.call() functions with varying + number of arguments, a Java function exposed in lua needs to handle the + argument fixup when a function is called with a number of arguments + differs from that expected. +

+ To simplify the creation of library functions, + there are 5 direct subclasses to handle common cases based on number of + argument values and number of return return values. +

+

+ To be a Java library that can be loaded via require, it should have + a public constructor that returns a LuaValue that, when executed, + initializes the library. +

+ For example, the following code will implement a library called "hyperbolic" + with two functions, "sinh", and "cosh": +

 import org.luaj.vm2.LuaValue;
+ import org.luaj.vm2.lib.OneArgFunction;
+ 
+ public class hyperbolic extends OneArgFunction {
+
+	public hyperbolic() {}
+
+	public LuaValue call(LuaValue libname) {
+		LuaValue library = tableOf();
+		library.set( "sinh", new sinh() );
+		library.set( "cosh", new cosh() );
+		env.set( "hyperbolic", library );
+		return library;
+	}
+
+	static class sinh extends OneArgFunction {
+		public LuaValue call(LuaValue x) {
+			return LuaValue.valueOf(Math.sinh(x.checkdouble()));
+		}
+	}
+	
+	static class cosh extends OneArgFunction {
+		public LuaValue call(LuaValue x) {
+			return LuaValue.valueOf(Math.cosh(x.checkdouble()));
+		}
+	}
+}
+
+ The default constructor is used to instantiate the library + in response to require 'hyperbolic' statement, + provided it is on Javas class path. + This instance is then invoked with the name supplied to require() + as the only argument, and library should initialized whatever global + data it needs to and place it into the environment if needed. + In this case, it creates two function, 'sinh', and 'cosh', and puts + them into a global table called 'hyperbolic.' + It placed the library table into the globals via the LuaFunction.env + local variable which corresponds to the globals that apply when the + library is loaded. +

+ To test it, a script such as this can be used: +

 local t = require('hyperbolic')
+ print( 't', t )
+ print( 'hyperbolic', hyperbolic )
+ for k,v in pairs(t) do
+ 	print( 'k,v', k,v )
+ end
+ print( 'sinh(.5)', hyperbolic.sinh(.5) )
+ print( 'cosh(.5)', hyperbolic.cosh(.5) )
+ 
+

+ It should produce something like: +

 t	table: 3dbbd23f
+ hyperbolic	table: 3dbbd23f
+ k,v	cosh	function: 3dbbd128
+ k,v	sinh	function: 3dbbd242
+ sinh(.5)	0.5210953
+ cosh(.5)	1.127626
+ 
+

+ See the source code in any of the library functions + such as BaseLib or TableLib for other examples. +

+ +

+


+ +

+ + + + + + + + + + + + + + + +
+Field Summary
+protected  java.lang.Stringname + +
+          The common name for this function, useful for debugging.
+protected  intopcode + +
+          User-defined opcode to differentiate between instances of the library function class.
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + + +
+Constructor Summary
+protected LibFunction() + +
+          Default constructor for use by subclasses
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+protected  voidbind(LuaValue env, + java.lang.Class factory, + java.lang.String[] names) + +
+          Bind a set of library functions.
+protected  voidbind(LuaValue env, + java.lang.Class factory, + java.lang.String[] names, + int firstopcode) + +
+          Bind a set of library functions, with an offset
+protected static LuaValue[]newupe() + +
+          Java code generation utility to allocate storage for upvalue, leave it empty
+protected static LuaValue[]newupl(LuaValue v) + +
+          Java code generation utility to allocate storage for upvalue, initialize with value
+protected static LuaValue[]newupn() + +
+          Java code generation utility to allocate storage for upvalue, initialize with nil
+ java.lang.Stringtojstring() + +
+          Convert to human readable String for any type.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, call, call, call, call, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+opcode

+
+protected int opcode
+
+
User-defined opcode to differentiate between instances of the library function class. +

+ Subclass will typicall switch on this value to provide the specific behavior for each function. +

+

+
+
+
+ +

+name

+
+protected java.lang.String name
+
+
The common name for this function, useful for debugging. +

+ Binding functions initialize this to the name to which it is bound. +

+

+
+
+ + + + + + + + +
+Constructor Detail
+ +

+LibFunction

+
+protected LibFunction()
+
+
Default constructor for use by subclasses +

+

+ + + + + + + + +
+Method Detail
+ +

+tojstring

+
+public java.lang.String tojstring()
+
+
Description copied from class: LuaValue
+
Convert to human readable String for any type. +

+

+
Overrides:
tojstring in class LuaValue
+
+
+ +
Returns:
String for use by human readers based on type.
See Also:
LuaValue.tostring(), +LuaValue.optjstring(String), +LuaValue.checkjstring(), +LuaValue.isstring(), +TSTRING
+
+
+
+ +

+bind

+
+protected void bind(LuaValue env,
+                    java.lang.Class factory,
+                    java.lang.String[] names)
+
+
Bind a set of library functions. +

+ An array of names is provided, and the first name is bound + with opcode = 0, second with 1, etc. +

+

+
Parameters:
env - The environment to apply to each bound function
factory - the Class to instantiate for each bound function
names - array of String names, one for each function.
See Also:
bind(LuaValue, Class, String[], int)
+
+
+
+ +

+bind

+
+protected void bind(LuaValue env,
+                    java.lang.Class factory,
+                    java.lang.String[] names,
+                    int firstopcode)
+
+
Bind a set of library functions, with an offset +

+ An array of names is provided, and the first name is bound + with opcode = firstopcode, second with firstopcode+1, etc. +

+

+
Parameters:
env - The environment to apply to each bound function
factory - the Class to instantiate for each bound function
names - array of String names, one for each function.
firstopcode - the first opcode to use
See Also:
bind(LuaValue, Class, String[])
+
+
+
+ +

+newupe

+
+protected static LuaValue[] newupe()
+
+
Java code generation utility to allocate storage for upvalue, leave it empty +

+

+
+
+
+
+ +

+newupn

+
+protected static LuaValue[] newupn()
+
+
Java code generation utility to allocate storage for upvalue, initialize with nil +

+

+
+
+
+
+ +

+newupl

+
+protected static LuaValue[] newupl(LuaValue v)
+
+
Java code generation utility to allocate storage for upvalue, initialize with value +

+

+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/MathLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/MathLib.html new file mode 100644 index 0000000000..1d4edf0883 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/MathLib.html @@ -0,0 +1,528 @@ + + + + + + +MathLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib +
+Class MathLib

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.OneArgFunction
+                      extended by org.luaj.vm2.lib.MathLib
+
+
+
Direct Known Subclasses:
JseMathLib
+
+
+
+
public class MathLib
extends OneArgFunction
+ + +

+Subclass of LibFunction which implements the lua standard math + library. +

+ It contains only the math library support that is possible on JME. + For a more complete implementation based on math functions specific to JSE + use JseMathLib. + In Particular the following math functions are not implemented by this library: +

    +
  • acos
  • +
  • asin
  • +
  • atan
  • +
  • cosh
  • +
  • log
  • +
  • log10
  • +
  • sinh
  • +
  • tanh
  • +
  • atan2
  • +
+

+ The implementations of exp() and pow() are constructed by + hand for JME, so will be slower and less accurate than when executed on the JSE platform. +

+ Typically, this library is included as part of a call to either + JmePlatform#standardGlobals() +

+ To instantiate and use it directly, + link it into your globals table via LuaValue.load(LuaValue) using code such as: +

 LuaTable _G = new LuaTable();
+ LuaThread.setGlobals(_G);
+ _G.load(new BaseLib());
+ _G.load(new PackageLib());
+ _G.load(new MathLib());
+ System.out.println( _G.get("math").get("sqrt").call( LuaValue.valueOf(2) ) );
+  
+ Doing so will ensure the library is properly initialized + and loaded into the globals table. +

+ This has been implemented to match as closely as possible the behavior in the corresponding library in C. +

+ +

+

+
See Also:
LibFunction, +JsePlatform, +JmePlatform, +JseMathLib, +http://www.lua.org/manual/5.1/manual.html#5.6
+
+ +

+ + + + + + + + + + + +
+Field Summary
+static MathLibMATHLIB + +
+           
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + +
+Constructor Summary
MathLib() + +
+           
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ LuaValuecall(LuaValue arg) + +
+          Call this with 1 argument, including metatag processing, + and return only the first return value.
+static doubledpow_d(double a, + double b) + +
+           
+protected static doubledpow_default(double a, + double b) + +
+          Default JME version computes using longhand heuristics.
+ doubledpow_lib(double a, + double b) + +
+          Hook to override default dpow behavior with faster implementation.
+static LuaValuedpow(double a, + double b) + +
+          compute power using installed math library, or default if there is no math library installed
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.OneArgFunction
call, call, call, invoke
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+MATHLIB

+
+public static MathLib MATHLIB
+
+
+
+
+ + + + + + + + +
+Constructor Detail
+ +

+MathLib

+
+public MathLib()
+
+
+ + + + + + + + +
+Method Detail
+ +

+call

+
+public LuaValue call(LuaValue arg)
+
+
Description copied from class: LuaValue
+
Call this with 1 argument, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Specified by:
call in class OneArgFunction
+
+
+
Parameters:
arg - First argument to supply to the called function +
Returns:
First return value (this(arg)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue,LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue), +LuaValue.method(String,LuaValue), +LuaValue.method(LuaValue,LuaValue)
+
+
+
+ +

+dpow

+
+public static LuaValue dpow(double a,
+                            double b)
+
+
compute power using installed math library, or default if there is no math library installed +

+

+
+
+
+
+ +

+dpow_d

+
+public static double dpow_d(double a,
+                            double b)
+
+
+
+
+
+
+ +

+dpow_lib

+
+public double dpow_lib(double a,
+                       double b)
+
+
Hook to override default dpow behavior with faster implementation. +

+

+
+
+
+
+ +

+dpow_default

+
+protected static double dpow_default(double a,
+                                     double b)
+
+
Default JME version computes using longhand heuristics. +

+

+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/OneArgFunction.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/OneArgFunction.html new file mode 100644 index 0000000000..dd2ded2910 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/OneArgFunction.html @@ -0,0 +1,571 @@ + + + + + + +OneArgFunction (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib +
+Class OneArgFunction

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.OneArgFunction
+
+
+
Direct Known Subclasses:
BaseLib, IoLib, JseMathLib.JseMathLib1, MathLib, PackageLib, StringLib, TableLib
+
+
+
+
public abstract class OneArgFunction
extends LibFunction
+ + +

+Abstract base class for Java function implementations that take one argument and + return one value. +

+ Subclasses need only implement LuaValue.call(LuaValue) to complete this class, + simplifying development. + All other uses of call(), invoke(Varargs),etc, + are routed through this method by this class, + dropping or extending arguments with nil values as required. +

+ If more than one argument are required, or no arguments are required, + or variable argument or variable return values, + then use one of the related function + ZeroArgFunction, TwoArgFunction, ThreeArgFunction, or VarArgFunction. +

+ See LibFunction for more information on implementation libraries and library functions. +

+ +

+

+
See Also:
call(LuaValue), +LibFunction, +ZeroArgFunction, +TwoArgFunction, +ThreeArgFunction, +VarArgFunction
+
+ +

+ + + + + + + +
+Field Summary
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + + + + +
+Constructor Summary
OneArgFunction() + +
+          Default constructor
OneArgFunction(LuaValue env) + +
+          Constructor with specific environment
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ LuaValuecall() + +
+          Call this with 0 arguments, including metatag processing, + and return only the first return value.
+abstract  LuaValuecall(LuaValue arg) + +
+          Call this with 1 argument, including metatag processing, + and return only the first return value.
+ LuaValuecall(LuaValue arg1, + LuaValue arg2) + +
+          Call this with 2 arguments, including metatag processing, + and return only the first return value.
+ LuaValuecall(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+          Call this with 3 arguments, including metatag processing, + and return only the first return value.
+ Varargsinvoke(Varargs varargs) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+OneArgFunction

+
+public OneArgFunction()
+
+
Default constructor +

+

+
+ +

+OneArgFunction

+
+public OneArgFunction(LuaValue env)
+
+
Constructor with specific environment +

+

+
Parameters:
env - The environment to apply during constructon.
+
+ + + + + + + + +
+Method Detail
+ +

+call

+
+public abstract LuaValue call(LuaValue arg)
+
+
Description copied from class: LuaValue
+
Call this with 1 argument, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+
Parameters:
arg - First argument to supply to the called function +
Returns:
First return value (this(arg)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue,LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue), +LuaValue.method(String,LuaValue), +LuaValue.method(LuaValue,LuaValue)
+
+
+
+ +

+call

+
+public final LuaValue call()
+
+
Description copied from class: LuaValue
+
Call this with 0 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+ +
Returns:
First return value (this()), or NIL if there were none.
See Also:
LuaValue.call(LuaValue), +LuaValue.call(LuaValue,LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +LuaValue.invoke(), +LuaValue.method(String), +LuaValue.method(LuaValue)
+
+
+
+ +

+call

+
+public final LuaValue call(LuaValue arg1,
+                           LuaValue arg2)
+
+
Description copied from class: LuaValue
+
Call this with 2 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+
Parameters:
arg1 - First argument to supply to the called function
arg2 - Second argument to supply to the called function +
Returns:
First return value (this(arg1,arg2)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue,LuaValue), +LuaValue.method(String,LuaValue,LuaValue), +LuaValue.method(LuaValue,LuaValue,LuaValue)
+
+
+
+ +

+call

+
+public LuaValue call(LuaValue arg1,
+                     LuaValue arg2,
+                     LuaValue arg3)
+
+
Description copied from class: LuaValue
+
Call this with 3 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+
Parameters:
arg1 - First argument to supply to the called function
arg2 - Second argument to supply to the called function
arg3 - Second argument to supply to the called function +
Returns:
First return value (this(arg1,arg2,arg3)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue), +LuaValue.call(LuaValue, LuaValue), +#invoke(LuaValue,LuaValue, LuaValue), +LuaValue.invokemethod(String,Varargs), +LuaValue.invokemethod(LuaValue,Varargs)
+
+
+
+ +

+invoke

+
+public Varargs invoke(Varargs varargs)
+
+
Description copied from class: LuaValue
+
Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs. +

+ If this is a LuaFunction, call it, and return all values. + Otherwise, look for the CALL metatag and call that. +

+ To get a particular return value, us Varargs.arg(int) +

+ To call this as a method call, use LuaValue.invokemethod(LuaValue) instead. +

+

+
Overrides:
invoke in class LuaValue
+
+
+
Parameters:
varargs - Varargs containing the arguments to supply to the called function +
Returns:
All return values as a Varargs instance.
See Also:
LuaValue.varargsOf(LuaValue[]), +LuaValue.call(LuaValue), +LuaValue.invoke(), +LuaValue.invoke(LuaValue,Varargs), +LuaValue.invokemethod(String,Varargs), +LuaValue.invokemethod(LuaValue,Varargs)
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/OsLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/OsLib.html new file mode 100644 index 0000000000..83026cd3cf --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/OsLib.html @@ -0,0 +1,772 @@ + + + + + + +OsLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib +
+Class OsLib

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.VarArgFunction
+                      extended by org.luaj.vm2.lib.OsLib
+
+
+
Direct Known Subclasses:
JseOsLib
+
+
+
+
public class OsLib
extends VarArgFunction
+ + +

+Subclass of LibFunction which implements the standard lua os library. +

+ It is a usable base with simplified stub functions + for library functions that cannot be implemented uniformly + on Jse and Jme. +

+ This can be installed as-is on either platform, or extended + and refined to be used in a complete Jse implementation. +

+ Because the nature of the os library is to encapsulate + os-specific features, the behavior of these functions varies considerably + from their counterparts in the C platform. +

+ The following functions have limited implementations of features + that are not supported well on Jme: +

    +
  • execute()
  • +
  • remove()
  • +
  • rename()
  • +
  • tmpname()
  • +
+

+ Typically, this library is included as part of a call to either + JmePlatform#standardGlobals() +

+ To instantiate and use it directly, + link it into your globals table via LuaValue.load(LuaValue) using code such as: +

 LuaTable _G = new LuaTable();
+ LuaThread.setGlobals(_G);
+ _G.load(new BaseLib());
+ _G.load(new PackageLib());
+ _G.load(new OsLib());
+ System.out.println( _G.get("os").get("time").call() );
+  
+ Doing so will ensure the library is properly initialized + and loaded into the globals table. +

+

+ +

+

+
See Also:
LibFunction, +JseOsLib, +JsePlatform, +JmePlatform, +http://www.lua.org/manual/5.1/manual.html#5.8
+
+ +

+ + + + + + + + + + + + + + + +
+Field Summary
+static java.lang.StringTMP_PREFIX + +
+           
+static java.lang.StringTMP_SUFFIX + +
+           
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + +
+Constructor Summary
OsLib() + +
+          Create and OsLib instance.
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+protected  doubleclock() + +
+           
+protected  java.lang.Stringdate(java.lang.String format, + double time) + +
+          If the time argument is present, this is the time to be formatted + (see the os.time function for a description of this value).
+protected  doubledifftime(double t2, + double t1) + +
+          Returns the number of seconds from time t1 to time t2.
+protected  intexecute(java.lang.String command) + +
+          This function is equivalent to the C function system.
+protected  voidexit(int code) + +
+          Calls the C function exit, with an optional code, to terminate the host program.
+protected  java.lang.Stringgetenv(java.lang.String varname) + +
+          Returns the value of the process environment variable varname, + or null if the variable is not defined.
+ LuaValueinit() + +
+           
+ Varargsinvoke(Varargs args) + +
+          Override and implement for the best performance.
+protected  voidremove(java.lang.String filename) + +
+          Deletes the file or directory with the given name.
+protected  voidrename(java.lang.String oldname, + java.lang.String newname) + +
+          Renames file or directory named oldname to newname.
+protected  java.lang.Stringsetlocale(java.lang.String locale, + java.lang.String category) + +
+          Sets the current locale of the program.
+protected  longtime(LuaTable table) + +
+          Returns the current time when called without arguments, + or a time representing the date and time specified by the given table.
+protected  java.lang.Stringtmpname() + +
+          Returns a string with a file name that can be used for a temporary file.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.VarArgFunction
call, call, call, call, onInvoke
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+TMP_PREFIX

+
+public static java.lang.String TMP_PREFIX
+
+
+
+
+
+ +

+TMP_SUFFIX

+
+public static java.lang.String TMP_SUFFIX
+
+
+
+
+ + + + + + + + +
+Constructor Detail
+ +

+OsLib

+
+public OsLib()
+
+
Create and OsLib instance. +

+

+ + + + + + + + +
+Method Detail
+ +

+init

+
+public LuaValue init()
+
+
+
+
+
+
+ +

+invoke

+
+public Varargs invoke(Varargs args)
+
+
Description copied from class: VarArgFunction
+
Override and implement for the best performance. + May not have expected behavior for tail calls. + Should not be used if either: + - function needs to be used as a module + - function has a possibility of returning a TailcallVarargs +

+

+
Overrides:
invoke in class VarArgFunction
+
+
+
Parameters:
args - the arguments to the function call. +
Returns:
All return values as a Varargs instance.
See Also:
LuaValue.varargsOf(LuaValue[]), +LuaValue.call(LuaValue), +LuaValue.invoke(), +LuaValue.invoke(LuaValue,Varargs), +LuaValue.invokemethod(String,Varargs), +LuaValue.invokemethod(LuaValue,Varargs)
+
+
+
+ +

+clock

+
+protected double clock()
+
+
+ +
Returns:
an approximation of the amount in seconds of CPU time used by + the program.
+
+
+
+ +

+difftime

+
+protected double difftime(double t2,
+                          double t1)
+
+
Returns the number of seconds from time t1 to time t2. + In POSIX, Windows, and some other systems, this value is exactly t2-t1. +

+

+
Parameters:
t2 -
t1 - +
Returns:
diffeence in time values, in seconds
+
+
+
+ +

+date

+
+protected java.lang.String date(java.lang.String format,
+                                double time)
+
+
If the time argument is present, this is the time to be formatted + (see the os.time function for a description of this value). + Otherwise, date formats the current time. + + If format starts with '!', then the date is formatted in Coordinated + Universal Time. After this optional character, if format is the string + "*t", then date returns a table with the following fields: year + (four digits), month (1--12), day (1--31), hour (0--23), min (0--59), + sec (0--61), wday (weekday, Sunday is 1), yday (day of the year), + and isdst (daylight saving flag, a boolean). + + If format is not "*t", then date returns the date as a string, + formatted according to the same rules as the C function strftime. + + When called without arguments, date returns a reasonable date and + time representation that depends on the host system and on the + current locale (that is, os.date() is equivalent to os.date("%c")). +

+

+
Parameters:
format -
time - time since epoch, or -1 if not supplied +
Returns:
a LString or a LTable containing date and time, + formatted according to the given string format.
+
+
+
+ +

+execute

+
+protected int execute(java.lang.String command)
+
+
This function is equivalent to the C function system. + It passes command to be executed by an operating system shell. + It returns a status code, which is system-dependent. + If command is absent, then it returns nonzero if a shell + is available and zero otherwise. +

+

+
Parameters:
command - command to pass to the system
+
+
+
+ +

+exit

+
+protected void exit(int code)
+
+
Calls the C function exit, with an optional code, to terminate the host program. +

+

+
Parameters:
code -
+
+
+
+ +

+getenv

+
+protected java.lang.String getenv(java.lang.String varname)
+
+
Returns the value of the process environment variable varname, + or null if the variable is not defined. +

+

+
Parameters:
varname - +
Returns:
String value, or null if not defined
+
+
+
+ +

+remove

+
+protected void remove(java.lang.String filename)
+               throws java.io.IOException
+
+
Deletes the file or directory with the given name. + Directories must be empty to be removed. + If this function fails, it throws and IOException +

+

+
Parameters:
filename - +
Throws: +
java.io.IOException - if it fails
+
+
+
+ +

+rename

+
+protected void rename(java.lang.String oldname,
+                      java.lang.String newname)
+               throws java.io.IOException
+
+
Renames file or directory named oldname to newname. + If this function fails,it throws and IOException +

+

+
Parameters:
oldname - old file name
newname - new file name +
Throws: +
java.io.IOException - if it fails
+
+
+
+ +

+setlocale

+
+protected java.lang.String setlocale(java.lang.String locale,
+                                     java.lang.String category)
+
+
Sets the current locale of the program. locale is a string specifying + a locale; category is an optional string describing which category to change: + "all", "collate", "ctype", "monetary", "numeric", or "time"; the default category + is "all". + + If locale is the empty string, the current locale is set to an implementation- + defined native locale. If locale is the string "C", the current locale is set + to the standard C locale. + + When called with null as the first argument, this function only returns the + name of the current locale for the given category. +

+

+
Parameters:
locale -
category - +
Returns:
the name of the new locale, or null if the request + cannot be honored.
+
+
+
+ +

+time

+
+protected long time(LuaTable table)
+
+
Returns the current time when called without arguments, + or a time representing the date and time specified by the given table. + This table must have fields year, month, and day, + and may have fields hour, min, sec, and isdst + (for a description of these fields, see the os.date function). +

+

+
Parameters:
table - +
Returns:
long value for the time
+
+
+
+ +

+tmpname

+
+protected java.lang.String tmpname()
+
+
Returns a string with a file name that can be used for a temporary file. + The file must be explicitly opened before its use and explicitly removed + when no longer needed. + + On some systems (POSIX), this function also creates a file with that name, + to avoid security risks. (Someone else might create the file with wrong + permissions in the time between getting the name and creating the file.) + You still have to open the file to use it and to remove it (even if you + do not use it). +

+

+ +
Returns:
String filename to use
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/PackageLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/PackageLib.html new file mode 100644 index 0000000000..0ae9595a4f --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/PackageLib.html @@ -0,0 +1,772 @@ + + + + + + +PackageLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib +
+Class PackageLib

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.OneArgFunction
+                      extended by org.luaj.vm2.lib.PackageLib
+
+
+
+
public class PackageLib
extends OneArgFunction
+ + +

+Subclass of LibFunction which implements the lua standard package and module + library functions. + +

+ Typically, this library is included as part of a call to either + JsePlatform#standardGlobals() or JmePlatform#standardGlobals() +

+ To instantiate and use it directly, + link it into your globals table via LuaValue.load(LuaValue) using code such as: +

 LuaTable _G = new LuaTable();
+ LuaThread.setGlobals(_G);
+ _G.load(new BaseLib());
+ _G.load(new PackageLib());
+ System.out.println( _G.get("require").call(LuaValue.valueOf("hyperbolic")) );
+  
+ In practice, the first 4 lines of the above are minimal requirements to get + and initialize a globals table capable of basic reqire, print, and other functions, + so it is much more convenient to use the JsePlatform and JmePlatform + utility classes instead. +

+ This has been implemented to match as closely as possible the behavior in the corresponding library in C. + However, the default filesystem search semantics are different and delegated to the bas library + as outlined in the BaseLib and JseBaseLib documetnation. +

+ +

+

+
See Also:
LibFunction, +BaseLib, +JseBaseLib, +JsePlatform, +JmePlatform, +http://www.lua.org/manual/5.1/manual.html#5.3
+
+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Field Summary
+static java.lang.StringDEFAULT_LUA_PATH + +
+           
+static PackageLibinstance + +
+          Most recent instance of PackageLib
+ LuaValuejava_loader + +
+          Loader that loads as a Java class.
+ LuaTableLOADED + +
+           
+ LuaValuelua_loader + +
+          Loader that loads as a lua script using the LUA_PATH
+ LuaTablePACKAGE + +
+           
+ LuaValuepreload_loader + +
+          Loader that loads from preload table if found there
+ java.io.InputStreamSTDIN + +
+           
+ java.io.PrintStreamSTDOUT + +
+           
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + +
+Constructor Summary
PackageLib() + +
+           
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ LuaValuecall(LuaValue arg) + +
+          Call this with 1 argument, including metatag processing, + and return only the first return value.
+static Varargsloadlib(Varargs args) + +
+           
+ Varargsmodule(Varargs args) + +
+          module (name [, ...]) + + Creates a module.
+ LuaValuerequire(LuaValue arg) + +
+          require (modname) + + Loads the given module.
+ voidsetIsLoaded(java.lang.String name, + LuaTable value) + +
+          Allow packages to mark themselves as loaded
+ voidsetLuaPath(java.lang.String newLuaPath) + +
+           
+static java.lang.StringtoClassname(java.lang.String filename) + +
+          Convert lua filename to valid class name
+ java.lang.Stringtojstring() + +
+          Convert to human readable String for any type.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.OneArgFunction
call, call, call, invoke
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+DEFAULT_LUA_PATH

+
+public static java.lang.String DEFAULT_LUA_PATH
+
+
+
+
+
+ +

+STDIN

+
+public java.io.InputStream STDIN
+
+
+
+
+
+ +

+STDOUT

+
+public java.io.PrintStream STDOUT
+
+
+
+
+
+ +

+LOADED

+
+public LuaTable LOADED
+
+
+
+
+
+ +

+PACKAGE

+
+public LuaTable PACKAGE
+
+
+
+
+
+ +

+instance

+
+public static PackageLib instance
+
+
Most recent instance of PackageLib +

+

+
+
+
+ +

+preload_loader

+
+public LuaValue preload_loader
+
+
Loader that loads from preload table if found there +

+

+
+
+
+ +

+lua_loader

+
+public LuaValue lua_loader
+
+
Loader that loads as a lua script using the LUA_PATH +

+

+
+
+
+ +

+java_loader

+
+public LuaValue java_loader
+
+
Loader that loads as a Java class. Class must have public constructor and be a LuaValue +

+

+
+
+ + + + + + + + +
+Constructor Detail
+ +

+PackageLib

+
+public PackageLib()
+
+
+ + + + + + + + +
+Method Detail
+ +

+call

+
+public LuaValue call(LuaValue arg)
+
+
Description copied from class: LuaValue
+
Call this with 1 argument, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Specified by:
call in class OneArgFunction
+
+
+
Parameters:
arg - First argument to supply to the called function +
Returns:
First return value (this(arg)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue,LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue), +LuaValue.method(String,LuaValue), +LuaValue.method(LuaValue,LuaValue)
+
+
+
+ +

+setIsLoaded

+
+public void setIsLoaded(java.lang.String name,
+                        LuaTable value)
+
+
Allow packages to mark themselves as loaded +

+

+
+
+
+
+ +

+setLuaPath

+
+public void setLuaPath(java.lang.String newLuaPath)
+
+
+
+
+
+
+ +

+tojstring

+
+public java.lang.String tojstring()
+
+
Description copied from class: LuaValue
+
Convert to human readable String for any type. +

+

+
Overrides:
tojstring in class LibFunction
+
+
+ +
Returns:
String for use by human readers based on type.
See Also:
LuaValue.tostring(), +LuaValue.optjstring(String), +LuaValue.checkjstring(), +LuaValue.isstring(), +TSTRING
+
+
+
+ +

+module

+
+public Varargs module(Varargs args)
+
+
module (name [, ...]) + + Creates a module. If there is a table in package.loaded[name], this table + is the module. Otherwise, if there is a global table t with the given + name, this table is the module. Otherwise creates a new table t and sets + it as the value of the global name and the value of package.loaded[name]. + This function also initializes t._NAME with the given name, t._M with the + module (t itself), and t._PACKAGE with the package name (the full module + name minus last component; see below). Finally, module sets t as the new + environment of the current function and the new value of + package.loaded[name], so that require returns t. + + If name is a compound name (that is, one with components separated by + dots), module creates (or reuses, if they already exist) tables for each + component. For instance, if name is a.b.c, then module stores the module + table in field c of field b of global a. + + This function may receive optional options after the module name, where + each option is a function to be applied over the module. +

+

+
+
+
+
+ +

+require

+
+public LuaValue require(LuaValue arg)
+
+
require (modname) + + Loads the given module. The function starts by looking into the package.loaded table to + determine whether modname is already loaded. If it is, then require returns the value + stored at package.loaded[modname]. Otherwise, it tries to find a loader for the module. + + To find a loader, require is guided by the package.loaders array. By changing this array, + we can change how require looks for a module. The following explanation is based on the + default configuration for package.loaders. + + First require queries package.preload[modname]. If it has a value, this value + (which should be a function) is the loader. Otherwise require searches for a Lua loader + using the path stored in package.path. If that also fails, it searches for a C loader + using the path stored in package.cpath. If that also fails, it tries an all-in-one loader + (see package.loaders). + + Once a loader is found, require calls the loader with a single argument, modname. + If the loader returns any value, require assigns the returned value to package.loaded[modname]. + If the loader returns no value and has not assigned any value to package.loaded[modname], + then require assigns true to this entry. In any case, require returns the final value of + package.loaded[modname]. + + If there is any error loading or running the module, or if it cannot find any loader for + the module, then require signals an error. +

+

+
+
+
+
+ +

+loadlib

+
+public static Varargs loadlib(Varargs args)
+
+
+
+
+
+
+ +

+toClassname

+
+public static final java.lang.String toClassname(java.lang.String filename)
+
+
Convert lua filename to valid class name +

+

+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/ResourceFinder.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/ResourceFinder.html new file mode 100644 index 0000000000..81ff0032a8 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/ResourceFinder.html @@ -0,0 +1,234 @@ + + + + + + +ResourceFinder (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib +
+Interface ResourceFinder

+
+
All Known Implementing Classes:
BaseLib, JseBaseLib
+
+
+
+
public interface ResourceFinder
+ + +

+Interface for opening application resource files such as scripts sources. +

+ This is used by required to load files that are part of + the application, and implemented by BaseLib + for both the Jme and Jse platforms. +

+ The Jme version of base lib BaseLib + implements BaseLib.FINDER via Class.getResourceAsStream(String), + while the Jse version JseBaseLib implements it using File.File(String). +

+ The io library does not use this API for file manipulation. +

+

+ +

+

+
See Also:
BaseLib, +BaseLib.FINDER, +JseBaseLib, +JmePlatform, +JsePlatform
+
+ +

+ + + + + + + + + + + + +
+Method Summary
+ java.io.InputStreamfindResource(java.lang.String filename) + +
+          Try to open a file, or return null if not found.
+  +

+ + + + + + + + +
+Method Detail
+ +

+findResource

+
+java.io.InputStream findResource(java.lang.String filename)
+
+
Try to open a file, or return null if not found. +

+

+
Parameters:
filename - +
Returns:
InputStream, or null if not found.
See Also:
BaseLib, +JseBaseLib
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/StringLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/StringLib.html new file mode 100644 index 0000000000..33403d2855 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/StringLib.html @@ -0,0 +1,445 @@ + + + + + + +StringLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib +
+Class StringLib

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.OneArgFunction
+                      extended by org.luaj.vm2.lib.StringLib
+
+
+
+
public class StringLib
extends OneArgFunction
+ + +

+Subclass of LibFunction which implements the lua standard string + library. + +

+ Typically, this library is included as part of a call to either + JsePlatform#standardGlobals() or JmePlatform#standardGlobals() +

+ To instantiate and use it directly, + link it into your globals table via LuaValue.load(LuaValue) using code such as: +

 LuaTable _G = new LuaTable();
+ LuaThread.setGlobals(_G);
+ _G.load(new BaseLib());
+ _G.load(new PackageLib());
+ _G.load(new StringLib());
+ System.out.println( _G.get("string").get("upper").call( LuaValue.valueOf("abcde") ) );
+  
+ Doing so will ensure the library is properly initialized + and loaded into the globals table. +

+ This is a direct port of the corresponding library in C. +

+ +

+

+
See Also:
LibFunction, +JsePlatform, +JmePlatform, +http://www.lua.org/manual/5.1/manual.html#5.4
+
+ +

+ + + + + + + + + + + +
+Field Summary
+static LuaTableinstance + +
+           
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + +
+Constructor Summary
StringLib() + +
+           
+  + + + + + + + + + + + + + + + +
+Method Summary
+ LuaValuecall(LuaValue arg) + +
+          Call this with 1 argument, including metatag processing, + and return only the first return value.
+static Varargschar_(Varargs args) + +
+          string.char (...) + + Receives zero or more integers.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.OneArgFunction
call, call, call, invoke
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+instance

+
+public static LuaTable instance
+
+
+
+
+ + + + + + + + +
+Constructor Detail
+ +

+StringLib

+
+public StringLib()
+
+
+ + + + + + + + +
+Method Detail
+ +

+call

+
+public LuaValue call(LuaValue arg)
+
+
Description copied from class: LuaValue
+
Call this with 1 argument, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Specified by:
call in class OneArgFunction
+
+
+
Parameters:
arg - First argument to supply to the called function +
Returns:
First return value (this(arg)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue,LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue), +LuaValue.method(String,LuaValue), +LuaValue.method(LuaValue,LuaValue)
+
+
+
+ +

+char_

+
+public static Varargs char_(Varargs args)
+
+
string.char (...) + + Receives zero or more integers. Returns a string with length equal + to the number of arguments, in which each character has the internal + numerical code equal to its corresponding argument. + + Note that numerical codes are not necessarily portable across platforms. +

+

+
Parameters:
args - the calling VM
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/TableLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/TableLib.html new file mode 100644 index 0000000000..bd0c8bab1b --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/TableLib.html @@ -0,0 +1,393 @@ + + + + + + +TableLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib +
+Class TableLib

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.OneArgFunction
+                      extended by org.luaj.vm2.lib.TableLib
+
+
+
+
public class TableLib
extends OneArgFunction
+ + +

+Subclass of LibFunction which implements the lua standard table + library. + +

+ Typically, this library is included as part of a call to either + JsePlatform#standardGlobals() or JmePlatform#standardGlobals() +

+ To instantiate and use it directly, + link it into your globals table via LuaValue.load(LuaValue) using code such as: +

 LuaTable _G = new LuaTable();
+ LuaThread.setGlobals(_G);
+ _G.load(new BaseLib());
+ _G.load(new PackageLib());
+ _G.load(new TableLib());
+ LuaValue tbl = LuaValue.listOf( new LuaValue[] {
+ 		LuaValue.valueOf( "abc" ),
+ 		LuaValue.valueOf( "def" ) } );
+ LuaValue sep = LuaValue.valueOf( "-" );
+ System.out.println( _G.get("table").get("concat").call( tbl, sep ) );
+  
+ Doing so will ensure the library is properly initialized + and loaded into the globals table. +

+ This has been implemented to match as closely as possible the behavior in the corresponding library in C. +

+ +

+

+
See Also:
LibFunction, +JsePlatform, +JmePlatform, +http://www.lua.org/manual/5.1/manual.html#5.5
+
+ +

+ + + + + + + +
+Field Summary
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + +
+Constructor Summary
TableLib() + +
+           
+  + + + + + + + + + + + +
+Method Summary
+ LuaValuecall(LuaValue arg) + +
+          Call this with 1 argument, including metatag processing, + and return only the first return value.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.OneArgFunction
call, call, call, invoke
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+TableLib

+
+public TableLib()
+
+
+ + + + + + + + +
+Method Detail
+ +

+call

+
+public LuaValue call(LuaValue arg)
+
+
Description copied from class: LuaValue
+
Call this with 1 argument, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Specified by:
call in class OneArgFunction
+
+
+
Parameters:
arg - First argument to supply to the called function +
Returns:
First return value (this(arg)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue,LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue), +LuaValue.method(String,LuaValue), +LuaValue.method(LuaValue,LuaValue)
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/ThreeArgFunction.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/ThreeArgFunction.html new file mode 100644 index 0000000000..7a5bdd7284 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/ThreeArgFunction.html @@ -0,0 +1,568 @@ + + + + + + +ThreeArgFunction (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib +
+Class ThreeArgFunction

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.ThreeArgFunction
+
+
+
+
public abstract class ThreeArgFunction
extends LibFunction
+ + +

+Abstract base class for Java function implementations that take two arguments and + return one value. +

+ Subclasses need only implement LuaValue.call(LuaValue,LuaValue,LuaValue) to complete this class, + simplifying development. + All other uses of call(), invoke(Varargs),etc, + are routed through this method by this class, + dropping or extending arguments with nil values as required. +

+ If more or less than three arguments are required, + or variable argument or variable return values, + then use one of the related function + ZeroArgFunction, OneArgFunction, TwoArgFunction, or VarArgFunction. +

+ See LibFunction for more information on implementation libraries and library functions. +

+ +

+

+
See Also:
call(LuaValue,LuaValue,LuaValue), +LibFunction, +ZeroArgFunction, +OneArgFunction, +TwoArgFunction, +VarArgFunction
+
+ +

+ + + + + + + +
+Field Summary
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + + + + +
+Constructor Summary
ThreeArgFunction() + +
+          Default constructor
ThreeArgFunction(LuaValue env) + +
+          Constructor with specific environment
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ LuaValuecall() + +
+          Call this with 0 arguments, including metatag processing, + and return only the first return value.
+ LuaValuecall(LuaValue arg) + +
+          Call this with 1 argument, including metatag processing, + and return only the first return value.
+ LuaValuecall(LuaValue arg1, + LuaValue arg2) + +
+          Call this with 2 arguments, including metatag processing, + and return only the first return value.
+abstract  LuaValuecall(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+          Call this with 3 arguments, including metatag processing, + and return only the first return value.
+ Varargsinvoke(Varargs varargs) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+ThreeArgFunction

+
+public ThreeArgFunction()
+
+
Default constructor +

+

+
+ +

+ThreeArgFunction

+
+public ThreeArgFunction(LuaValue env)
+
+
Constructor with specific environment +

+

+
Parameters:
env - The environment to apply during constructon.
+
+ + + + + + + + +
+Method Detail
+ +

+call

+
+public abstract LuaValue call(LuaValue arg1,
+                              LuaValue arg2,
+                              LuaValue arg3)
+
+
Description copied from class: LuaValue
+
Call this with 3 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+
Parameters:
arg1 - First argument to supply to the called function
arg2 - Second argument to supply to the called function
arg3 - Second argument to supply to the called function +
Returns:
First return value (this(arg1,arg2,arg3)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue), +LuaValue.call(LuaValue, LuaValue), +#invoke(LuaValue,LuaValue, LuaValue), +LuaValue.invokemethod(String,Varargs), +LuaValue.invokemethod(LuaValue,Varargs)
+
+
+
+ +

+call

+
+public final LuaValue call()
+
+
Description copied from class: LuaValue
+
Call this with 0 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+ +
Returns:
First return value (this()), or NIL if there were none.
See Also:
LuaValue.call(LuaValue), +LuaValue.call(LuaValue,LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +LuaValue.invoke(), +LuaValue.method(String), +LuaValue.method(LuaValue)
+
+
+
+ +

+call

+
+public final LuaValue call(LuaValue arg)
+
+
Description copied from class: LuaValue
+
Call this with 1 argument, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+
Parameters:
arg - First argument to supply to the called function +
Returns:
First return value (this(arg)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue,LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue), +LuaValue.method(String,LuaValue), +LuaValue.method(LuaValue,LuaValue)
+
+
+
+ +

+call

+
+public LuaValue call(LuaValue arg1,
+                     LuaValue arg2)
+
+
Description copied from class: LuaValue
+
Call this with 2 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+
Parameters:
arg1 - First argument to supply to the called function
arg2 - Second argument to supply to the called function +
Returns:
First return value (this(arg1,arg2)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue,LuaValue), +LuaValue.method(String,LuaValue,LuaValue), +LuaValue.method(LuaValue,LuaValue,LuaValue)
+
+
+
+ +

+invoke

+
+public Varargs invoke(Varargs varargs)
+
+
Description copied from class: LuaValue
+
Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs. +

+ If this is a LuaFunction, call it, and return all values. + Otherwise, look for the CALL metatag and call that. +

+ To get a particular return value, us Varargs.arg(int) +

+ To call this as a method call, use LuaValue.invokemethod(LuaValue) instead. +

+

+
Overrides:
invoke in class LuaValue
+
+
+
Parameters:
varargs - Varargs containing the arguments to supply to the called function +
Returns:
All return values as a Varargs instance.
See Also:
LuaValue.varargsOf(LuaValue[]), +LuaValue.call(LuaValue), +LuaValue.invoke(), +LuaValue.invoke(LuaValue,Varargs), +LuaValue.invokemethod(String,Varargs), +LuaValue.invokemethod(LuaValue,Varargs)
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/TwoArgFunction.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/TwoArgFunction.html new file mode 100644 index 0000000000..1a51ef6b18 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/TwoArgFunction.html @@ -0,0 +1,571 @@ + + + + + + +TwoArgFunction (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib +
+Class TwoArgFunction

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.TwoArgFunction
+
+
+
Direct Known Subclasses:
JseMathLib.JseMathLib2
+
+
+
+
public abstract class TwoArgFunction
extends LibFunction
+ + +

+Abstract base class for Java function implementations that take two arguments and + return one value. +

+ Subclasses need only implement LuaValue.call(LuaValue,LuaValue) to complete this class, + simplifying development. + All other uses of call(), invoke(Varargs),etc, + are routed through this method by this class, + dropping or extending arguments with nil values as required. +

+ If more or less than two arguments are required, + or variable argument or variable return values, + then use one of the related function + ZeroArgFunction, OneArgFunction, ThreeArgFunction, or VarArgFunction. +

+ See LibFunction for more information on implementation libraries and library functions. +

+ +

+

+
See Also:
call(LuaValue,LuaValue), +LibFunction, +ZeroArgFunction, +OneArgFunction, +ThreeArgFunction, +VarArgFunction
+
+ +

+ + + + + + + +
+Field Summary
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + + + + +
+Constructor Summary
TwoArgFunction() + +
+          Default constructor
TwoArgFunction(LuaValue env) + +
+          Constructor with specific environment
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ LuaValuecall() + +
+          Call this with 0 arguments, including metatag processing, + and return only the first return value.
+ LuaValuecall(LuaValue arg) + +
+          Call this with 1 argument, including metatag processing, + and return only the first return value.
+abstract  LuaValuecall(LuaValue arg1, + LuaValue arg2) + +
+          Call this with 2 arguments, including metatag processing, + and return only the first return value.
+ LuaValuecall(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+          Call this with 3 arguments, including metatag processing, + and return only the first return value.
+ Varargsinvoke(Varargs varargs) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+TwoArgFunction

+
+public TwoArgFunction()
+
+
Default constructor +

+

+
+ +

+TwoArgFunction

+
+public TwoArgFunction(LuaValue env)
+
+
Constructor with specific environment +

+

+
Parameters:
env - The environment to apply during constructon.
+
+ + + + + + + + +
+Method Detail
+ +

+call

+
+public abstract LuaValue call(LuaValue arg1,
+                              LuaValue arg2)
+
+
Description copied from class: LuaValue
+
Call this with 2 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+
Parameters:
arg1 - First argument to supply to the called function
arg2 - Second argument to supply to the called function +
Returns:
First return value (this(arg1,arg2)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue,LuaValue), +LuaValue.method(String,LuaValue,LuaValue), +LuaValue.method(LuaValue,LuaValue,LuaValue)
+
+
+
+ +

+call

+
+public final LuaValue call()
+
+
Description copied from class: LuaValue
+
Call this with 0 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+ +
Returns:
First return value (this()), or NIL if there were none.
See Also:
LuaValue.call(LuaValue), +LuaValue.call(LuaValue,LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +LuaValue.invoke(), +LuaValue.method(String), +LuaValue.method(LuaValue)
+
+
+
+ +

+call

+
+public final LuaValue call(LuaValue arg)
+
+
Description copied from class: LuaValue
+
Call this with 1 argument, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+
Parameters:
arg - First argument to supply to the called function +
Returns:
First return value (this(arg)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue,LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue), +LuaValue.method(String,LuaValue), +LuaValue.method(LuaValue,LuaValue)
+
+
+
+ +

+call

+
+public LuaValue call(LuaValue arg1,
+                     LuaValue arg2,
+                     LuaValue arg3)
+
+
Description copied from class: LuaValue
+
Call this with 3 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+
Parameters:
arg1 - First argument to supply to the called function
arg2 - Second argument to supply to the called function
arg3 - Second argument to supply to the called function +
Returns:
First return value (this(arg1,arg2,arg3)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue), +LuaValue.call(LuaValue, LuaValue), +#invoke(LuaValue,LuaValue, LuaValue), +LuaValue.invokemethod(String,Varargs), +LuaValue.invokemethod(LuaValue,Varargs)
+
+
+
+ +

+invoke

+
+public Varargs invoke(Varargs varargs)
+
+
Description copied from class: LuaValue
+
Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs. +

+ If this is a LuaFunction, call it, and return all values. + Otherwise, look for the CALL metatag and call that. +

+ To get a particular return value, us Varargs.arg(int) +

+ To call this as a method call, use LuaValue.invokemethod(LuaValue) instead. +

+

+
Overrides:
invoke in class LuaValue
+
+
+
Parameters:
varargs - Varargs containing the arguments to supply to the called function +
Returns:
All return values as a Varargs instance.
See Also:
LuaValue.varargsOf(LuaValue[]), +LuaValue.call(LuaValue), +LuaValue.invoke(), +LuaValue.invoke(LuaValue,Varargs), +LuaValue.invokemethod(String,Varargs), +LuaValue.invokemethod(LuaValue,Varargs)
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/VarArgFunction.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/VarArgFunction.html new file mode 100644 index 0000000000..90bc5e6366 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/VarArgFunction.html @@ -0,0 +1,590 @@ + + + + + + +VarArgFunction (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib +
+Class VarArgFunction

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.VarArgFunction
+
+
+
Direct Known Subclasses:
CoroutineLib, DebugLib, LuajavaLib, OsLib
+
+
+
+
public abstract class VarArgFunction
extends LibFunction
+ + +

+Abstract base class for Java function implementations that takes varaiable arguments and + returns multiple return values. +

+ Subclasses need only implement LuaValue.invoke(Varargs) to complete this class, + simplifying development. + All other uses of call(LuaValue), LuaValue.invoke(),etc, + are routed through this method by this class, + converting arguments to and + dropping or extending return values with nil values as required. +

+ If between one and three arguments are required, and only one return value is returned, + ZeroArgFunction, OneArgFunction, TwoArgFunction, or ThreeArgFunction. +

+ See LibFunction for more information on implementation libraries and library functions. +

+ +

+

+
See Also:
invoke(Varargs), +LibFunction, +ZeroArgFunction, +OneArgFunction, +TwoArgFunction, +ThreeArgFunction
+
+ +

+ + + + + + + +
+Field Summary
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + + + + +
+Constructor Summary
VarArgFunction() + +
+           
VarArgFunction(LuaValue env) + +
+           
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ LuaValuecall() + +
+          Call this with 0 arguments, including metatag processing, + and return only the first return value.
+ LuaValuecall(LuaValue arg) + +
+          Call this with 1 argument, including metatag processing, + and return only the first return value.
+ LuaValuecall(LuaValue arg1, + LuaValue arg2) + +
+          Call this with 2 arguments, including metatag processing, + and return only the first return value.
+ LuaValuecall(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+          Call this with 3 arguments, including metatag processing, + and return only the first return value.
+ Varargsinvoke(Varargs args) + +
+          Override and implement for the best performance.
+ VarargsonInvoke(Varargs args) + +
+          Override to provide a call implementation that runs in an environment + that can participate in setfenv, and behaves as expected + when returning TailcallVarargs.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+VarArgFunction

+
+public VarArgFunction()
+
+
+
+ +

+VarArgFunction

+
+public VarArgFunction(LuaValue env)
+
+
+ + + + + + + + +
+Method Detail
+ +

+call

+
+public LuaValue call()
+
+
Description copied from class: LuaValue
+
Call this with 0 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+ +
Returns:
First return value (this()), or NIL if there were none.
See Also:
LuaValue.call(LuaValue), +LuaValue.call(LuaValue,LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +LuaValue.invoke(), +LuaValue.method(String), +LuaValue.method(LuaValue)
+
+
+
+ +

+call

+
+public LuaValue call(LuaValue arg)
+
+
Description copied from class: LuaValue
+
Call this with 1 argument, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+
Parameters:
arg - First argument to supply to the called function +
Returns:
First return value (this(arg)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue,LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue), +LuaValue.method(String,LuaValue), +LuaValue.method(LuaValue,LuaValue)
+
+
+
+ +

+call

+
+public LuaValue call(LuaValue arg1,
+                     LuaValue arg2)
+
+
Description copied from class: LuaValue
+
Call this with 2 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+
Parameters:
arg1 - First argument to supply to the called function
arg2 - Second argument to supply to the called function +
Returns:
First return value (this(arg1,arg2)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue,LuaValue), +LuaValue.method(String,LuaValue,LuaValue), +LuaValue.method(LuaValue,LuaValue,LuaValue)
+
+
+
+ +

+call

+
+public LuaValue call(LuaValue arg1,
+                     LuaValue arg2,
+                     LuaValue arg3)
+
+
Description copied from class: LuaValue
+
Call this with 3 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+
Parameters:
arg1 - First argument to supply to the called function
arg2 - Second argument to supply to the called function
arg3 - Second argument to supply to the called function +
Returns:
First return value (this(arg1,arg2,arg3)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue), +LuaValue.call(LuaValue, LuaValue), +#invoke(LuaValue,LuaValue, LuaValue), +LuaValue.invokemethod(String,Varargs), +LuaValue.invokemethod(LuaValue,Varargs)
+
+
+
+ +

+invoke

+
+public Varargs invoke(Varargs args)
+
+
Override and implement for the best performance. + May not have expected behavior for tail calls. + Should not be used if either: + - function needs to be used as a module + - function has a possibility of returning a TailcallVarargs +

+

+
Overrides:
invoke in class LuaValue
+
+
+
Parameters:
args - the arguments to the function call. +
Returns:
All return values as a Varargs instance.
See Also:
LuaValue.varargsOf(LuaValue[]), +LuaValue.call(LuaValue), +LuaValue.invoke(), +LuaValue.invoke(LuaValue,Varargs), +LuaValue.invokemethod(String,Varargs), +LuaValue.invokemethod(LuaValue,Varargs)
+
+
+
+ +

+onInvoke

+
+public Varargs onInvoke(Varargs args)
+
+
Override to provide a call implementation that runs in an environment + that can participate in setfenv, and behaves as expected + when returning TailcallVarargs. +

+

+
Overrides:
onInvoke in class LuaValue
+
+
+
Parameters:
args - the arguments to the function call. +
Returns:
Varargs the return values, possible a TailcallVarargs.
See Also:
LuaValue.call(), +LuaValue.invoke(), +LuaValue.method(LuaValue), +LuaValue.invokemethod(LuaValue)
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/ZeroArgFunction.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/ZeroArgFunction.html new file mode 100644 index 0000000000..adecefd31a --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/ZeroArgFunction.html @@ -0,0 +1,566 @@ + + + + + + +ZeroArgFunction (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib +
+Class ZeroArgFunction

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.ZeroArgFunction
+
+
+
+
public abstract class ZeroArgFunction
extends LibFunction
+ + +

+Abstract base class for Java function implementations that take no arguments and + return one value. +

+ Subclasses need only implement LuaValue.call() to complete this class, + simplifying development. + All other uses of call(LuaValue), invoke(Varargs),etc, + are routed through this method by this class. +

+ If one or more arguments are required, or variable argument or variable return values, + then use one of the related function + OneArgFunction, TwoArgFunction, ThreeArgFunction, or VarArgFunction. +

+ See LibFunction for more information on implementation libraries and library functions. +

+ +

+

+
See Also:
call(), +LibFunction, +OneArgFunction, +TwoArgFunction, +ThreeArgFunction, +VarArgFunction
+
+ +

+ + + + + + + +
+Field Summary
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + + + + +
+Constructor Summary
ZeroArgFunction() + +
+          Default constructor
ZeroArgFunction(LuaValue env) + +
+          Constructor with specific environment
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+abstract  LuaValuecall() + +
+          Call this with 0 arguments, including metatag processing, + and return only the first return value.
+ LuaValuecall(LuaValue arg) + +
+          Call this with 1 argument, including metatag processing, + and return only the first return value.
+ LuaValuecall(LuaValue arg1, + LuaValue arg2) + +
+          Call this with 2 arguments, including metatag processing, + and return only the first return value.
+ LuaValuecall(LuaValue arg1, + LuaValue arg2, + LuaValue arg3) + +
+          Call this with 3 arguments, including metatag processing, + and return only the first return value.
+ Varargsinvoke(Varargs varargs) + +
+          Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+ZeroArgFunction

+
+public ZeroArgFunction()
+
+
Default constructor +

+

+
+ +

+ZeroArgFunction

+
+public ZeroArgFunction(LuaValue env)
+
+
Constructor with specific environment +

+

+
Parameters:
env - The environment to apply during constructon.
+
+ + + + + + + + +
+Method Detail
+ +

+call

+
+public abstract LuaValue call()
+
+
Description copied from class: LuaValue
+
Call this with 0 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+ +
Returns:
First return value (this()), or NIL if there were none.
See Also:
LuaValue.call(LuaValue), +LuaValue.call(LuaValue,LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +LuaValue.invoke(), +LuaValue.method(String), +LuaValue.method(LuaValue)
+
+
+
+ +

+call

+
+public LuaValue call(LuaValue arg)
+
+
Description copied from class: LuaValue
+
Call this with 1 argument, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+
Parameters:
arg - First argument to supply to the called function +
Returns:
First return value (this(arg)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue,LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue), +LuaValue.method(String,LuaValue), +LuaValue.method(LuaValue,LuaValue)
+
+
+
+ +

+call

+
+public LuaValue call(LuaValue arg1,
+                     LuaValue arg2)
+
+
Description copied from class: LuaValue
+
Call this with 2 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+
Parameters:
arg1 - First argument to supply to the called function
arg2 - Second argument to supply to the called function +
Returns:
First return value (this(arg1,arg2)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue,LuaValue), +LuaValue.method(String,LuaValue,LuaValue), +LuaValue.method(LuaValue,LuaValue,LuaValue)
+
+
+
+ +

+call

+
+public LuaValue call(LuaValue arg1,
+                     LuaValue arg2,
+                     LuaValue arg3)
+
+
Description copied from class: LuaValue
+
Call this with 3 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class LuaValue
+
+
+
Parameters:
arg1 - First argument to supply to the called function
arg2 - Second argument to supply to the called function
arg3 - Second argument to supply to the called function +
Returns:
First return value (this(arg1,arg2,arg3)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue), +LuaValue.call(LuaValue, LuaValue), +#invoke(LuaValue,LuaValue, LuaValue), +LuaValue.invokemethod(String,Varargs), +LuaValue.invokemethod(LuaValue,Varargs)
+
+
+
+ +

+invoke

+
+public Varargs invoke(Varargs varargs)
+
+
Description copied from class: LuaValue
+
Call this with variable arguments, including metatag processing, + and retain all return values in a Varargs. +

+ If this is a LuaFunction, call it, and return all values. + Otherwise, look for the CALL metatag and call that. +

+ To get a particular return value, us Varargs.arg(int) +

+ To call this as a method call, use LuaValue.invokemethod(LuaValue) instead. +

+

+
Overrides:
invoke in class LuaValue
+
+
+
Parameters:
varargs - Varargs containing the arguments to supply to the called function +
Returns:
All return values as a Varargs instance.
See Also:
LuaValue.varargsOf(LuaValue[]), +LuaValue.call(LuaValue), +LuaValue.invoke(), +LuaValue.invoke(LuaValue,Varargs), +LuaValue.invokemethod(String,Varargs), +LuaValue.invokemethod(LuaValue,Varargs)
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/BaseLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/BaseLib.html new file mode 100644 index 0000000000..bb7be79074 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/BaseLib.html @@ -0,0 +1,210 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.BaseLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.BaseLib

+
+ + + + + + + + + + + + + +
+Packages that use BaseLib
org.luaj.vm2.lib  
org.luaj.vm2.lib.jse  
+  +

+ + + + + +
+Uses of BaseLib in org.luaj.vm2.lib
+  +

+ + + + + + + + + +
Fields in org.luaj.vm2.lib declared as BaseLib
+static BaseLibBaseLib.instance + +
+           
+  +

+ + + + + +
+Uses of BaseLib in org.luaj.vm2.lib.jse
+  +

+ + + + + + + + + +
Subclasses of BaseLib in org.luaj.vm2.lib.jse
+ classJseBaseLib + +
+          Subclass of BaseLib and LibFunction which implements the lua basic library functions + and provides a directory based ResourceFinder as the FINDER.
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/CoroutineLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/CoroutineLib.html new file mode 100644 index 0000000000..64ab86d6da --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/CoroutineLib.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.CoroutineLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.CoroutineLib

+
+No usage of org.luaj.vm2.lib.CoroutineLib +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/DebugLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/DebugLib.html new file mode 100644 index 0000000000..aed890dc25 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/DebugLib.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.DebugLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.DebugLib

+
+No usage of org.luaj.vm2.lib.DebugLib +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/IoLib.File.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/IoLib.File.html new file mode 100644 index 0000000000..34c3543fb9 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/IoLib.File.html @@ -0,0 +1,399 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.IoLib.File (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.IoLib.File

+
+ + + + + + + + + + + + + + + + + +
+Packages that use IoLib.File
org.luaj.vm2.lib  
org.luaj.vm2.lib.jme  
org.luaj.vm2.lib.jse  
+  +

+ + + + + +
+Uses of IoLib.File in org.luaj.vm2.lib
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2.lib that return IoLib.File
+protected abstract  IoLib.FileIoLib.openFile(java.lang.String filename, + boolean readMode, + boolean appendMode, + boolean updateMode, + boolean binaryMode) + +
+          Open a file in a particular mode.
+protected abstract  IoLib.FileIoLib.openProgram(java.lang.String prog, + java.lang.String mode) + +
+          Start a new process and return a file for input or output
+protected abstract  IoLib.FileIoLib.tmpFile() + +
+          Open a temporary file.
+protected abstract  IoLib.FileIoLib.wrapStdin() + +
+          Wrap the standard input.
+protected abstract  IoLib.FileIoLib.wrapStdout() + +
+          Wrap the standard output.
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2.lib with parameters of type IoLib.File
+static LuaValueIoLib.freadall(IoLib.File f) + +
+           
+static LuaValueIoLib.freadbytes(IoLib.File f, + int count) + +
+           
+static LuaValueIoLib.freadline(IoLib.File f) + +
+           
+static LuaValueIoLib.freadnumber(IoLib.File f) + +
+           
+static LuaValueIoLib.freaduntil(IoLib.File f, + boolean lineonly) + +
+           
+  +

+ + + + + +
+Uses of IoLib.File in org.luaj.vm2.lib.jme
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2.lib.jme that return IoLib.File
+protected  IoLib.FileJmeIoLib.openFile(java.lang.String filename, + boolean readMode, + boolean appendMode, + boolean updateMode, + boolean binaryMode) + +
+           
+protected  IoLib.FileJmeIoLib.openProgram(java.lang.String prog, + java.lang.String mode) + +
+           
+protected  IoLib.FileJmeIoLib.tmpFile() + +
+           
+protected  IoLib.FileJmeIoLib.wrapStdin() + +
+           
+protected  IoLib.FileJmeIoLib.wrapStdout() + +
+           
+  +

+ + + + + +
+Uses of IoLib.File in org.luaj.vm2.lib.jse
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Methods in org.luaj.vm2.lib.jse that return IoLib.File
+protected  IoLib.FileJseIoLib.openFile(java.lang.String filename, + boolean readMode, + boolean appendMode, + boolean updateMode, + boolean binaryMode) + +
+           
+protected  IoLib.FileJseIoLib.openProgram(java.lang.String prog, + java.lang.String mode) + +
+           
+protected  IoLib.FileJseIoLib.tmpFile() + +
+           
+protected  IoLib.FileJseIoLib.wrapStdin() + +
+           
+protected  IoLib.FileJseIoLib.wrapStdout() + +
+           
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/IoLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/IoLib.html new file mode 100644 index 0000000000..00c1e25237 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/IoLib.html @@ -0,0 +1,211 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.IoLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.IoLib

+
+ + + + + + + + + + + + + +
+Packages that use IoLib
org.luaj.vm2.lib.jme  
org.luaj.vm2.lib.jse  
+  +

+ + + + + +
+Uses of IoLib in org.luaj.vm2.lib.jme
+  +

+ + + + + + + + + +
Subclasses of IoLib in org.luaj.vm2.lib.jme
+ classJmeIoLib + +
+          Subclass of IoLib and therefore LibFunction which implements the lua standard io + library for the JSE platform.
+  +

+ + + + + +
+Uses of IoLib in org.luaj.vm2.lib.jse
+  +

+ + + + + + + + + +
Subclasses of IoLib in org.luaj.vm2.lib.jse
+ classJseIoLib + +
+          Subclass of IoLib and therefore LibFunction which implements the lua standard io + library for the JSE platform.
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/LibFunction.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/LibFunction.html new file mode 100644 index 0000000000..a67cc7cf1c --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/LibFunction.html @@ -0,0 +1,406 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.LibFunction (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.LibFunction

+
+ + + + + + + + + + + + + + + + + +
+Packages that use LibFunction
org.luaj.vm2.lib  
org.luaj.vm2.lib.jme  
org.luaj.vm2.lib.jse  
+  +

+ + + + + +
+Uses of LibFunction in org.luaj.vm2.lib
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Subclasses of LibFunction in org.luaj.vm2.lib
+ classBaseLib + +
+          Subclass of LibFunction which implements the lua basic library functions.
+ classCoroutineLib + +
+          Subclass of LibFunction which implements the lua standard coroutine + library.
+ classDebugLib + +
+          Subclass of LibFunction which implements the lua standard debug + library.
+ classIoLib + +
+          Abstract base class extending LibFunction which implements the + core of the lua standard io library.
+ classMathLib + +
+          Subclass of LibFunction which implements the lua standard math + library.
+ classOneArgFunction + +
+          Abstract base class for Java function implementations that take one argument and + return one value.
+ classOsLib + +
+          Subclass of LibFunction which implements the standard lua os library.
+ classPackageLib + +
+          Subclass of LibFunction which implements the lua standard package and module + library functions.
+ classStringLib + +
+          Subclass of LibFunction which implements the lua standard string + library.
+ classTableLib + +
+          Subclass of LibFunction which implements the lua standard table + library.
+ classThreeArgFunction + +
+          Abstract base class for Java function implementations that take two arguments and + return one value.
+ classTwoArgFunction + +
+          Abstract base class for Java function implementations that take two arguments and + return one value.
+ classVarArgFunction + +
+          Abstract base class for Java function implementations that takes varaiable arguments and + returns multiple return values.
+ classZeroArgFunction + +
+          Abstract base class for Java function implementations that take no arguments and + return one value.
+  +

+ + + + + +
+Uses of LibFunction in org.luaj.vm2.lib.jme
+  +

+ + + + + + + + + +
Subclasses of LibFunction in org.luaj.vm2.lib.jme
+ classJmeIoLib + +
+          Subclass of IoLib and therefore LibFunction which implements the lua standard io + library for the JSE platform.
+  +

+ + + + + +
+Uses of LibFunction in org.luaj.vm2.lib.jse
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Subclasses of LibFunction in org.luaj.vm2.lib.jse
+ classJseBaseLib + +
+          Subclass of BaseLib and LibFunction which implements the lua basic library functions + and provides a directory based ResourceFinder as the BaseLib.FINDER.
+ classJseIoLib + +
+          Subclass of IoLib and therefore LibFunction which implements the lua standard io + library for the JSE platform.
+ classJseMathLib + +
+          Subclass of LibFunction which implements the lua standard math + library.
+static classJseMathLib.JseMathLib1 + +
+           
+static classJseMathLib.JseMathLib2 + +
+           
+ classJseOsLib + +
+          Subclass of LibFunction which implements the standard lua os library.
+ classLuajavaLib + +
+          Subclass of LibFunction which implements the features of the luajava package.
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/MathLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/MathLib.html new file mode 100644 index 0000000000..529ecba9f6 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/MathLib.html @@ -0,0 +1,210 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.MathLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.MathLib

+
+ + + + + + + + + + + + + +
+Packages that use MathLib
org.luaj.vm2.lib  
org.luaj.vm2.lib.jse  
+  +

+ + + + + +
+Uses of MathLib in org.luaj.vm2.lib
+  +

+ + + + + + + + + +
Fields in org.luaj.vm2.lib declared as MathLib
+static MathLibMathLib.MATHLIB + +
+           
+  +

+ + + + + +
+Uses of MathLib in org.luaj.vm2.lib.jse
+  +

+ + + + + + + + + +
Subclasses of MathLib in org.luaj.vm2.lib.jse
+ classJseMathLib + +
+          Subclass of LibFunction which implements the lua standard math + library.
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/OneArgFunction.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/OneArgFunction.html new file mode 100644 index 0000000000..be4a740a36 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/OneArgFunction.html @@ -0,0 +1,311 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.OneArgFunction (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.OneArgFunction

+
+ + + + + + + + + + + + + + + + + +
+Packages that use OneArgFunction
org.luaj.vm2.lib  
org.luaj.vm2.lib.jme  
org.luaj.vm2.lib.jse  
+  +

+ + + + + +
+Uses of OneArgFunction in org.luaj.vm2.lib
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Subclasses of OneArgFunction in org.luaj.vm2.lib
+ classBaseLib + +
+          Subclass of LibFunction which implements the lua basic library functions.
+ classIoLib + +
+          Abstract base class extending LibFunction which implements the + core of the lua standard io library.
+ classMathLib + +
+          Subclass of LibFunction which implements the lua standard math + library.
+ classPackageLib + +
+          Subclass of LibFunction which implements the lua standard package and module + library functions.
+ classStringLib + +
+          Subclass of LibFunction which implements the lua standard string + library.
+ classTableLib + +
+          Subclass of LibFunction which implements the lua standard table + library.
+  +

+ + + + + +
+Uses of OneArgFunction in org.luaj.vm2.lib.jme
+  +

+ + + + + + + + + +
Subclasses of OneArgFunction in org.luaj.vm2.lib.jme
+ classJmeIoLib + +
+          Subclass of IoLib and therefore LibFunction which implements the lua standard io + library for the JSE platform.
+  +

+ + + + + +
+Uses of OneArgFunction in org.luaj.vm2.lib.jse
+  +

+ + + + + + + + + + + + + + + + + + + + + +
Subclasses of OneArgFunction in org.luaj.vm2.lib.jse
+ classJseBaseLib + +
+          Subclass of BaseLib and LibFunction which implements the lua basic library functions + and provides a directory based ResourceFinder as the BaseLib.FINDER.
+ classJseIoLib + +
+          Subclass of IoLib and therefore LibFunction which implements the lua standard io + library for the JSE platform.
+ classJseMathLib + +
+          Subclass of LibFunction which implements the lua standard math + library.
+static classJseMathLib.JseMathLib1 + +
+           
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/OsLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/OsLib.html new file mode 100644 index 0000000000..65573d5ae6 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/OsLib.html @@ -0,0 +1,180 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.OsLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.OsLib

+
+ + + + + + + + + +
+Packages that use OsLib
org.luaj.vm2.lib.jse  
+  +

+ + + + + +
+Uses of OsLib in org.luaj.vm2.lib.jse
+  +

+ + + + + + + + + +
Subclasses of OsLib in org.luaj.vm2.lib.jse
+ classJseOsLib + +
+          Subclass of LibFunction which implements the standard lua os library.
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/PackageLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/PackageLib.html new file mode 100644 index 0000000000..bb6be5cae3 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/PackageLib.html @@ -0,0 +1,180 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.PackageLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.PackageLib

+
+ + + + + + + + + +
+Packages that use PackageLib
org.luaj.vm2.lib  
+  +

+ + + + + +
+Uses of PackageLib in org.luaj.vm2.lib
+  +

+ + + + + + + + + +
Fields in org.luaj.vm2.lib declared as PackageLib
+static PackageLibPackageLib.instance + +
+          Most recent instance of PackageLib
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/ResourceFinder.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/ResourceFinder.html new file mode 100644 index 0000000000..1cdf69f924 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/ResourceFinder.html @@ -0,0 +1,226 @@ + + + + + + +Uses of Interface org.luaj.vm2.lib.ResourceFinder (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Interface
org.luaj.vm2.lib.ResourceFinder

+
+ + + + + + + + + + + + + +
+Packages that use ResourceFinder
org.luaj.vm2.lib  
org.luaj.vm2.lib.jse  
+  +

+ + + + + +
+Uses of ResourceFinder in org.luaj.vm2.lib
+  +

+ + + + + + + + + +
Classes in org.luaj.vm2.lib that implement ResourceFinder
+ classBaseLib + +
+          Subclass of LibFunction which implements the lua basic library functions.
+  +

+ + + + + + + + + +
Fields in org.luaj.vm2.lib declared as ResourceFinder
+static ResourceFinderBaseLib.FINDER + +
+          Singleton file opener for this Java ClassLoader realm.
+  +

+ + + + + +
+Uses of ResourceFinder in org.luaj.vm2.lib.jse
+  +

+ + + + + + + + + +
Classes in org.luaj.vm2.lib.jse that implement ResourceFinder
+ classJseBaseLib + +
+          Subclass of BaseLib and LibFunction which implements the lua basic library functions + and provides a directory based ResourceFinder as the BaseLib.FINDER.
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/StringLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/StringLib.html new file mode 100644 index 0000000000..dc4b13388f --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/StringLib.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.StringLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.StringLib

+
+No usage of org.luaj.vm2.lib.StringLib +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/TableLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/TableLib.html new file mode 100644 index 0000000000..b31307ee46 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/TableLib.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.TableLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.TableLib

+
+No usage of org.luaj.vm2.lib.TableLib +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/ThreeArgFunction.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/ThreeArgFunction.html new file mode 100644 index 0000000000..2b8b7ee5f5 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/ThreeArgFunction.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.ThreeArgFunction (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.ThreeArgFunction

+
+No usage of org.luaj.vm2.lib.ThreeArgFunction +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/TwoArgFunction.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/TwoArgFunction.html new file mode 100644 index 0000000000..ef9fb4ba37 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/TwoArgFunction.html @@ -0,0 +1,180 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.TwoArgFunction (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.TwoArgFunction

+
+ + + + + + + + + +
+Packages that use TwoArgFunction
org.luaj.vm2.lib.jse  
+  +

+ + + + + +
+Uses of TwoArgFunction in org.luaj.vm2.lib.jse
+  +

+ + + + + + + + + +
Subclasses of TwoArgFunction in org.luaj.vm2.lib.jse
+static classJseMathLib.JseMathLib2 + +
+           
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/VarArgFunction.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/VarArgFunction.html new file mode 100644 index 0000000000..370ac3b332 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/VarArgFunction.html @@ -0,0 +1,235 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.VarArgFunction (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.VarArgFunction

+
+ + + + + + + + + + + + + +
+Packages that use VarArgFunction
org.luaj.vm2.lib  
org.luaj.vm2.lib.jse  
+  +

+ + + + + +
+Uses of VarArgFunction in org.luaj.vm2.lib
+  +

+ + + + + + + + + + + + + + + + + +
Subclasses of VarArgFunction in org.luaj.vm2.lib
+ classCoroutineLib + +
+          Subclass of LibFunction which implements the lua standard coroutine + library.
+ classDebugLib + +
+          Subclass of LibFunction which implements the lua standard debug + library.
+ classOsLib + +
+          Subclass of LibFunction which implements the standard lua os library.
+  +

+ + + + + +
+Uses of VarArgFunction in org.luaj.vm2.lib.jse
+  +

+ + + + + + + + + + + + + +
Subclasses of VarArgFunction in org.luaj.vm2.lib.jse
+ classJseOsLib + +
+          Subclass of LibFunction which implements the standard lua os library.
+ classLuajavaLib + +
+          Subclass of LibFunction which implements the features of the luajava package.
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/ZeroArgFunction.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/ZeroArgFunction.html new file mode 100644 index 0000000000..3acbff89ab --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/class-use/ZeroArgFunction.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.ZeroArgFunction (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.ZeroArgFunction

+
+No usage of org.luaj.vm2.lib.ZeroArgFunction +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/JmeIoLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/JmeIoLib.html new file mode 100644 index 0000000000..4cb9936d98 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/JmeIoLib.html @@ -0,0 +1,544 @@ + + + + + + +JmeIoLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib.jme +
+Class JmeIoLib

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.OneArgFunction
+                      extended by org.luaj.vm2.lib.IoLib
+                          extended by org.luaj.vm2.lib.jme.JmeIoLib
+
+
+
+
public class JmeIoLib
extends IoLib
+ + +

+Subclass of IoLib and therefore LibFunction which implements the lua standard io + library for the JSE platform. +

+ The implementation of the is based on CLDC 1.0 and StreamConnection. + However, seek is not supported. +

+ Typically, this library is included as part of a call to + JmePlatform.standardGlobals() +

+ To instantiate and use it directly, + link it into your globals table via LuaValue.load(LuaValue) using code such as: +

 LuaTable _G = new LuaTable();
+ LuaThread.setGlobals(_G);
+ _G.load(new BaseLib());
+ _G.load(new PackageLib());
+ _G.load(new JmeIoLib());
+ _G.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
+  
+ Doing so will ensure the library is properly initialized + and loaded into the globals table. +

+ This has been implemented to match as closely as possible the behavior in the corresponding library in C. +

+ +

+

+
See Also:
LibFunction, +JsePlatform, +JmePlatform, +IoLib, +JseIoLib, +http://www.lua.org/manual/5.1/manual.html#5.6
+
+ +

+ + + + + + + +
+Nested Class Summary
+ + + + + + + +
Nested classes/interfaces inherited from class org.luaj.vm2.lib.IoLib
IoLib.File
+  + + + + + + + +
+Field Summary
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.IoLib
FILE_NAMES, IO_NAMES
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + +
+Constructor Summary
JmeIoLib() + +
+           
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+protected  IoLib.FileopenFile(java.lang.String filename, + boolean readMode, + boolean appendMode, + boolean updateMode, + boolean binaryMode) + +
+          Open a file in a particular mode.
+protected  IoLib.FileopenProgram(java.lang.String prog, + java.lang.String mode) + +
+          Start a new process and return a file for input or output
+protected  IoLib.FiletmpFile() + +
+          Open a temporary file.
+protected  IoLib.FilewrapStdin() + +
+          Wrap the standard input.
+protected  IoLib.FilewrapStdout() + +
+          Wrap the standard output.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.IoLib
_file_close, _file_flush, _file_lines, _file_read, _file_seek, _file_setvbuf, _file_write, _io_close, _io_flush, _io_index, _io_input, _io_lines, _io_open, _io_output, _io_popen, _io_read, _io_tmpfile, _io_type, _io_write, _lines_iter, call, freadall, freadbytes, freadline, freadnumber, freaduntil
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.OneArgFunction
call, call, call, invoke
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+JmeIoLib

+
+public JmeIoLib()
+
+
+ + + + + + + + +
+Method Detail
+ +

+wrapStdin

+
+protected IoLib.File wrapStdin()
+                        throws java.io.IOException
+
+
Description copied from class: IoLib
+
Wrap the standard input. +

+

+
Specified by:
wrapStdin in class IoLib
+
+
+ +
Returns:
File +
Throws: +
java.io.IOException
+
+
+
+ +

+wrapStdout

+
+protected IoLib.File wrapStdout()
+                         throws java.io.IOException
+
+
Description copied from class: IoLib
+
Wrap the standard output. +

+

+
Specified by:
wrapStdout in class IoLib
+
+
+ +
Returns:
File +
Throws: +
java.io.IOException
+
+
+
+ +

+openFile

+
+protected IoLib.File openFile(java.lang.String filename,
+                              boolean readMode,
+                              boolean appendMode,
+                              boolean updateMode,
+                              boolean binaryMode)
+                       throws java.io.IOException
+
+
Description copied from class: IoLib
+
Open a file in a particular mode. +

+

+
Specified by:
openFile in class IoLib
+
+
+
readMode - true if opening in read mode
appendMode - true if opening in append mode
updateMode - true if opening in update mode
binaryMode - true if opening in binary mode +
Returns:
File object if successful +
Throws: +
java.io.IOException - if could not be opened
+
+
+
+ +

+openProgram

+
+protected IoLib.File openProgram(java.lang.String prog,
+                                 java.lang.String mode)
+                          throws java.io.IOException
+
+
Description copied from class: IoLib
+
Start a new process and return a file for input or output +

+

+
Specified by:
openProgram in class IoLib
+
+
+
Parameters:
prog - the program to execute
mode - "r" to read, "w" to write +
Returns:
File to read to or write from +
Throws: +
java.io.IOException - if an i/o exception occurs
+
+
+
+ +

+tmpFile

+
+protected IoLib.File tmpFile()
+                      throws java.io.IOException
+
+
Description copied from class: IoLib
+
Open a temporary file. +

+

+
Specified by:
tmpFile in class IoLib
+
+
+ +
Returns:
File object if successful +
Throws: +
java.io.IOException - if could not be opened
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/JmePlatform.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/JmePlatform.html new file mode 100644 index 0000000000..41e03de030 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/JmePlatform.html @@ -0,0 +1,336 @@ + + + + + + +JmePlatform (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib.jme +
+Class JmePlatform

+
+java.lang.Object
+  extended by org.luaj.vm2.lib.jme.JmePlatform
+
+
+
+
public class JmePlatform
extends java.lang.Object
+ + +

+The JmePlatform class is a convenience class to standardize + how globals tables are initialized for the JME platform. +

+ The JME platform, being limited, cannot implement all libraries in all aspects. The main limitations are +

    +
  • Some math functions are not implemented, see MathLib for details
  • +
  • Scripts are loaded via Class.getResourceAsStream(), see BaseLib for details
  • +
  • OS functions execute(), remove(), rename(), and tmpname() vary, see OsLib for details
  • +
  • I/O seek is not implemented, see JmeIoLib for details
  • +
  • luajava is not available, see LuajavaLib for details
  • +
+

+ It is used to allocate either a set of standard globals using + standardGlobals() or debug globals using debugGlobals() +

+ A simple example of initializing globals and using them from Java is: +

 LuaValue _G = JmePlatform.standardGlobals();
+ _G.get("print").call(LuaValue.valueOf("hello, world"));
+  
+

+ Once globals are created, a simple way to load and run a script is: +

 LoadState.load( getClass().getResourceAsStream("main.lua"), "main.lua", _G ).call();
+  
+

+ although require could also be used: +

 _G.get("require").call(LuaValue.valueOf("main"));
+  
+ For this to succeed, the file "main.lua" must be a resource in the class path. + See BaseLib for details on finding scripts using ResourceFinder. +

+ The standard globals will contain all standard libraries in their JME flavors: +

+ In addition, the LuaC compiler is installed so lua files may be loaded in their source form. +

+ The debug globals are simply the standard globals plus the debug library DebugLib. +

+

+ The class ensures that initialization is done in the correct order, + and that linkage is made to LuaThread.setGlobals(LuaValue). +

+ +

+

+
See Also:
JsePlatform, +LoadState
+
+ +

+ + + + + + + + + + + +
+Constructor Summary
JmePlatform() + +
+           
+  + + + + + + + + + + + + + + + +
+Method Summary
+static LuaTabledebugGlobals() + +
+          Create standard globals including the debug library.
+static LuaTablestandardGlobals() + +
+          Create a standard set of globals for JME including all the libraries.
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+JmePlatform

+
+public JmePlatform()
+
+
+ + + + + + + + +
+Method Detail
+ +

+standardGlobals

+
+public static LuaTable standardGlobals()
+
+
Create a standard set of globals for JME including all the libraries. +

+

+ +
Returns:
Table of globals initialized with the standard JME libraries
See Also:
debugGlobals(), +JsePlatform, +JmePlatform
+
+
+
+ +

+debugGlobals

+
+public static LuaTable debugGlobals()
+
+
Create standard globals including the debug library. +

+

+ +
Returns:
Table of globals initialized with the standard JSE and debug libraries
See Also:
#standarsGlobals(), +JsePlatform, +JmePlatform, +DebugLib
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/class-use/JmeIoLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/class-use/JmeIoLib.html new file mode 100644 index 0000000000..71cb0ad319 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/class-use/JmeIoLib.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.jme.JmeIoLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.jme.JmeIoLib

+
+No usage of org.luaj.vm2.lib.jme.JmeIoLib +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/class-use/JmePlatform.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/class-use/JmePlatform.html new file mode 100644 index 0000000000..b1c12c7cc8 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/class-use/JmePlatform.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.jme.JmePlatform (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.jme.JmePlatform

+
+No usage of org.luaj.vm2.lib.jme.JmePlatform +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/package-frame.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/package-frame.html new file mode 100644 index 0000000000..d481b52a97 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/package-frame.html @@ -0,0 +1,34 @@ + + + + + + +org.luaj.vm2.lib.jme (Luaj API) + + + + + + + + + + + +org.luaj.vm2.lib.jme + + + + +
+Classes  + +
+JmeIoLib +
+JmePlatform
+ + + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/package-summary.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/package-summary.html new file mode 100644 index 0000000000..e0e17cd7ab --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/package-summary.html @@ -0,0 +1,163 @@ + + + + + + +org.luaj.vm2.lib.jme (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+

+Package org.luaj.vm2.lib.jme +

+ + + + + + + + + + + + + +
+Class Summary
JmeIoLibSubclass of IoLib and therefore LibFunction which implements the lua standard io + library for the JSE platform.
JmePlatformThe JmePlatform class is a convenience class to standardize + how globals tables are initialized for the JME platform.
+  + +

+

+
+
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/package-tree.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/package-tree.html new file mode 100644 index 0000000000..23cb703d68 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/package-tree.html @@ -0,0 +1,165 @@ + + + + + + +org.luaj.vm2.lib.jme Class Hierarchy (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Hierarchy For Package org.luaj.vm2.lib.jme +

+
+
+
Package Hierarchies:
All Packages
+
+

+Class Hierarchy +

+ +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/package-use.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/package-use.html new file mode 100644 index 0000000000..2ad589af8f --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jme/package-use.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Package org.luaj.vm2.lib.jme (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Package
org.luaj.vm2.lib.jme

+
+No usage of org.luaj.vm2.lib.jme +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/CoerceJavaToLua.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/CoerceJavaToLua.html new file mode 100644 index 0000000000..4002e8794d --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/CoerceJavaToLua.html @@ -0,0 +1,297 @@ + + + + + + +CoerceJavaToLua (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib.jse +
+Class CoerceJavaToLua

+
+java.lang.Object
+  extended by org.luaj.vm2.lib.jse.CoerceJavaToLua
+
+
+
+
public class CoerceJavaToLua
extends java.lang.Object
+ + +

+Helper class to coerce values from Java to lua within the luajava library. +

+ This class is primarily used by the LuajavaLib, + but can also be used directly when working with Java/lua bindings. +

+ To coerce scalar types, the various, generally the valueOf(type) methods + on LuaValue may be used: +

+

+ To coerce arrays of objects and lists, the listOf(..) and tableOf(...) methods + on LuaValue may be used: +

+ The method coerce(Object) looks as the type and dimesioning + of the argument and tries to guess the best fit for corrsponding lua scalar, + table, or table of tables. +

+ +

+

+
See Also:
coerce(Object), +LuajavaLib
+
+ +

+ + + + + + + + + + + +
+Constructor Summary
CoerceJavaToLua() + +
+           
+  + + + + + + + + + + + +
+Method Summary
+static LuaValuecoerce(java.lang.Object o) + +
+          Coerse a Java object to a corresponding lua value.
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+CoerceJavaToLua

+
+public CoerceJavaToLua()
+
+
+ + + + + + + + +
+Method Detail
+ +

+coerce

+
+public static LuaValue coerce(java.lang.Object o)
+
+
Coerse a Java object to a corresponding lua value. +

+ Integral types boolean, byte, char, and int + will become LuaInteger; + long, float, and double will become LuaDouble; + String and byte[] will become LuaString; + other types will become LuaUserdata. +

+

+
Parameters:
o - Java object needing conversion +
Returns:
LuaValue corresponding to the supplied Java value.
See Also:
LuaValue, +LuaInteger, +LuaDouble, +LuaString, +LuaUserdata
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/CoerceLuaToJava.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/CoerceLuaToJava.html new file mode 100644 index 0000000000..6f4d952b39 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/CoerceLuaToJava.html @@ -0,0 +1,285 @@ + + + + + + +CoerceLuaToJava (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib.jse +
+Class CoerceLuaToJava

+
+java.lang.Object
+  extended by org.luaj.vm2.lib.jse.CoerceLuaToJava
+
+
+
+
public class CoerceLuaToJava
extends java.lang.Object
+ + +

+Helper class to coerce values from lua to Java within the luajava library. +

+ This class is primarily used by the LuajavaLib, + but can also be used directly when working with Java/lua bindings. +

+ To coerce to specific Java values, generally the toType() methods + on LuaValue may be used: +

+

+ For data in lua tables, the various methods on LuaTable can be used directly + to convert data to something more useful. +

+ +

+

+
See Also:
LuajavaLib, +CoerceJavaToLua
+
+ +

+ + + + + + + + + + + +
+Constructor Summary
CoerceLuaToJava() + +
+           
+  + + + + + + + + + + + +
+Method Summary
+static java.lang.Objectcoerce(LuaValue value, + java.lang.Class clazz) + +
+          Coerce a LuaValue value to a specified java class
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+CoerceLuaToJava

+
+public CoerceLuaToJava()
+
+
+ + + + + + + + +
+Method Detail
+ +

+coerce

+
+public static java.lang.Object coerce(LuaValue value,
+                                      java.lang.Class clazz)
+
+
Coerce a LuaValue value to a specified java class +

+

+
Parameters:
value - LuaValue to coerce
clazz - Class to coerce into +
Returns:
Object of type clazz (or a subclass) with the corresponding value.
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseBaseLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseBaseLib.html new file mode 100644 index 0000000000..901161126e --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseBaseLib.html @@ -0,0 +1,409 @@ + + + + + + +JseBaseLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib.jse +
+Class JseBaseLib

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.OneArgFunction
+                      extended by org.luaj.vm2.lib.BaseLib
+                          extended by org.luaj.vm2.lib.jse.JseBaseLib
+
+
+
All Implemented Interfaces:
ResourceFinder
+
+
+
+
public class JseBaseLib
extends BaseLib
+ + +

+Subclass of BaseLib and LibFunction which implements the lua basic library functions + and provides a directory based ResourceFinder as the BaseLib.FINDER. +

+ Since JME has no file system by default, BaseLib implements + ResourceFinder using Class.getResource(String). + The JseBaseLib implements FINDER by scanning the current directory + first, then falling back to Class.getResource(String) if that fails. + Otherwise, the behavior is the same as that of BaseLib. +

+ Typically, this library is included as part of a call to + JsePlatform.standardGlobals() +

+ To instantiate and use it directly, + link it into your globals table via LuaValue.load(LuaValue) using code such as: +

 LuaTable _G = new LuaTable();
+ LuaThread.setGlobals(_G);
+ _G.load(new JseBaseLib());
+ _G.get("print").call(LuaValue.valueOf("hello, world"));
+  
+ Doing so will ensure the library is properly initialized + and loaded into the globals table. +

+ This is a direct port of the corresponding library in C. +

+ +

+

+
See Also:
BaseLib, +ResourceFinder, +BaseLib.FINDER, +LibFunction, +JsePlatform, +JmePlatform, +http://www.lua.org/manual/5.1/manual.html#5.1
+
+ +

+ + + + + + + +
+Field Summary
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.BaseLib
FINDER, instance, STDERR, STDIN, STDOUT
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + +
+Constructor Summary
JseBaseLib() + +
+          Construct a JSE base library instance
+  + + + + + + + + + + + +
+Method Summary
+ java.io.InputStreamfindResource(java.lang.String filename) + +
+          Try to open a file in the current working directory, + or fall back to base opener if not found.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.BaseLib
call, loadFile, loadStream, pcall
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.OneArgFunction
call, call, call, invoke
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+JseBaseLib

+
+public JseBaseLib()
+
+
Construct a JSE base library instance +

+

+ + + + + + + + +
+Method Detail
+ +

+findResource

+
+public java.io.InputStream findResource(java.lang.String filename)
+
+
Try to open a file in the current working directory, + or fall back to base opener if not found. + + This implementation attempts to open the file using new File(filename). + It falls back to the base implementation that looks it up as a resource + in the class path if not found as a plain file. +

+

+
Specified by:
findResource in interface ResourceFinder
Overrides:
findResource in class BaseLib
+
+
+
Parameters:
filename - +
Returns:
InputStream, or null if not found.
See Also:
BaseLib, +ResourceFinder
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseIoLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseIoLib.html new file mode 100644 index 0000000000..2dbd43950c --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseIoLib.html @@ -0,0 +1,543 @@ + + + + + + +JseIoLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib.jse +
+Class JseIoLib

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.OneArgFunction
+                      extended by org.luaj.vm2.lib.IoLib
+                          extended by org.luaj.vm2.lib.jse.JseIoLib
+
+
+
+
public class JseIoLib
extends IoLib
+ + +

+Subclass of IoLib and therefore LibFunction which implements the lua standard io + library for the JSE platform. +

+ It uses RandomAccessFile to implement seek on files. +

+ Typically, this library is included as part of a call to + JsePlatform.standardGlobals() +

+ To instantiate and use it directly, + link it into your globals table via LuaValue.load(LuaValue) using code such as: +

 LuaTable _G = new LuaTable();
+ LuaThread.setGlobals(_G);
+ _G.load(new JseBaseLib());
+ _G.load(new PackageLib());
+ _G.load(new JseIoLib());
+ _G.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
+  
+ Doing so will ensure the library is properly initialized + and loaded into the globals table. +

+ This has been implemented to match as closely as possible the behavior in the corresponding library in C. +

+ +

+

+
See Also:
LibFunction, +JsePlatform, +JmePlatform, +IoLib, +JmeIoLib, +http://www.lua.org/manual/5.1/manual.html#5.7
+
+ +

+ + + + + + + +
+Nested Class Summary
+ + + + + + + +
Nested classes/interfaces inherited from class org.luaj.vm2.lib.IoLib
IoLib.File
+  + + + + + + + +
+Field Summary
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.IoLib
FILE_NAMES, IO_NAMES
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + +
+Constructor Summary
JseIoLib() + +
+           
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+protected  IoLib.FileopenFile(java.lang.String filename, + boolean readMode, + boolean appendMode, + boolean updateMode, + boolean binaryMode) + +
+          Open a file in a particular mode.
+protected  IoLib.FileopenProgram(java.lang.String prog, + java.lang.String mode) + +
+          Start a new process and return a file for input or output
+protected  IoLib.FiletmpFile() + +
+          Open a temporary file.
+protected  IoLib.FilewrapStdin() + +
+          Wrap the standard input.
+protected  IoLib.FilewrapStdout() + +
+          Wrap the standard output.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.IoLib
_file_close, _file_flush, _file_lines, _file_read, _file_seek, _file_setvbuf, _file_write, _io_close, _io_flush, _io_index, _io_input, _io_lines, _io_open, _io_output, _io_popen, _io_read, _io_tmpfile, _io_type, _io_write, _lines_iter, call, freadall, freadbytes, freadline, freadnumber, freaduntil
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.OneArgFunction
call, call, call, invoke
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+JseIoLib

+
+public JseIoLib()
+
+
+ + + + + + + + +
+Method Detail
+ +

+wrapStdin

+
+protected IoLib.File wrapStdin()
+                        throws java.io.IOException
+
+
Description copied from class: IoLib
+
Wrap the standard input. +

+

+
Specified by:
wrapStdin in class IoLib
+
+
+ +
Returns:
File +
Throws: +
java.io.IOException
+
+
+
+ +

+wrapStdout

+
+protected IoLib.File wrapStdout()
+                         throws java.io.IOException
+
+
Description copied from class: IoLib
+
Wrap the standard output. +

+

+
Specified by:
wrapStdout in class IoLib
+
+
+ +
Returns:
File +
Throws: +
java.io.IOException
+
+
+
+ +

+openFile

+
+protected IoLib.File openFile(java.lang.String filename,
+                              boolean readMode,
+                              boolean appendMode,
+                              boolean updateMode,
+                              boolean binaryMode)
+                       throws java.io.IOException
+
+
Description copied from class: IoLib
+
Open a file in a particular mode. +

+

+
Specified by:
openFile in class IoLib
+
+
+
readMode - true if opening in read mode
appendMode - true if opening in append mode
updateMode - true if opening in update mode
binaryMode - true if opening in binary mode +
Returns:
File object if successful +
Throws: +
java.io.IOException - if could not be opened
+
+
+
+ +

+openProgram

+
+protected IoLib.File openProgram(java.lang.String prog,
+                                 java.lang.String mode)
+                          throws java.io.IOException
+
+
Description copied from class: IoLib
+
Start a new process and return a file for input or output +

+

+
Specified by:
openProgram in class IoLib
+
+
+
Parameters:
prog - the program to execute
mode - "r" to read, "w" to write +
Returns:
File to read to or write from +
Throws: +
java.io.IOException - if an i/o exception occurs
+
+
+
+ +

+tmpFile

+
+protected IoLib.File tmpFile()
+                      throws java.io.IOException
+
+
Description copied from class: IoLib
+
Open a temporary file. +

+

+
Specified by:
tmpFile in class IoLib
+
+
+ +
Returns:
File object if successful +
Throws: +
java.io.IOException - if could not be opened
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseMathLib.JseMathLib1.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseMathLib.JseMathLib1.html new file mode 100644 index 0000000000..1d7aaec0fb --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseMathLib.JseMathLib1.html @@ -0,0 +1,364 @@ + + + + + + +JseMathLib.JseMathLib1 (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib.jse +
+Class JseMathLib.JseMathLib1

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.OneArgFunction
+                      extended by org.luaj.vm2.lib.jse.JseMathLib.JseMathLib1
+
+
+
Enclosing class:
JseMathLib
+
+
+
+
public static final class JseMathLib.JseMathLib1
extends OneArgFunction
+ + +

+


+ +

+ + + + + + + +
+Field Summary
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + +
+Constructor Summary
JseMathLib.JseMathLib1() + +
+           
+  + + + + + + + + + + + +
+Method Summary
+ LuaValuecall(LuaValue arg) + +
+          Call this with 1 argument, including metatag processing, + and return only the first return value.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.OneArgFunction
call, call, call, invoke
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+JseMathLib.JseMathLib1

+
+public JseMathLib.JseMathLib1()
+
+
+ + + + + + + + +
+Method Detail
+ +

+call

+
+public LuaValue call(LuaValue arg)
+
+
Description copied from class: LuaValue
+
Call this with 1 argument, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Specified by:
call in class OneArgFunction
+
+
+
Parameters:
arg - First argument to supply to the called function +
Returns:
First return value (this(arg)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue,LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue), +LuaValue.method(String,LuaValue), +LuaValue.method(LuaValue,LuaValue)
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseMathLib.JseMathLib2.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseMathLib.JseMathLib2.html new file mode 100644 index 0000000000..34a29d1bc3 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseMathLib.JseMathLib2.html @@ -0,0 +1,366 @@ + + + + + + +JseMathLib.JseMathLib2 (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib.jse +
+Class JseMathLib.JseMathLib2

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.TwoArgFunction
+                      extended by org.luaj.vm2.lib.jse.JseMathLib.JseMathLib2
+
+
+
Enclosing class:
JseMathLib
+
+
+
+
public static final class JseMathLib.JseMathLib2
extends TwoArgFunction
+ + +

+


+ +

+ + + + + + + +
+Field Summary
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + +
+Constructor Summary
JseMathLib.JseMathLib2() + +
+           
+  + + + + + + + + + + + +
+Method Summary
+ LuaValuecall(LuaValue arg1, + LuaValue arg2) + +
+          Call this with 2 arguments, including metatag processing, + and return only the first return value.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.TwoArgFunction
call, call, call, invoke
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+JseMathLib.JseMathLib2

+
+public JseMathLib.JseMathLib2()
+
+
+ + + + + + + + +
+Method Detail
+ +

+call

+
+public LuaValue call(LuaValue arg1,
+                     LuaValue arg2)
+
+
Description copied from class: LuaValue
+
Call this with 2 arguments, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Specified by:
call in class TwoArgFunction
+
+
+
Parameters:
arg1 - First argument to supply to the called function
arg2 - Second argument to supply to the called function +
Returns:
First return value (this(arg1,arg2)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue,LuaValue), +LuaValue.method(String,LuaValue,LuaValue), +LuaValue.method(LuaValue,LuaValue,LuaValue)
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseMathLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseMathLib.html new file mode 100644 index 0000000000..c682c7eebe --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseMathLib.html @@ -0,0 +1,462 @@ + + + + + + +JseMathLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib.jse +
+Class JseMathLib

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.OneArgFunction
+                      extended by org.luaj.vm2.lib.MathLib
+                          extended by org.luaj.vm2.lib.jse.JseMathLib
+
+
+
+
public class JseMathLib
extends MathLib
+ + +

+Subclass of LibFunction which implements the lua standard math + library. +

+ It contains all lua math functions, including those not available on the JME platform. + See org.luaj.lib.MathLib for the exception list. +

+ Typically, this library is included as part of a call to + JsePlatform.standardGlobals() +

+ To instantiate and use it directly, + link it into your globals table via LuaValue.load(LuaValue) using code such as: +

 LuaTable _G = new LuaTable();
+ LuaThread.setGlobals(_G);
+ _G.load(new JseBaseLib());
+ _G.load(new PackageLib());
+ _G.load(new JseMathLib());
+ System.out.println( _G.get("math").get("sqrt").call( LuaValue.valueOf(2) ) );
+  
+ Doing so will ensure the library is properly initialized + and loaded into the globals table. +

+ This has been implemented to match as closely as possible the behavior in the corresponding library in C. +

+ +

+

+
See Also:
LibFunction, +JsePlatform, +JmePlatform, +JseMathLib, +http://www.lua.org/manual/5.1/manual.html#5.6
+
+ +

+ + + + + + + + + + + + + + + +
+Nested Class Summary
+static classJseMathLib.JseMathLib1 + +
+           
+static classJseMathLib.JseMathLib2 + +
+           
+ + + + + + +
+Field Summary
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.MathLib
MATHLIB
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + +
+Constructor Summary
JseMathLib() + +
+           
+  + + + + + + + + + + + + + + + +
+Method Summary
+ LuaValuecall(LuaValue arg) + +
+          Call this with 1 argument, including metatag processing, + and return only the first return value.
+ doubledpow_lib(double a, + double b) + +
+          Faster, better version of pow() used by arithmetic operator ^
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.MathLib
dpow_d, dpow_default, dpow
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.OneArgFunction
call, call, call, invoke
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, onInvoke, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+JseMathLib

+
+public JseMathLib()
+
+
+ + + + + + + + +
+Method Detail
+ +

+call

+
+public LuaValue call(LuaValue arg)
+
+
Description copied from class: LuaValue
+
Call this with 1 argument, including metatag processing, + and return only the first return value. +

+ If this is a LuaFunction, call it, + and return only its first return value, dropping any others. + Otherwise, look for the CALL metatag and call that. +

+ If the return value is a Varargs, only the 1st value will be returned. + To get multiple values, use LuaValue.invoke() instead. +

+ To call this as a method call, use LuaValue.method(LuaValue) instead. +

+

+
Overrides:
call in class MathLib
+
+
+
Parameters:
arg - First argument to supply to the called function +
Returns:
First return value (this(arg)), or NIL if there were none.
See Also:
LuaValue.call(), +LuaValue.call(LuaValue,LuaValue), +LuaValue.call(LuaValue, LuaValue, LuaValue), +#invoke(LuaValue), +LuaValue.method(String,LuaValue), +LuaValue.method(LuaValue,LuaValue)
+
+
+
+ +

+dpow_lib

+
+public double dpow_lib(double a,
+                       double b)
+
+
Faster, better version of pow() used by arithmetic operator ^ +

+

+
Overrides:
dpow_lib in class MathLib
+
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseOsLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseOsLib.html new file mode 100644 index 0000000000..01353df700 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseOsLib.html @@ -0,0 +1,572 @@ + + + + + + +JseOsLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib.jse +
+Class JseOsLib

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.VarArgFunction
+                      extended by org.luaj.vm2.lib.OsLib
+                          extended by org.luaj.vm2.lib.jse.JseOsLib
+
+
+
+
public class JseOsLib
extends OsLib
+ + +

+Subclass of LibFunction which implements the standard lua os library. +

+ This contains more complete implementations of the following functions + using features that are specific to JSE: +

    +
  • execute()
  • +
  • remove()
  • +
  • rename()
  • +
  • tmpname()
  • +
+

+ Because the nature of the os library is to encapsulate + os-specific features, the behavior of these functions varies considerably + from their counterparts in the C platform. +

+ Typically, this library is included as part of a call to either + JsePlatform.standardGlobals() +

+ To instantiate and use it directly, + link it into your globals table via LuaValue.load(LuaValue) using code such as: +

 LuaTable _G = new LuaTable();
+ LuaThread.setGlobals(_G);
+ _G.load(new JseBaseLib());
+ _G.load(new PackageLib());
+ _G.load(new JseOsLib());
+ System.out.println( _G.get("os").get("time").call() );
+  
+ Doing so will ensure the library is properly initialized + and loaded into the globals table. +

+

+ +

+

+
See Also:
LibFunction, +OsLib, +JsePlatform, +JmePlatform, +http://www.lua.org/manual/5.1/manual.html#5.8
+
+ +

+ + + + + + + + + + + + + + + + + + + +
+Field Summary
+static intEXEC_ERROR + +
+          return code indicating the execute() threw an unknown exception
+static intEXEC_INTERRUPTED + +
+          return code indicating the execute() was interrupted
+static intEXEC_IOEXCEPTION + +
+          return code indicating the execute() threw an I/O exception
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.OsLib
TMP_PREFIX, TMP_SUFFIX
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + +
+Constructor Summary
JseOsLib() + +
+          public constructor
+  + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+protected  intexecute(java.lang.String command) + +
+          This function is equivalent to the C function system.
+protected  voidremove(java.lang.String filename) + +
+          Deletes the file or directory with the given name.
+protected  voidrename(java.lang.String oldname, + java.lang.String newname) + +
+          Renames file or directory named oldname to newname.
+protected  java.lang.Stringtmpname() + +
+          Returns a string with a file name that can be used for a temporary file.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.OsLib
clock, date, difftime, exit, getenv, init, invoke, setlocale, time
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.VarArgFunction
call, call, call, call, onInvoke
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Field Detail
+ +

+EXEC_IOEXCEPTION

+
+public static int EXEC_IOEXCEPTION
+
+
return code indicating the execute() threw an I/O exception +

+

+
+
+
+ +

+EXEC_INTERRUPTED

+
+public static int EXEC_INTERRUPTED
+
+
return code indicating the execute() was interrupted +

+

+
+
+
+ +

+EXEC_ERROR

+
+public static int EXEC_ERROR
+
+
return code indicating the execute() threw an unknown exception +

+

+
+
+ + + + + + + + +
+Constructor Detail
+ +

+JseOsLib

+
+public JseOsLib()
+
+
public constructor +

+

+ + + + + + + + +
+Method Detail
+ +

+execute

+
+protected int execute(java.lang.String command)
+
+
Description copied from class: OsLib
+
This function is equivalent to the C function system. + It passes command to be executed by an operating system shell. + It returns a status code, which is system-dependent. + If command is absent, then it returns nonzero if a shell + is available and zero otherwise. +

+

+
Overrides:
execute in class OsLib
+
+
+
Parameters:
command - command to pass to the system
+
+
+
+ +

+remove

+
+protected void remove(java.lang.String filename)
+               throws java.io.IOException
+
+
Description copied from class: OsLib
+
Deletes the file or directory with the given name. + Directories must be empty to be removed. + If this function fails, it throws and IOException +

+

+
Overrides:
remove in class OsLib
+
+
+ +
Throws: +
java.io.IOException - if it fails
+
+
+
+ +

+rename

+
+protected void rename(java.lang.String oldname,
+                      java.lang.String newname)
+               throws java.io.IOException
+
+
Description copied from class: OsLib
+
Renames file or directory named oldname to newname. + If this function fails,it throws and IOException +

+

+
Overrides:
rename in class OsLib
+
+
+
Parameters:
oldname - old file name
newname - new file name +
Throws: +
java.io.IOException - if it fails
+
+
+
+ +

+tmpname

+
+protected java.lang.String tmpname()
+
+
Description copied from class: OsLib
+
Returns a string with a file name that can be used for a temporary file. + The file must be explicitly opened before its use and explicitly removed + when no longer needed. + + On some systems (POSIX), this function also creates a file with that name, + to avoid security risks. (Someone else might create the file with wrong + permissions in the time between getting the name and creating the file.) + You still have to open the file to use it and to remove it (even if you + do not use it). +

+

+
Overrides:
tmpname in class OsLib
+
+
+ +
Returns:
String filename to use
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JsePlatform.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JsePlatform.html new file mode 100644 index 0000000000..f00150d5d1 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JsePlatform.html @@ -0,0 +1,326 @@ + + + + + + +JsePlatform (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib.jse +
+Class JsePlatform

+
+java.lang.Object
+  extended by org.luaj.vm2.lib.jse.JsePlatform
+
+
+
+
public class JsePlatform
extends java.lang.Object
+ + +

+The JsePlatform class is a convenience class to standardize + how globals tables are initialized for the JSE platform. +

+ It is used to allocate either a set of standard globals using + standardGlobals() or debug globals using debugGlobals() +

+ A simple example of initializing globals and using them from Java is: +

 LuaValue _G = JsePlatform.standardGlobals();
+ _G.get("print").call(LuaValue.valueOf("hello, world"));
+  
+

+ Once globals are created, a simple way to load and run a script is: +

 LoadState.load( new FileInputStream("main.lua"), "main.lua", _G ).call();
+  
+

+ although require could also be used: +

 _G.get("require").call(LuaValue.valueOf("main"));
+  
+ For this to succeed, the file "main.lua" must be in the current directory or a resource. + See JseBaseLib for details on finding scripts using ResourceFinder. +

+ The standard globals will contain all standard libraries plus luajava: +

+ In addition, the LuaC compiler is installed so lua files may be loaded in their source form. +

+ The debug globals are simply the standard globals plus the debug library DebugLib. +

+ The class ensures that initialization is done in the correct order, + and that linkage is made to LuaThread.setGlobals(LuaValue). +

+ +

+

+
See Also:
JmePlatform
+
+ +

+ + + + + + + + + + + +
+Constructor Summary
JsePlatform() + +
+           
+  + + + + + + + + + + + + + + + +
+Method Summary
+static LuaTabledebugGlobals() + +
+          Create standard globals including the debug library.
+static LuaTablestandardGlobals() + +
+          Create a standard set of globals for JSE including all the libraries.
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+JsePlatform

+
+public JsePlatform()
+
+
+ + + + + + + + +
+Method Detail
+ +

+standardGlobals

+
+public static LuaTable standardGlobals()
+
+
Create a standard set of globals for JSE including all the libraries. +

+

+ +
Returns:
Table of globals initialized with the standard JSE libraries
See Also:
debugGlobals(), +JsePlatform, +JmePlatform
+
+
+
+ +

+debugGlobals

+
+public static LuaTable debugGlobals()
+
+
Create standard globals including the debug library. +

+

+ +
Returns:
Table of globals initialized with the standard JSE and debug libraries
See Also:
standardGlobals(), +JsePlatform, +JmePlatform, +DebugLib
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseProcess.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseProcess.html new file mode 100644 index 0000000000..297ffaa92e --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/JseProcess.html @@ -0,0 +1,323 @@ + + + + + + +JseProcess (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib.jse +
+Class JseProcess

+
+java.lang.Object
+  extended by org.luaj.vm2.lib.jse.JseProcess
+
+
+
+
public class JseProcess
extends java.lang.Object
+ + +

+Analog of Process that pipes input and output to client-specified streams. +

+ +

+


+ +

+ + + + + + + + + + + + + + +
+Constructor Summary
JseProcess(java.lang.String[] cmd, + java.io.InputStream stdin, + java.io.OutputStream stdout, + java.io.OutputStream stderr) + +
+          Construct a process around a command, with specified streams to redirect input and output to.
JseProcess(java.lang.String cmd, + java.io.InputStream stdin, + java.io.OutputStream stdout, + java.io.OutputStream stderr) + +
+          Construct a process around a command, with specified streams to redirect input and output to.
+  + + + + + + + + + + + + + + + +
+Method Summary
+ intexitValue() + +
+          Get the exit value of the process.
+ intwaitFor() + +
+          Wait for the process to complete, and all pending output to finish.
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+JseProcess

+
+public JseProcess(java.lang.String[] cmd,
+                  java.io.InputStream stdin,
+                  java.io.OutputStream stdout,
+                  java.io.OutputStream stderr)
+           throws java.io.IOException
+
+
Construct a process around a command, with specified streams to redirect input and output to. +

+

+
Parameters:
cmd - The command to execute, including arguments, if any
stdin - Optional InputStream to read from as process input, or null if input is not needed.
stdout - Optional OutputStream to copy process output to, or null if output is ignored.
stderr - Optinoal OutputStream to copy process stderr output to, or null if output is ignored. +
Throws: +
java.io.IOException - If the system process could not be created.
See Also:
Process
+
+
+ +

+JseProcess

+
+public JseProcess(java.lang.String cmd,
+                  java.io.InputStream stdin,
+                  java.io.OutputStream stdout,
+                  java.io.OutputStream stderr)
+           throws java.io.IOException
+
+
Construct a process around a command, with specified streams to redirect input and output to. +

+

+
Parameters:
cmd - The command to execute, including arguments, if any
stdin - Optional InputStream to read from as process input, or null if input is not needed.
stdout - Optional OutputStream to copy process output to, or null if output is ignored.
stderr - Optinoal OutputStream to copy process stderr output to, or null if output is ignored. +
Throws: +
java.io.IOException - If the system process could not be created.
See Also:
Process
+
+ + + + + + + + +
+Method Detail
+ +

+exitValue

+
+public int exitValue()
+
+
Get the exit value of the process. +

+

+
+
+
+
+ +

+waitFor

+
+public int waitFor()
+            throws java.lang.InterruptedException
+
+
Wait for the process to complete, and all pending output to finish. +

+

+ +
Returns:
The exit status. +
Throws: +
java.lang.InterruptedException
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/LuajavaLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/LuajavaLib.html new file mode 100644 index 0000000000..ff4c39403e --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/LuajavaLib.html @@ -0,0 +1,412 @@ + + + + + + +LuajavaLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.lib.jse +
+Class LuajavaLib

+
+java.lang.Object
+  extended by org.luaj.vm2.Varargs
+      extended by org.luaj.vm2.LuaValue
+          extended by org.luaj.vm2.LuaFunction
+              extended by org.luaj.vm2.lib.LibFunction
+                  extended by org.luaj.vm2.lib.VarArgFunction
+                      extended by org.luaj.vm2.lib.jse.LuajavaLib
+
+
+
+
public class LuajavaLib
extends VarArgFunction
+ + +

+Subclass of LibFunction which implements the features of the luajava package. +

+ Luajava is an approach to mixing lua and java using simple functions that bind + java classes and methods to lua dynamically. The API is documented on the + luajava documentation pages. +

+ Typically, this library is included as part of a call to either + JsePlatform.standardGlobals() +

+ To instantiate and use it directly, + link it into your globals table via LuaValue.load(LuaValue) using code such as: +

 LuaTable _G = new LuaTable();
+ LuaThread.setGlobals(_G);
+ LuaC.install();
+ _G.load(new BaseLib());
+ _G.load(new PackageLib());
+ _G.load(new LuajavaLib());
+ _G.get("loadstring").call( LuaValue.valueOf( 
+ 		"sys = luajava.bindClass('java.lang.System')\n"+
+ 		"print ( sys:currentTimeMillis() )\n" ) ).call(); 
+  
+ This example is not intended to be realistic - only to show how the LuajavaLib + may be initialized by hand. In practice, the luajava library is available + on all JSE platforms via the call to JsePlatform.standardGlobals() + and the luajava api's are simply invoked from lua. +

+ This has been implemented to match as closely as possible the behavior in the corresponding library in C. +

+ +

+

+
See Also:
LibFunction, +JsePlatform, +JmePlatform, +LuaC, +http://www.keplerproject.org/luajava/manual.html#luareference
+
+ +

+ + + + + + + +
+Field Summary
+ + + + + + + +
Fields inherited from class org.luaj.vm2.lib.LibFunction
name, opcode
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaFunction
env, s_metatable
+ + + + + + + +
Fields inherited from class org.luaj.vm2.LuaValue
ADD, CALL, CONCAT, DIV, EMPTYSTRING, EQ, FALSE, INDEX, LE, LEN, LT, METATABLE, MINUSONE, MOD, MODE, MUL, NEWINDEX, NIL, NILS, NONE, NOVALS, ONE, POW, SUB, TBOOLEAN, TFUNCTION, TINT, TLIGHTUSERDATA, TNIL, TNONE, TNUMBER, TOSTRING, TRUE, TSTRING, TTABLE, TTHREAD, TUSERDATA, TVALUE, TYPE_NAMES, UNM, ZERO
+  + + + + + + + + + + +
+Constructor Summary
LuajavaLib() + +
+           
+  + + + + + + + + + + + + + + + +
+Method Summary
+protected  java.lang.ClassclassForName(java.lang.String name) + +
+           
+ Varargsinvoke(Varargs args) + +
+          Override and implement for the best performance.
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.VarArgFunction
call, call, call, call, onInvoke
+ + + + + + + +
Methods inherited from class org.luaj.vm2.lib.LibFunction
bind, bind, newupe, newupl, newupn, tojstring
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaFunction
checkfunction, getfenv, getmetatable, isfunction, optfunction, setfenv, type, typename
+ + + + + + + +
Methods inherited from class org.luaj.vm2.LuaValue
add, add, add, and, arg, arg1, argerror, argerror, aritherror, aritherror, arithmt, arithmtwith, assert_, buffer, callmt, checkboolean, checkclosure, checkdouble, checkint, checkinteger, checkjstring, checklong, checkmetatag, checknotnil, checknumber, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalidkey, compareerror, compareerror, comparemt, concat, concat, concatmt, concatTo, concatTo, concatTo, div, div, div, divInto, eq_b, eq, eqmtcall, equals, error, get, get, get, getn, gettable, gt_b, gt_b, gt_b, gt, gt, gt, gteq_b, gteq_b, gteq_b, gteq, gteq, gteq, illegal, inext, invoke, invoke, invoke, invoke, invoke, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, invokemethod, isboolean, isclosure, isint, isinttype, islong, isnil, isnumber, isstring, istable, isthread, isuserdata, isuserdata, isweaknil, len, lenerror, length, listOf, listOf, load, lt_b, lt_b, lt_b, lt, lt, lt, lteq_b, lteq_b, lteq_b, lteq, lteq, lteq, metatag, method, method, method, method, method, method, mod, mod, mod, modFrom, mul, mul, mul, narg, neg, neq_b, neq, next, not, optboolean, optclosure, optdouble, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, or, pow, pow, pow, powWith, powWith, presize, raweq, raweq, raweq, raweq, raweq, rawget, rawget, rawget, rawset, rawset, rawset, rawset, rawset, rawset, rawset, rawsetlist, set, set, set, set, set, set, set, setmetatable, settable, strcmp, strcmp, strongkey, strongvalue, strvalue, sub, sub, sub, subFrom, subFrom, tableOf, tableOf, tableOf, tableOf, tableOf, tableOf, tailcallOf, testfor_b, toboolean, tobyte, tochar, todouble, tofloat, toint, tolong, tonumber, toshort, tostring, toString, touserdata, touserdata, typerror, unimplemented, userdataOf, userdataOf, valueOf, valueOf, valueOf, valueOf, valueOf, valueOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf, varargsOf
+ + + + + + + +
Methods inherited from class org.luaj.vm2.Varargs
argcheck, checkboolean, checkclosure, checkdouble, checkfunction, checkint, checkinteger, checkjstring, checklong, checknotnil, checknumber, checkstring, checktable, checkthread, checkuserdata, checkuserdata, checkvalue, eval, isfunction, isnil, isnoneornil, isnumber, isstring, istable, isTailcall, isthread, isuserdata, isvalue, optboolean, optclosure, optdouble, optfunction, optint, optinteger, optjstring, optlong, optnumber, optstring, opttable, optthread, optuserdata, optuserdata, optvalue, subargs, toboolean, tobyte, tochar, todouble, tofloat, toint, tojstring, tolong, toshort, touserdata, touserdata, type
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+LuajavaLib

+
+public LuajavaLib()
+
+
+ + + + + + + + +
+Method Detail
+ +

+invoke

+
+public Varargs invoke(Varargs args)
+
+
Description copied from class: VarArgFunction
+
Override and implement for the best performance. + May not have expected behavior for tail calls. + Should not be used if either: + - function needs to be used as a module + - function has a possibility of returning a TailcallVarargs +

+

+
Overrides:
invoke in class VarArgFunction
+
+
+
Parameters:
args - the arguments to the function call. +
Returns:
All return values as a Varargs instance.
See Also:
LuaValue.varargsOf(LuaValue[]), +LuaValue.call(LuaValue), +LuaValue.invoke(), +LuaValue.invoke(LuaValue,Varargs), +LuaValue.invokemethod(String,Varargs), +LuaValue.invokemethod(LuaValue,Varargs)
+
+
+
+ +

+classForName

+
+protected java.lang.Class classForName(java.lang.String name)
+                                throws java.lang.ClassNotFoundException
+
+
+ +
Throws: +
java.lang.ClassNotFoundException
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/CoerceJavaToLua.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/CoerceJavaToLua.html new file mode 100644 index 0000000000..4fe33652b3 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/CoerceJavaToLua.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.jse.CoerceJavaToLua (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.jse.CoerceJavaToLua

+
+No usage of org.luaj.vm2.lib.jse.CoerceJavaToLua +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/CoerceLuaToJava.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/CoerceLuaToJava.html new file mode 100644 index 0000000000..314ef66ecf --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/CoerceLuaToJava.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.jse.CoerceLuaToJava (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.jse.CoerceLuaToJava

+
+No usage of org.luaj.vm2.lib.jse.CoerceLuaToJava +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseBaseLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseBaseLib.html new file mode 100644 index 0000000000..9bfc0d2c46 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseBaseLib.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.jse.JseBaseLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.jse.JseBaseLib

+
+No usage of org.luaj.vm2.lib.jse.JseBaseLib +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseIoLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseIoLib.html new file mode 100644 index 0000000000..dfb67e2709 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseIoLib.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.jse.JseIoLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.jse.JseIoLib

+
+No usage of org.luaj.vm2.lib.jse.JseIoLib +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseMathLib.JseMathLib1.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseMathLib.JseMathLib1.html new file mode 100644 index 0000000000..00bb0c1be6 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseMathLib.JseMathLib1.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.jse.JseMathLib.JseMathLib1 (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.jse.JseMathLib.JseMathLib1

+
+No usage of org.luaj.vm2.lib.jse.JseMathLib.JseMathLib1 +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseMathLib.JseMathLib2.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseMathLib.JseMathLib2.html new file mode 100644 index 0000000000..acc814aabb --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseMathLib.JseMathLib2.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.jse.JseMathLib.JseMathLib2 (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.jse.JseMathLib.JseMathLib2

+
+No usage of org.luaj.vm2.lib.jse.JseMathLib.JseMathLib2 +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseMathLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseMathLib.html new file mode 100644 index 0000000000..f4eaed13a8 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseMathLib.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.jse.JseMathLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.jse.JseMathLib

+
+No usage of org.luaj.vm2.lib.jse.JseMathLib +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseOsLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseOsLib.html new file mode 100644 index 0000000000..2a1d5c2136 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseOsLib.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.jse.JseOsLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.jse.JseOsLib

+
+No usage of org.luaj.vm2.lib.jse.JseOsLib +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JsePlatform.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JsePlatform.html new file mode 100644 index 0000000000..d679f0d2aa --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JsePlatform.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.jse.JsePlatform (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.jse.JsePlatform

+
+No usage of org.luaj.vm2.lib.jse.JsePlatform +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseProcess.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseProcess.html new file mode 100644 index 0000000000..f577d206a1 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/JseProcess.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.jse.JseProcess (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.jse.JseProcess

+
+No usage of org.luaj.vm2.lib.jse.JseProcess +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/LuajavaLib.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/LuajavaLib.html new file mode 100644 index 0000000000..5d6c1bc209 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/class-use/LuajavaLib.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class org.luaj.vm2.lib.jse.LuajavaLib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.lib.jse.LuajavaLib

+
+No usage of org.luaj.vm2.lib.jse.LuajavaLib +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/package-frame.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/package-frame.html new file mode 100644 index 0000000000..61b8dc7c27 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/package-frame.html @@ -0,0 +1,52 @@ + + + + + + +org.luaj.vm2.lib.jse (Luaj API) + + + + + + + + + + + +org.luaj.vm2.lib.jse + + + + +
+Classes  + +
+CoerceJavaToLua +
+CoerceLuaToJava +
+JseBaseLib +
+JseIoLib +
+JseMathLib +
+JseMathLib.JseMathLib1 +
+JseMathLib.JseMathLib2 +
+JseOsLib +
+JsePlatform +
+JseProcess +
+LuajavaLib
+ + + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/package-summary.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/package-summary.html new file mode 100644 index 0000000000..5b0f773377 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/package-summary.html @@ -0,0 +1,201 @@ + + + + + + +org.luaj.vm2.lib.jse (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+

+Package org.luaj.vm2.lib.jse +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Class Summary
CoerceJavaToLuaHelper class to coerce values from Java to lua within the luajava library.
CoerceLuaToJavaHelper class to coerce values from lua to Java within the luajava library.
JseBaseLibSubclass of BaseLib and LibFunction which implements the lua basic library functions + and provides a directory based ResourceFinder as the BaseLib.FINDER.
JseIoLibSubclass of IoLib and therefore LibFunction which implements the lua standard io + library for the JSE platform.
JseMathLibSubclass of LibFunction which implements the lua standard math + library.
JseMathLib.JseMathLib1 
JseMathLib.JseMathLib2 
JseOsLibSubclass of LibFunction which implements the standard lua os library.
JsePlatformThe JsePlatform class is a convenience class to standardize + how globals tables are initialized for the JSE platform.
JseProcessAnalog of Process that pipes input and output to client-specified streams.
LuajavaLibSubclass of LibFunction which implements the features of the luajava package.
+  + +

+

+
+
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/package-tree.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/package-tree.html new file mode 100644 index 0000000000..785d3f9f1d --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/package-tree.html @@ -0,0 +1,176 @@ + + + + + + +org.luaj.vm2.lib.jse Class Hierarchy (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Hierarchy For Package org.luaj.vm2.lib.jse +

+
+
+
Package Hierarchies:
All Packages
+
+

+Class Hierarchy +

+ +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/package-use.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/package-use.html new file mode 100644 index 0000000000..7f9f47ee37 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/jse/package-use.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Package org.luaj.vm2.lib.jse (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Package
org.luaj.vm2.lib.jse

+
+No usage of org.luaj.vm2.lib.jse +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/package-frame.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/package-frame.html new file mode 100644 index 0000000000..a838fe26d5 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/package-frame.html @@ -0,0 +1,71 @@ + + + + + + +org.luaj.vm2.lib (Luaj API) + + + + + + + + + + + +org.luaj.vm2.lib + + + + +
+Interfaces  + +
+ResourceFinder
+ + + + + + +
+Classes  + +
+BaseLib +
+CoroutineLib +
+DebugLib +
+IoLib +
+LibFunction +
+MathLib +
+OneArgFunction +
+OsLib +
+PackageLib +
+StringLib +
+TableLib +
+ThreeArgFunction +
+TwoArgFunction +
+VarArgFunction +
+ZeroArgFunction
+ + + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/package-summary.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/package-summary.html new file mode 100644 index 0000000000..90cc76ef9b --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/package-summary.html @@ -0,0 +1,239 @@ + + + + + + +org.luaj.vm2.lib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+

+Package org.luaj.vm2.lib +

+ + + + + + + + + +
+Interface Summary
ResourceFinderInterface for opening application resource files such as scripts sources.
+  + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Class Summary
BaseLibSubclass of LibFunction which implements the lua basic library functions.
CoroutineLibSubclass of LibFunction which implements the lua standard coroutine + library.
DebugLibSubclass of LibFunction which implements the lua standard debug + library.
IoLibAbstract base class extending LibFunction which implements the + core of the lua standard io library.
LibFunctionSubclass of LuaFunction common to Java functions exposed to lua.
MathLibSubclass of LibFunction which implements the lua standard math + library.
OneArgFunctionAbstract base class for Java function implementations that take one argument and + return one value.
OsLibSubclass of LibFunction which implements the standard lua os library.
PackageLibSubclass of LibFunction which implements the lua standard package and module + library functions.
StringLibSubclass of LibFunction which implements the lua standard string + library.
TableLibSubclass of LibFunction which implements the lua standard table + library.
ThreeArgFunctionAbstract base class for Java function implementations that take two arguments and + return one value.
TwoArgFunctionAbstract base class for Java function implementations that take two arguments and + return one value.
VarArgFunctionAbstract base class for Java function implementations that takes varaiable arguments and + returns multiple return values.
ZeroArgFunctionAbstract base class for Java function implementations that take no arguments and + return one value.
+  + +

+

+
+
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/package-tree.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/package-tree.html new file mode 100644 index 0000000000..bdd86f02ab --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/package-tree.html @@ -0,0 +1,171 @@ + + + + + + +org.luaj.vm2.lib Class Hierarchy (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Hierarchy For Package org.luaj.vm2.lib +

+
+
+
Package Hierarchies:
All Packages
+
+

+Class Hierarchy +

+ +

+Interface Hierarchy +

+ +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/lib/package-use.html b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/package-use.html new file mode 100644 index 0000000000..f5484bf6fe --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/lib/package-use.html @@ -0,0 +1,333 @@ + + + + + + +Uses of Package org.luaj.vm2.lib (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Package
org.luaj.vm2.lib

+
+ + + + + + + + + + + + + + + + + +
+Packages that use org.luaj.vm2.lib
org.luaj.vm2.lib  
org.luaj.vm2.lib.jme  
org.luaj.vm2.lib.jse  
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Classes in org.luaj.vm2.lib used by org.luaj.vm2.lib
BaseLib + +
+          Subclass of LibFunction which implements the lua basic library functions.
IoLib.File + +
+           
LibFunction + +
+          Subclass of LuaFunction common to Java functions exposed to lua.
MathLib + +
+          Subclass of LibFunction which implements the lua standard math + library.
OneArgFunction + +
+          Abstract base class for Java function implementations that take one argument and + return one value.
PackageLib + +
+          Subclass of LibFunction which implements the lua standard package and module + library functions.
ResourceFinder + +
+          Interface for opening application resource files such as scripts sources.
VarArgFunction + +
+          Abstract base class for Java function implementations that takes varaiable arguments and + returns multiple return values.
+  +

+ + + + + + + + + + + + + + + + + +
+Classes in org.luaj.vm2.lib used by org.luaj.vm2.lib.jme
IoLib + +
+          Abstract base class extending LibFunction which implements the + core of the lua standard io library.
IoLib.File + +
+           
LibFunction + +
+          Subclass of LuaFunction common to Java functions exposed to lua.
OneArgFunction + +
+          Abstract base class for Java function implementations that take one argument and + return one value.
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Classes in org.luaj.vm2.lib used by org.luaj.vm2.lib.jse
BaseLib + +
+          Subclass of LibFunction which implements the lua basic library functions.
IoLib + +
+          Abstract base class extending LibFunction which implements the + core of the lua standard io library.
IoLib.File + +
+           
LibFunction + +
+          Subclass of LuaFunction common to Java functions exposed to lua.
MathLib + +
+          Subclass of LibFunction which implements the lua standard math + library.
OneArgFunction + +
+          Abstract base class for Java function implementations that take one argument and + return one value.
OsLib + +
+          Subclass of LibFunction which implements the standard lua os library.
ResourceFinder + +
+          Interface for opening application resource files such as scripts sources.
TwoArgFunction + +
+          Abstract base class for Java function implementations that take two arguments and + return one value.
VarArgFunction + +
+          Abstract base class for Java function implementations that takes varaiable arguments and + returns multiple return values.
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/luajc/LuaJC.html b/luaj-2.0.3/docs/api/org/luaj/vm2/luajc/LuaJC.html new file mode 100644 index 0000000000..d5d6b0bdb3 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/luajc/LuaJC.html @@ -0,0 +1,369 @@ + + + + + + +LuaJC (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ +org.luaj.vm2.luajc +
+Class LuaJC

+
+java.lang.Object
+  extended by org.luaj.vm2.luajc.LuaJC
+
+
+
All Implemented Interfaces:
LoadState.LuaCompiler
+
+
+
+
public class LuaJC
extends java.lang.Object
implements LoadState.LuaCompiler
+ + +

+Implementation of LoadState.LuaCompiler which does direct + lua-to-java-bytecode compiling. +

+ This requires the bcel library to be on the class path to work as expected. + If the library is not found, the default LuaC lua-to-lua-bytecode + compiler will be used. +

+ The compiler should be installed as part of globals initialization, + and before any scripts or lua code is executed. + A typical example is to install it following the globals creation, + as in the following: +

 LuaValue _G = JsePlatform.standardGlobals();
+ LuaJC.install();
+ LoadState.load( new ByteArrayInputStream("print 'hello'".getBytes()), "main.lua", _G ).call();
+  
+

+ +

+

+
See Also:
LoadState.LuaCompiler, +LuaC, +JsePlatform, +JmePlatform, +BaseLib, +LuaValue
+
+ +

+ + + + + + + + + + + +
+Constructor Summary
LuaJC() + +
+           
+  + + + + + + + + + + + + + + + + + + + + + + + +
+Method Summary
+ java.util.HashtablecompileAll(java.io.InputStream script, + java.lang.String chunkname, + java.lang.String filename) + +
+           
+static LuaJCgetInstance() + +
+           
+static voidinstall() + +
+          Install the compiler as the main compiler to use.
+ LuaFunctionload(java.io.InputStream stream, + java.lang.String name, + LuaValue env) + +
+          Load into a Closure or LuaFunction from a Stream and initializes the environment
+ + + + + + + +
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
+  +

+ + + + + + + + +
+Constructor Detail
+ +

+LuaJC

+
+public LuaJC()
+
+
+ + + + + + + + +
+Method Detail
+ +

+getInstance

+
+public static LuaJC getInstance()
+
+
+
+
+
+
+
+
+
+ +

+install

+
+public static final void install()
+
+
Install the compiler as the main compiler to use. + Will fall back to the LuaC prototype compiler. +

+

+
+
+
+
+
+
+
+ +

+compileAll

+
+public java.util.Hashtable compileAll(java.io.InputStream script,
+                                      java.lang.String chunkname,
+                                      java.lang.String filename)
+                               throws java.io.IOException
+
+
+
+
+
+ +
Throws: +
java.io.IOException
+
+
+
+ +

+load

+
+public LuaFunction load(java.io.InputStream stream,
+                        java.lang.String name,
+                        LuaValue env)
+                 throws java.io.IOException
+
+
Description copied from interface: LoadState.LuaCompiler
+
Load into a Closure or LuaFunction from a Stream and initializes the environment +

+

+
Specified by:
load in interface LoadState.LuaCompiler
+
+
+ +
Throws: +
java.io.IOException
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/luajc/class-use/LuaJC.html b/luaj-2.0.3/docs/api/org/luaj/vm2/luajc/class-use/LuaJC.html new file mode 100644 index 0000000000..36590848d5 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/luajc/class-use/LuaJC.html @@ -0,0 +1,180 @@ + + + + + + +Uses of Class org.luaj.vm2.luajc.LuaJC (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Class
org.luaj.vm2.luajc.LuaJC

+
+ + + + + + + + + +
+Packages that use LuaJC
org.luaj.vm2.luajc  
+  +

+ + + + + +
+Uses of LuaJC in org.luaj.vm2.luajc
+  +

+ + + + + + + + + +
Methods in org.luaj.vm2.luajc that return LuaJC
+static LuaJCLuaJC.getInstance() + +
+           
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/luajc/package-frame.html b/luaj-2.0.3/docs/api/org/luaj/vm2/luajc/package-frame.html new file mode 100644 index 0000000000..ae6ace9b78 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/luajc/package-frame.html @@ -0,0 +1,32 @@ + + + + + + +org.luaj.vm2.luajc (Luaj API) + + + + + + + + + + + +org.luaj.vm2.luajc + + + + +
+Classes  + +
+LuaJC
+ + + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/luajc/package-summary.html b/luaj-2.0.3/docs/api/org/luaj/vm2/luajc/package-summary.html new file mode 100644 index 0000000000..3446959c7b --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/luajc/package-summary.html @@ -0,0 +1,158 @@ + + + + + + +org.luaj.vm2.luajc (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+

+Package org.luaj.vm2.luajc +

+ + + + + + + + + +
+Class Summary
LuaJCImplementation of LoadState.LuaCompiler which does direct + lua-to-java-bytecode compiling.
+  + +

+

+
+
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/luajc/package-tree.html b/luaj-2.0.3/docs/api/org/luaj/vm2/luajc/package-tree.html new file mode 100644 index 0000000000..c7e60e2cb5 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/luajc/package-tree.html @@ -0,0 +1,154 @@ + + + + + + +org.luaj.vm2.luajc Class Hierarchy (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Hierarchy For Package org.luaj.vm2.luajc +

+
+
+
Package Hierarchies:
All Packages
+
+

+Class Hierarchy +

+ +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/luajc/package-use.html b/luaj-2.0.3/docs/api/org/luaj/vm2/luajc/package-use.html new file mode 100644 index 0000000000..ef67ada155 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/luajc/package-use.html @@ -0,0 +1,171 @@ + + + + + + +Uses of Package org.luaj.vm2.luajc (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Package
org.luaj.vm2.luajc

+
+ + + + + + + + + +
+Packages that use org.luaj.vm2.luajc
org.luaj.vm2.luajc  
+  +

+ + + + + + + + +
+Classes in org.luaj.vm2.luajc used by org.luaj.vm2.luajc
LuaJC + +
+          Implementation of LoadState.LuaCompiler which does direct + lua-to-java-bytecode compiling.
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/package-frame.html b/luaj-2.0.3/docs/api/org/luaj/vm2/package-frame.html new file mode 100644 index 0000000000..d86427e99d --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/package-frame.html @@ -0,0 +1,109 @@ + + + + + + +org.luaj.vm2 (Luaj API) + + + + + + + + + + + +org.luaj.vm2 + + + + +
+Interfaces  + +
+LoadState.LuaCompiler
+ + + + + + +
+Classes  + +
+Buffer +
+LoadState +
+LocVars +
+Lua +
+LuaBoolean +
+LuaClosure +
+LuaDouble +
+LuaFunction +
+LuaInteger +
+LuaNil +
+LuaNumber +
+LuaString +
+LuaTable +
+LuaThread +
+LuaThread.CallStack +
+LuaUserdata +
+LuaValue +
+Print +
+Prototype +
+TailcallVarargs +
+UpValue +
+Varargs +
+WeakTable
+ + + + + + +
+Exceptions  + +
+LuaError
+ + + + + + +
+Errors  + +
+OrphanedThread
+ + + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/package-summary.html b/luaj-2.0.3/docs/api/org/luaj/vm2/package-summary.html new file mode 100644 index 0000000000..e8bffe8e0f --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/package-summary.html @@ -0,0 +1,291 @@ + + + + + + +org.luaj.vm2 (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+

+Package org.luaj.vm2 +

+ + + + + + + + + +
+Interface Summary
LoadState.LuaCompilerInterface for the compiler, if it is installed.
+  + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Class Summary
BufferString buffer for use in string library methods, optimized for production + of StrValue instances.
LoadStateClass to manage loading of Prototype instances.
LocVarsData class to hold debug information relatign to local variables for a Prototype
LuaConstants for lua limits and opcodes.
LuaBooleanExtension of LuaValue which can hold a Java boolean as its value.
LuaClosureExtension of LuaFunction which executes lua bytecode.
LuaDoubleExtension of LuaNumber which can hold a Java double as its value.
LuaFunctionBase class for functions implemented in Java.
LuaIntegerExtension of LuaNumber which can hold a Java int as its value.
LuaNilClass to encapsulate behavior of the singleton instance nil
LuaNumberBase class for representing numbers as lua values directly.
LuaStringSubclass of LuaValue for representing lua strings.
LuaTableSubclass of LuaValue for representing lua tables.
LuaThreadSubclass of LuaValue that implements + a lua coroutine thread using Java Threads.
LuaThread.CallStack 
LuaUserdata 
LuaValueBase class for all concrete lua type values.
PrintDebug helper class to pretty-print lua bytecodes.
PrototypePrototype representing compiled lua code.
TailcallVarargsSubclass of Varargs that represents a lua tail call + in a Java library function execution environment.
UpValueUpvalue used with Closure formulation
VarargsClass to encapsulate varargs values, either as part of a variable argument list, or multiple return values.
WeakTableSubclass of LuaTable that provides weak key and weak value semantics.
+  + +

+ + + + + + + + + +
+Exception Summary
LuaErrorRuntimeException that is thrown and caught in response to a lua error.
+  + +

+ + + + + + + + + +
+Error Summary
OrphanedThreadError sublcass that indicates a lua thread that is no + longer referenced has been detected.
+  + +

+

+
+
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/package-tree.html b/luaj-2.0.3/docs/api/org/luaj/vm2/package-tree.html new file mode 100644 index 0000000000..8669767686 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/package-tree.html @@ -0,0 +1,179 @@ + + + + + + +org.luaj.vm2 Class Hierarchy (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Hierarchy For Package org.luaj.vm2 +

+
+
+
Package Hierarchies:
All Packages
+
+

+Class Hierarchy +

+ +

+Interface Hierarchy +

+ +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/org/luaj/vm2/package-use.html b/luaj-2.0.3/docs/api/org/luaj/vm2/package-use.html new file mode 100644 index 0000000000..8e4890ac69 --- /dev/null +++ b/luaj-2.0.3/docs/api/org/luaj/vm2/package-use.html @@ -0,0 +1,490 @@ + + + + + + +Uses of Package org.luaj.vm2 (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Uses of Package
org.luaj.vm2

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Packages that use org.luaj.vm2
org.luaj.vm2  
org.luaj.vm2.compiler  
org.luaj.vm2.lib  
org.luaj.vm2.lib.jme  
org.luaj.vm2.lib.jse  
org.luaj.vm2.luajc  
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Classes in org.luaj.vm2 used by org.luaj.vm2
Buffer + +
+          String buffer for use in string library methods, optimized for production + of StrValue instances.
LoadState.LuaCompiler + +
+          Interface for the compiler, if it is installed.
LocVars + +
+          Data class to hold debug information relatign to local variables for a Prototype
Lua + +
+          Constants for lua limits and opcodes.
LuaBoolean + +
+          Extension of LuaValue which can hold a Java boolean as its value.
LuaClosure + +
+          Extension of LuaFunction which executes lua bytecode.
LuaDouble + +
+          Extension of LuaNumber which can hold a Java double as its value.
LuaFunction + +
+          Base class for functions implemented in Java.
LuaInteger + +
+          Extension of LuaNumber which can hold a Java int as its value.
LuaNumber + +
+          Base class for representing numbers as lua values directly.
LuaString + +
+          Subclass of LuaValue for representing lua strings.
LuaTable + +
+          Subclass of LuaValue for representing lua tables.
LuaThread + +
+          Subclass of LuaValue that implements + a lua coroutine thread using Java Threads.
LuaThread.CallStack + +
+           
LuaUserdata + +
+           
LuaValue + +
+          Base class for all concrete lua type values.
Prototype + +
+          Prototype representing compiled lua code.
UpValue + +
+          Upvalue used with Closure formulation
Varargs + +
+          Class to encapsulate varargs values, either as part of a variable argument list, or multiple return values.
+  +

+ + + + + + + + + + + + + + + + + + + + + + + +
+Classes in org.luaj.vm2 used by org.luaj.vm2.compiler
LoadState.LuaCompiler + +
+          Interface for the compiler, if it is installed.
Lua + +
+          Constants for lua limits and opcodes.
LuaFunction + +
+          Base class for functions implemented in Java.
LuaString + +
+          Subclass of LuaValue for representing lua strings.
LuaValue + +
+          Base class for all concrete lua type values.
Prototype + +
+          Prototype representing compiled lua code.
+  +

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+Classes in org.luaj.vm2 used by org.luaj.vm2.lib
LuaFunction + +
+          Base class for functions implemented in Java.
LuaString + +
+          Subclass of LuaValue for representing lua strings.
LuaTable + +
+          Subclass of LuaValue for representing lua tables.
LuaThread + +
+          Subclass of LuaValue that implements + a lua coroutine thread using Java Threads.
LuaValue + +
+          Base class for all concrete lua type values.
Prototype + +
+          Prototype representing compiled lua code.
Varargs + +
+          Class to encapsulate varargs values, either as part of a variable argument list, or multiple return values.
+  +

+ + + + + + + + + + + + + + + + + +
+Classes in org.luaj.vm2 used by org.luaj.vm2.lib.jme
LuaFunction + +
+          Base class for functions implemented in Java.
LuaTable + +
+          Subclass of LuaValue for representing lua tables.
LuaValue + +
+          Base class for all concrete lua type values.
Varargs + +
+          Class to encapsulate varargs values, either as part of a variable argument list, or multiple return values.
+  +

+ + + + + + + + + + + + + + + + + +
+Classes in org.luaj.vm2 used by org.luaj.vm2.lib.jse
LuaFunction + +
+          Base class for functions implemented in Java.
LuaTable + +
+          Subclass of LuaValue for representing lua tables.
LuaValue + +
+          Base class for all concrete lua type values.
Varargs + +
+          Class to encapsulate varargs values, either as part of a variable argument list, or multiple return values.
+  +

+ + + + + + + + + + + + + + +
+Classes in org.luaj.vm2 used by org.luaj.vm2.luajc
LoadState.LuaCompiler + +
+          Interface for the compiler, if it is installed.
LuaFunction + +
+          Base class for functions implemented in Java.
LuaValue + +
+          Base class for all concrete lua type values.
+  +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/overview-frame.html b/luaj-2.0.3/docs/api/overview-frame.html new file mode 100644 index 0000000000..f6d436a2b0 --- /dev/null +++ b/luaj-2.0.3/docs/api/overview-frame.html @@ -0,0 +1,52 @@ + + + + + + +Overview List (Luaj API) + + + + + + + + + + + + + + + +
+
+ + + + + +
All Classes +

+ +Packages +
+org.luaj.vm2 +
+org.luaj.vm2.compiler +
+org.luaj.vm2.lib +
+org.luaj.vm2.lib.jme +
+org.luaj.vm2.lib.jse +
+org.luaj.vm2.luajc +
+

+ +

+  + + diff --git a/luaj-2.0.3/docs/api/overview-summary.html b/luaj-2.0.3/docs/api/overview-summary.html new file mode 100644 index 0000000000..467df1d20b --- /dev/null +++ b/luaj-2.0.3/docs/api/overview-summary.html @@ -0,0 +1,176 @@ + + + + + + +Overview (Luaj API) + + + + + + + + + + + + +


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+

Luaj API

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Other Packages
org.luaj.vm2 
org.luaj.vm2.compiler 
org.luaj.vm2.lib 
org.luaj.vm2.lib.jme 
org.luaj.vm2.lib.jse 
org.luaj.vm2.luajc 
+ +


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/overview-tree.html b/luaj-2.0.3/docs/api/overview-tree.html new file mode 100644 index 0000000000..defde82f77 --- /dev/null +++ b/luaj-2.0.3/docs/api/overview-tree.html @@ -0,0 +1,197 @@ + + + + + + +Class Hierarchy (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Hierarchy For All Packages

+
+
+
Package Hierarchies:
org.luaj.vm2, org.luaj.vm2.compiler, org.luaj.vm2.lib, org.luaj.vm2.lib.jme, org.luaj.vm2.lib.jse, org.luaj.vm2.luajc
+
+

+Class Hierarchy +

+ +

+Interface Hierarchy +

+ +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/package-list b/luaj-2.0.3/docs/api/package-list new file mode 100644 index 0000000000..51014d44d7 --- /dev/null +++ b/luaj-2.0.3/docs/api/package-list @@ -0,0 +1,6 @@ +org.luaj.vm2 +org.luaj.vm2.compiler +org.luaj.vm2.lib +org.luaj.vm2.lib.jme +org.luaj.vm2.lib.jse +org.luaj.vm2.luajc diff --git a/luaj-2.0.3/docs/api/resources/inherit.gif b/luaj-2.0.3/docs/api/resources/inherit.gif new file mode 100644 index 0000000000000000000000000000000000000000..c814867a13deb0ca7ea2156c6ca1d5a03372af7e GIT binary patch literal 57 zcmZ?wbhEHbIIT!9-C*e{wE9>Kx3D)-;0v)C; KYxQGgum%9JOA&7X literal 0 HcmV?d00001 diff --git a/luaj-2.0.3/docs/api/serialized-form.html b/luaj-2.0.3/docs/api/serialized-form.html new file mode 100644 index 0000000000..6f291d6e9a --- /dev/null +++ b/luaj-2.0.3/docs/api/serialized-form.html @@ -0,0 +1,202 @@ + + + + + + +Serialized Form (Luaj API) + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ +
+ + + +
+
+

+Serialized Form

+
+
+ + + + + +
+Package org.luaj.vm2
+ +

+ + + + + +
+Class org.luaj.vm2.LuaError extends java.lang.RuntimeException implements Serializable
+ +

+serialVersionUID: 1L + +

+ + + + + +
+Serialized Fields
+ +

+traceback

+
+java.lang.String traceback
+
+
+
+
+
+

+cause

+
+java.lang.Throwable cause
+
+
+
+
+ +

+ + + + + +
+Class org.luaj.vm2.OrphanedThread extends java.lang.Error implements Serializable
+ +

+ +

+


+ + + + + + + + + + + + + + + +
+ +
+ + + +
+Copyright © 2007-2008 Luaj.org. All Rights Reserved. + + diff --git a/luaj-2.0.3/docs/api/stylesheet.css b/luaj-2.0.3/docs/api/stylesheet.css new file mode 100644 index 0000000000..6ea9e51616 --- /dev/null +++ b/luaj-2.0.3/docs/api/stylesheet.css @@ -0,0 +1,29 @@ +/* Javadoc style sheet */ + +/* Define colors, fonts and other style attributes here to override the defaults */ + +/* Page background color */ +body { background-color: #FFFFFF; color:#000000 } + +/* Headings */ +h1 { font-size: 145% } + +/* Table colors */ +.TableHeadingColor { background: #CCCCFF; color:#000000 } /* Dark mauve */ +.TableSubHeadingColor { background: #EEEEFF; color:#000000 } /* Light mauve */ +.TableRowColor { background: #FFFFFF; color:#000000 } /* White */ + +/* Font used in left-hand frame lists */ +.FrameTitleFont { font-size: 100%; font-family: Helvetica, Arial, sans-serif; color:#000000 } +.FrameHeadingFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 } +.FrameItemFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 } + +/* Navigation bar fonts and colors */ +.NavBarCell1 { background-color:#EEEEFF; color:#000000} /* Light mauve */ +.NavBarCell1Rev { background-color:#00008B; color:#FFFFFF} /* Dark Blue */ +.NavBarFont1 { font-family: Arial, Helvetica, sans-serif; color:#000000;color:#000000;} +.NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;color:#FFFFFF;} + +.NavBarCell2 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000} +.NavBarCell3 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000} + diff --git a/luaj-2.0.3/examples/jme/SampleMIDlet.java b/luaj-2.0.3/examples/jme/SampleMIDlet.java new file mode 100644 index 0000000000..19fd473428 --- /dev/null +++ b/luaj-2.0.3/examples/jme/SampleMIDlet.java @@ -0,0 +1,34 @@ + + +import javax.microedition.midlet.MIDlet; +import javax.microedition.midlet.MIDletStateChangeException; + +import org.luaj.vm2.*; +import org.luaj.vm2.lib.*; +import org.luaj.vm2.lib.jme.JmePlatform; +import org.luaj.vm2.compiler.LuaC; + + +public class SampleMIDlet extends MIDlet { + + // the script will be loaded as a resource + private static final String DEFAULT_SCRIPT = "hello.lua"; + + protected void startApp() throws MIDletStateChangeException { + // get the script as an app property + String script = this.getAppProperty("script"); + if ( script == null ) + script = DEFAULT_SCRIPT; + + // create an environment to run in + LuaValue _G = JmePlatform.standardGlobals(); + _G.get("require").call( LuaValue.valueOf(script) ); + } + + protected void destroyApp(boolean arg0) throws MIDletStateChangeException { + } + + protected void pauseApp() { + } + +} diff --git a/luaj-2.0.3/examples/jse/SampleJseMain.java b/luaj-2.0.3/examples/jse/SampleJseMain.java new file mode 100644 index 0000000000..956100816b --- /dev/null +++ b/luaj-2.0.3/examples/jse/SampleJseMain.java @@ -0,0 +1,18 @@ + + +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.jse.JsePlatform; + +public class SampleJseMain { + + + public static void main(String[] args) throws Exception { + String script = "examples/lua/hello.lua"; + + // create an environment to run in + LuaValue _G = JsePlatform.standardGlobals(); + _G.get("dofile").call( LuaValue.valueOf(script) ); + } + + +} diff --git a/luaj-2.0.3/examples/jse/SampleParser.java b/luaj-2.0.3/examples/jse/SampleParser.java new file mode 100644 index 0000000000..48b773e08d --- /dev/null +++ b/luaj-2.0.3/examples/jse/SampleParser.java @@ -0,0 +1,49 @@ +/** + * Sample luaj program that uses the LuaParser class for parsing, and intercepts the + * generated ParseExceptions and fills in the file, line and column information where + * the exception occurred. + */ +import java.io.*; + +import org.luaj.vm2.ast.*; +import org.luaj.vm2.ast.Exp.AnonFuncDef; +import org.luaj.vm2.ast.Stat.FuncDef; +import org.luaj.vm2.ast.Stat.LocalFuncDef; +import org.luaj.vm2.parser.*; + + +public class SampleParser { + + static public void main(String[] args) { + if (args.length == 0) { + System.out.println("usage: SampleParser luafile"); + return; + } + try { + final String file = args[0]; + + // Create a LuaParser. This will fill in line and column number + // information for most exceptions. + LuaParser parser = new LuaParser(new FileInputStream(file)); + + // Perform the parsing. + Chunk chunk = parser.Chunk(); + + // Print out names found in this source file. + chunk.accept( new Visitor() { + public void visit(Exp.NameExp exp) { + System.out.println("Name in use: "+exp.name.name); + } + } ); + + } catch ( ParseException e ) { + System.out.println("parse failed: " + e.getMessage() + "\n" + + "Token Image: '" + e.currentToken.image + "'\n" + + "Location: " + e.currentToken.beginLine + ":" + e.currentToken.beginColumn + + "-" + e.currentToken.endLine + "," + e.currentToken.endColumn); + } catch ( IOException e ) { + System.out.println( "IOException occurred: "+e ); + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/luaj-2.0.3/examples/jse/ScriptEngineSample.java b/luaj-2.0.3/examples/jse/ScriptEngineSample.java new file mode 100644 index 0000000000..e1518d64d7 --- /dev/null +++ b/luaj-2.0.3/examples/jse/ScriptEngineSample.java @@ -0,0 +1,128 @@ + + +import javax.script.Bindings; +import javax.script.Compilable; +import javax.script.CompiledScript; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineFactory; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import javax.script.SimpleBindings; + +import org.luaj.vm2.LuaValue; + +public class ScriptEngineSample { + + public static void main(String [] args) { + ScriptEngineManager sem = new ScriptEngineManager(); + ScriptEngine e = sem.getEngineByExtension(".lua"); + ScriptEngineFactory f = e.getFactory(); + + // uncomment to enable the lua-to-java bytecode compiler + // (require bcel library in class path) + // org.luaj.vm2.luajc.LuaJC.install(); + + System.out.println( "Engine name: " +f.getEngineName() ); + System.out.println( "Engine Version: " +f.getEngineVersion() ); + System.out.println( "LanguageName: " +f.getLanguageName() ); + System.out.println( "Language Version: " +f.getLanguageVersion() ); + String statement = f.getOutputStatement("\"hello, world\""); + System.out.println(statement); + try { + e.eval(statement); + + e.put("x", 25); + e.eval("y = math.sqrt(x)"); + System.out.println( "y="+e.get("y") ); + + e.put("x", 2); + e.eval("y = math.sqrt(x)"); + System.out.println( "y="+e.get("y") ); + + CompiledScript cs = ((Compilable)e).compile("y = math.sqrt(x); return y"); + Bindings b = e.createBindings(); + b.put("x", 3); + System.out.println( "eval: "+cs.eval(b) ); + System.out.println( "y="+b.get("y") ); + + SimpleBindings sb = new SimpleBindings(); + sb.put("x", 144); + System.out.println( "eval: "+cs.eval(sb) ); + System.out.println( "y="+sb.get("y") ); + + try { + e.eval("\n\nbogus example\n\n"); + } catch ( ScriptException se ) { + System.out.println("script threw ScriptException as expected, message is '"+se.getMessage()+"'"); + } + + testEngineBindings(e); + testClientBindings(e); + testUserClasses(e); + + } catch (ScriptException ex) { + ex.printStackTrace(); + } + } + + public static class SomeUserClass { + public String toString() { + return "user-class-instance-"+this.hashCode(); + } + } + + public static void testEngineBindings(ScriptEngine e) throws ScriptException { + testBindings(e, e.createBindings()); + } + public static void testClientBindings(ScriptEngine e) throws ScriptException { + testBindings(e, new SimpleBindings()); + } + public static void testBindings(ScriptEngine e, Bindings b) throws ScriptException { + CompiledScript cs = ((Compilable)e).compile( + "print( 'somejavaint', type(somejavaint), somejavaint )\n" + + "print( 'somejavadouble', type(somejavadouble), somejavadouble )\n" + + "print( 'somejavastring', type(somejavastring), somejavastring )\n" + + "print( 'somejavaobject', type(somejavaobject), somejavaobject )\n" + + "print( 'somejavaarray', type(somejavaarray), somejavaarray, somejavaarray[1] )\n" + + "someluaint = 444\n" + + "someluadouble = 555.666\n" + + "someluastring = 'def'\n" + + "someluauserdata = somejavaobject\n" + + "someluatable = { 999, 111 }\n" + + "someluafunction = function(x) print( 'hello, world', x ) return 678 end\n" + + "" ); + b.put("somejavaint", 111); + b.put("somejavadouble", 222.333); + b.put("somejavastring", "abc"); + b.put("somejavaobject", new SomeUserClass()); + b.put("somejavaarray", new int[] { 777, 888 } ); + System.out.println( "eval: "+cs.eval(b) ); + Object someluaint = b.get("someluaint"); + Object someluadouble = b.get("someluaint"); + Object someluastring = b.get("someluastring"); + Object someluauserdata = b.get("someluauserdata"); + Object someluatable = b.get("someluatable"); + Object someluafunction = b.get("someluafunction"); + System.out.println( "someluaint: "+someluaint.getClass()+" "+someluaint ); + System.out.println( "someluadouble: "+someluadouble.getClass()+" "+someluadouble ); + System.out.println( "someluastring: "+someluastring.getClass()+" "+someluastring ); + System.out.println( "someluauserdata: "+someluauserdata.getClass()+" "+someluauserdata ); + System.out.println( "someluatable: "+someluatable.getClass()+" "+someluatable ); + System.out.println( "someluafunction: "+someluafunction.getClass()+" "+someluafunction ); + System.out.println( "someluafunction(345): "+((LuaValue) someluafunction).call(LuaValue.valueOf(345)) ); + } + + public static void testUserClasses(ScriptEngine e) throws ScriptException { + CompiledScript cs = ((Compilable)e).compile( + "test = test or luajava.newInstance(\"java.lang.String\", \"test\")\n" + + "print( 'test', type(test), test, tostring(test) )\n" + + "return tostring(test)"); + Bindings b = e.createBindings(); + Object resultstring = cs.eval(b); + b.put("test", new SomeUserClass()); + Object resultuserclass = cs.eval(b); + System.out.println( "eval(string): "+resultstring.getClass()+" "+resultstring ); + System.out.println( "eval(userclass): "+resultuserclass.getClass()+" "+resultuserclass ); + } + +} diff --git a/luaj-2.0.3/examples/jse/hyperbolic.java b/luaj-2.0.3/examples/jse/hyperbolic.java new file mode 100644 index 0000000000..bbce40f52a --- /dev/null +++ b/luaj-2.0.3/examples/jse/hyperbolic.java @@ -0,0 +1,63 @@ +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.OneArgFunction; + +/** + * Sample library that can be called via luaj's require() implementation. + * + * This library, when loaded, creates a lua package called "hyperbolic" + * which has two functions, "sinh()" and "cosh()". + * + * Because the class is in the default Java package, it can be called using + * lua code such as: + * +
 {@code 
+ * require 'hyperbolic'
+ * print('sinh',  hyperbolic.sinh)
+ * print('sinh(1.0)',  hyperbolic.sinh(1.0))
+ * }
+ * + * When require() loads the code, two things happen: 1) the public constructor + * is called to construct a library instance, and 2) the instance is invoked + * as a java call with no arguments. This invocation should be used to initialize + * the library, and add any values to globals that are desired. + */ +public class hyperbolic extends OneArgFunction { + + /** Public constructor. To be loaded via require(), the library class + * must have a public constructor. + */ + public hyperbolic() {} + + /** The implementation of the ZeroArgFunction interface. + * This will be called once when the library is loaded via require(). + * @param arg LuaString containing the name used in the call to require(). + * @return Value that will be returned in the require() call. In this case, + * it is the library itself. + */ + public LuaValue call(LuaValue libname) { + LuaValue library = tableOf(); + library.set( "sinh", new sinh() ); + library.set( "cosh", new cosh() ); + env.set( "hyperbolic", library ); + return library; + } + + /* Each library function is coded as a specific LibFunction based on the + * arguments it expects and returns. By using OneArgFunction, rather than + * LibFunction directly, the number of arguments supplied will be coerced + * to match what the implementation expects. */ + + /** Mathematical sinh function provided as a OneArgFunction. */ + static class sinh extends OneArgFunction { + public LuaValue call(LuaValue x) { + return LuaValue.valueOf(Math.sinh(x.checkdouble())); + } + } + + /** Mathematical cosh function provided as a OneArgFunction. */ + static class cosh extends OneArgFunction { + public LuaValue call(LuaValue x) { + return LuaValue.valueOf(Math.cosh(x.checkdouble())); + } + } +} \ No newline at end of file diff --git a/luaj-2.0.3/examples/lua/hello.lua b/luaj-2.0.3/examples/lua/hello.lua new file mode 100644 index 0000000000..5f66bcecea --- /dev/null +++ b/luaj-2.0.3/examples/lua/hello.lua @@ -0,0 +1 @@ +print( 'hello, world' ) \ No newline at end of file diff --git a/luaj-2.0.3/examples/lua/hyperbolicapp.lua b/luaj-2.0.3/examples/lua/hyperbolicapp.lua new file mode 100644 index 0000000000..ea10389af9 --- /dev/null +++ b/luaj-2.0.3/examples/lua/hyperbolicapp.lua @@ -0,0 +1,19 @@ +-- Sample luaj code to try loading and executing the 'hyperbolic' sample library +-- +-- The sample library source is in examples/jse/hyperbolic.java. +-- For this sample to work, that source must be compiled, and the class must +-- be on the class path. +-- +-- First load the library via require(). This will call the public constructor +-- for the class named 'hyperbolic' if it exists, and then initialize the +-- library by invoking LuaValue.call('hyperbolic') on that instance +require 'hyperbolic' + +-- Test that the table is in the globals, and the functions exist. +print('hyperbolic', hyperbolic) +print('hyperbolic.sinh', hyperbolic.sinh) +print('hyperbolic.cosh', hyperbolic.cosh) + +-- Try exercising the functions. +print('sinh(0.5)', hyperbolic.sinh(0.5)) +print('cosh(0.5)', hyperbolic.cosh(0.5)) diff --git a/luaj-2.0.3/examples/lua/logo.gif b/luaj-2.0.3/examples/lua/logo.gif new file mode 100644 index 0000000000000000000000000000000000000000..193e69208494ed9272f4f0f10f275f3a65373d51 GIT binary patch literal 2694 zcmV;13VHQMNk%w1VSoUD0K@;M3G?CkaA0;@PYLMYA*0%^fGD=K2B20?&8 z$e&1|B9Y+pT67U38W02se=igb4*&xl0{{;O4F_>35DbP0HyU+kYA^v09;K$I0~rmM z8YFx@dIc~C1^}nGrX3prR00JG5K0TOD;EwM1Gu*U7Ohaf3JY*aYzhU5CkY(3%BC3? zPzwvrOA!PN3nU2!1`Y`&7Z%*z85EaDeIpkbxepw?BMxlq=D|P`Ph2i>P}TuM19AcQ zF?4XmjDm!5k`Z)BNS?9>mWZ5NfUSx~f*msdyc01>83!VTIN1_P@ytE&7FaG-$!42=dn>HsOy0}PZ7Y;|EE z>Ma9ADO^2e&<6oxG4L3}U~7V3zsmjs9)Q6CxEBrF-l``;?x_cM8Q_gU!NG$LfIX1i zOjdI#&Yk~uc;JBO2b>plDmFl7pD6%6&dGE^=0Ju4fH`aK;Mp_p-=BB$_M0lCin)qS zSs0N3Y6l(&7|ecg00ZXTr#kxv4&3+l;T|v;KM~+$@&Q>tG)VS*hk$8{GF;cq-MjbS z^?82=|1AabDWPfGqzBGbhKeGfp$%X`DAvOVUP#~1~}=~20BQPh6@^a*kG7B zj)@Cq4-8U*0~QiAz)CkDKvD~Fei>Yji0%YH1`Y&p0ZkVK;6Mi4{5HW*CM0lMa?2ed zfSlMRTIVtuI67lx&f$6F2mw$U6$Yji;bnKCis``s8$1Mq1|Dg4VhR^{6&56tSTNoY zVPx=St+kedfr~P<@XM+*Q~`t%0rB*ib1rzYpux*TG@z}~GaCREE(1KU0S65Pu#_`M9S}eR92{)keiOWlf*(Z` zO*M(P_EyRy4IBnTuvRmDsT5Mb-DG#THel`w2PlY{k3a~3z|bXt+HteL?Xp7vOg9}w z1q{H4LINfFogZ)B4(`JLLLg$+^9co1{KCa7DBGat3u@-m4iq@&+XU3k$np#jq@#ic z>~;S5%mW;Y1H@2vHbAT=)FFcgT&mDF)5F*KF%R+X2V&YQn8A1ozUaB{2d*1l{mi${ zeuKE#-OeUX5k$`ezZ}oWpv<1Riv#9T_V zc)$e7{Gz3PNu)cbpl=RZqX^olOqLweo2Hmj0LB@s|3LGH+d~`*wy-*Dq9Bi-W92s8 zvdnINAesd^K(9>kfR#|-F&Xj+J{cs)6%H^=nCL9H~iJ>QDdy zM5PerDMtU70yj-32eUd9Z*;oShnC`^xF{Jrx<(YBKJ}!u`ql3UaKxE>AW3S>Vk@Hp z)u!TtG|VG`RSQy5QyK)7UQHy3m>N{4vQ?e$|W^Z%~0jsi0_cB`iS`n*D9j*2NbDE>k#v)7C&f4{& z06D;rdUgh@E6;$9NLMUHngt&rasxJXv zJLlZgF;(UPl{ZigB%7QzgagEk!+0#kpHNV+l6L9@1`w@T+gA$c8X*iDSeAQP5X}~q zpgMOQC|pXAJsls{e=8n>1Uh=;u;vT^j^w5?2;)c}?wCxI?Ll+^Jc2NQwSc6wQ>Vt8 z+ZE6hu7vd6?{3P(GzV!V%JmhdR$#^(Y{|DJn4X=56ILMpMXVz5657;uf(ZDR29GxX zLHX?SHk`^Wo5DHESu8*l7dHrZWmEv1cWW;CO>l+mlIH#7rm_!EU>=wOfC)EBga$09wLGpC4q)cOCrv*XyA1y(7^_%D*J~B z4I15OJwl{`X$%~G51TheSjiBK;01Flx|wFw!R$NHNwC8PSioQy0LxhzW`PDIU{yiC z#4x-n1De#}>r>d0Wi9FXPu?U40w@xosc>Nh%)1H}dHom`AbTl9J@bm+5a@GX0FVFJ z+_^WwmaKvM8TbMi!GD1{G@*oxu?+ahH$eny9|QsrVAj!RK^^wsLhEN=%tdO$>M>X( zP<;Of_QFF2>_Exs(18Hdg^vL4vitLQpSrsn!Nu5LfBXCY{{R?(0yuyJmk max then + return max, math.random(-10,-2) + end + return x, vx +end +animate = function() + x1,y1,x2,y2 = x1+1,y1+1,x2-1,y2-1 + x1,vx1 = advance(x1,vx1,640) + y1,vy1 = advance(y1,vy1,480) + x2,vx2 = advance(x2,vx2,640) + y2,vy2 = advance(y2,vy2,480) + xi,vxi = advance(xi,vxi,540) + yi,vyi = advance(yi,vyi,380) +end + +-- try loading the logo image from a couple locations +local imageio = luajava.bindClass("javax.imageio.ImageIO") +local file = luajava.bindClass("java.io.File") +local loadimage = function(path) + local s,i = pcall(imageio.read, imageio, luajava.new(file, path)) + return s and i +end +local logo = loadimage("logo.gif") or loadimage("examples/lua/logo.gif") + +-- the render step draws the scene +local g = image:getGraphics() +local bg = luajava.newInstance("java.awt.Color", 0x22112244, true); +local fg = luajava.newInstance("java.awt.Color", 0xffaa33); +render = function() + g:setColor(bg) + g:fillRect(0,0,640,480) + if logo then g:drawImage(logo,xi,yi) end + g:setColor(fg) + g:drawLine(x1,y1,x2,y2) +end + +-- add mouse listeners for specific mouse events +label:addMouseListener(luajava.createProxy("java.awt.event.MouseListener", { + mousePressed = function(e) + --print('mousePressed', e:getX(), e:getY(), e) + x1,y1 = e:getX(),e:getY() + end, + -- mouseClicked = function(e) end, + -- mouseEntered = function(e) end, + -- mouseExited = function(e) end, + -- mouseReleased = function(e) end, +})) +label:addMouseMotionListener(luajava.createProxy("java.awt.event.MouseMotionListener", { + mouseDragged = function(e) + --print('mouseDragged', e:getX(), e:getY(), e) + x2,y2 = e:getX(),e:getY() + end, + -- mouseMoved= function(e) end, +})) + +-- add key listeners +frame:addKeyListener(luajava.createProxy("java.awt.event.KeyListener", { + keyPressed = function(e) + local id, code, char, text = e:getID(), e:getKeyCode(), e:getKeyChar(), e:getKeyText(e:getKeyCode()) + print('key id, code, char, text, pcall(string.char,char)', id, code, char, text, pcall(string.char,char)) + end, + -- keyReleased = function(e) end, + -- keyTyped = function(e) end, +})) + +-- use the window listener to kick off animation +frame:addWindowListener(luajava.createProxy("java.awt.event.WindowListener", { + windowOpened = function(e) + swingUtilities:invokeLater(tick) + end, + -- windowActivated = function(e) end, + -- windowClosed = function(e) end, + -- windowClosing = function(e) end, + -- windowDeactivated = function(e) end, + -- windowDeiconified = function(e) end, + -- windowIconified = function(e) end, +})) + +-- utility function to load an image from a file, for reference +local loadimage = function(filename) +end + +-- Set window visible last to start app. +frame:setVisible(true) diff --git a/luaj-2.0.3/names.csv b/luaj-2.0.3/names.csv new file mode 100644 index 0000000000..5c6b8f8f1a --- /dev/null +++ b/luaj-2.0.3/names.csv @@ -0,0 +1,89 @@ +LuaValue Consructors,,Return type,,,,,,,,,, +,valueOf(boolean),LuaBoolean,,,,,,,,,, +,valueOf(null),LuaNil,,,,,,,,,, +,valueOf(int) ,LuaInteger,,,,,,,,,, +,valueOf(double),LuaNumber,,,,,,,,,, +,valueOf(long),LuaNumber,,,,,,,,,, +,valueOf(String),LuaString,,,,,,,,,, +,tableOf(...),LuaTable,,,,,,,,,, +,listOf(LuaValue[]),LuaTable,,,,,,,,,, +,userdataOf(Object),LuaUserdata,,,,,,,,,, +,"uerdataOf(Object,Value)",LuaUserdata,,,,,,,,,, +,,,,,,,Arugment type,,,,, +,,,LuaBoolean,LuaClosure,LuaFunction,LuaDouble,LuaInteger,LuaNil,LuaString,LuaTable,LuaThread,LuaUserdata +Type Check Functions,,,,,,,,,,,, +,isboolean,boolean,TRUE,f,f,f,f,f,f,f,f,f +,isclosure,boolean,f,TRUE,f,f,f,f,f,f,f,f +,isfunction,boolean,f,TRUE,TRUE,f,f,f,f,f,f,f +,isint,boolean,f,f,f,f,TRUE,f,true | f,f,f,f +,isinttype,boolean,f,f,f,f,TRUE,f,f,f,f,f +,isnumber,boolean,f,f,f,TRUE,TRUE,f,true | f,f,f,f +,islong,boolean,f,f,f,true | f,TRUE,f,true | f,f,f,f +,isnil,boolean,f,f,f,f,f,TRUE,f,f,f,f +,isstring,boolean,f,f,f,true | f,TRUE,f,TRUE,f,f,f +,istable,boolean,f,f,f,f,f,f,f,TRUE,f,f +,isthread,boolean,f,f,f,f,f,f,f,f,TRUE,f +,isuserdata,boolean,f,f,f,f,f,f,f,f,f,TRUE +,isuserdata(Class c),boolean,f,f,f,f,f,f,f,f,f,true | f + + +Java Type Coercion Functions,,,,,,,,,,,, +,toboolean,boolean,this.v,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE +,tobyte,byte,0,0,0,0,this.v | 0,0,this.v | 0,0,0,0 +,tochar,char,0,0,0,0,this.v | 0,0,this.v | 0,0,0,0 +,todouble,double,0,0,0,this.v,this.v,0,this.v | 0,0,0,0 +,tofloat,float,0,0,0,this.v | 0,this.v,0,this.v | 0,0,0,0 +,toint,int,0,0,0,0,this.v,0,this.v | 0,0,0,0 +,tolong,long,0,0,0,0,this.v,0,this.v | 0,0,0,0 +,toshort,short,0,0,0,0,this.v | 0,0,this.v | 0,0,0,0 +,tojstring,String,"""true""|""false""","""closure: x""","""name""",(str) this.v,(str) this.v,"""nil""",this.v,"""table: x""","""thread: x""","""userdata: x""" +,touserdata,Object,null,null,null,null,null,null,null,null,this,this.instance + +,,,LuaBoolean,LuaClosure,LuaFunction,LuaDouble,LuaInteger,LuaNil,LuaString,LuaTable,LuaThread,LuaUserdata +Optional Argument Conversion Functions,,,,,,,,,,,, +,optboolean,boolean,this,e,e,e,e,defval,e,e,e,e +,optclosure,LuaClosure,n,this,e,e,e,defval,e,e,e,e +,optdouble,double,e,e,e,this,this,defval,this | e,e,e,e +,optfunction,LuaFunction,n,this,this,e,e,defval,e,e,e,e +,optint,int,e,e,e,(int) this,this,defval,this | e,e,e,e +,optinteger,LuaInteger,e,e,e,(int) this,this,defval,this | e,e,e,e +,optlong,long,e,e,e,(long) this,this,defval,this | e,e,e,e +,optnumber,LuaNumber,e,e,e,this,this,defval,this | e,e,e,e +,optjstring,String,e,e,e,(str) this.v,(str) this.v,defval,this,e,e,e +,optstring,LuaString,e,e,e,(str) this.v,(str) this.v,defval,this,e,e,e +,opttable,LuaTable,e,e,e,e,e,defval,e,this,e,e +,optthread,LuaThread,e,e,e,e,e,defval,e,e,this,n +,optuserdata,Object,e,e,e,e,e,defval,e,e,e,instance +,optuserdata(Class c),Object,e,e,e,e,e,defval,e,e,e,instance | e + +Required Argument Conversion Functions,,,,,,,,,,,, +,checkboolean,boolean,this,e,e,e,e,e,e,e,e,e +,checkclosure,LuaClosure,e,this,e,e,e,e,e,e,e,e +,checkdouble,double,e,e,e,this,this,e,e,e,e,e +,checkfunction,LuaFunction,e,this,this,e,e,e,e,e,e,e +,checkint,int,e,e,e,this | e,this,e,e,e,e,e +,checkinteger,LuaInteger,e,e,e,e,this,e,e,e,e,e +,checklong,LuaNumber,e,e,e,this | e,this,e,e,e,e,e +,checknumber,LuaNumber,e,e,e,this,this,e,e,e,e,e +,checkjstring,String,e,e,e,(str) this.v,(str) this.v,e,(str) this.v,e,e,e +,checkstring,LuaString,e,e,e,(str) this.v,(str) this.v,e,this,e,e,e +,checktable,LuaTable,e,e,e,e,e,e,e,this,e,e +,checkthread,LuaThread,e,e,e,e,e,e,e,e,this,e +,checkuserdata,Object,e,e,e,e,e,e,e,e,e,instance +,checkuserdata(Class c),Object,e,e,e,e,e,e,e,e,e,instance | e +,checkvalue,LuaValue,this,this,this,this,this,e,this,this,this,this + +,,,LuaBoolean,LuaClosure,LuaFunction,LuaDouble,LuaInteger,LuaNil,LuaString,LuaTable,LuaThread,LuaUserdata +Lua Language Operations,,,,,,,,,,,, +,type,int,TBOOLEAN,TFUNCTION,TFUNCTION,TNUMBER,TNUMBER,TNIL,TSTRING,TTABLE,TTHREAD,TUSERDATA +,typename,string,"""boolean""","""function""","""function""","""number""","""number""","""nil""","""string""","""table""","""thread""","""userdata""" +,len,LuaInteger,e,e,e,e,e,e,#v,#v,e,e +,length,int,e,e,e,e,e,e,#v,#v,e,e +,getmetatable,LuaValue,static,static,static,static,static,static,static,instance,static ,instance +,setmetatable,LuaValue,e,e,e,e,e,e,e,instance,e,instance +,getfenv,LuaTable,e,instance,instance,e,e,e,e,e,instance,e +,setfenv,LuaFunction,e,instance,instance,e,e,e,e,e,instance,e +,call,LuaValue,__call,call,call,__call,__call,__call,__call,__call,__call,__call +,invoke,Varargs,__call,call,call,__call,__call,__call,__call,__call,__call,__call +,get,LuaValue,__index,__index,__index,__index,__index,__index,__index,get,__index,__index +,set,LuaValue,__newindex,__newindex,__newindex,__newindex,__newindex,__newindex,__newindex,set,__newindex,__newindex diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/Buffer.java b/luaj-2.0.3/src/core/org/luaj/vm2/Buffer.java new file mode 100644 index 0000000000..1789bc39de --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/Buffer.java @@ -0,0 +1,260 @@ +/******************************************************************************* + * Copyright (c) 2009 Luaj.org. 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. + ******************************************************************************/ +package org.luaj.vm2; + + +/** + * String buffer for use in string library methods, optimized for production + * of StrValue instances. + *

+ * The buffer can begin initially as a wrapped {@link LuaValue} + * and only when concatenation actually occurs are the bytes first copied. + *

+ * To convert back to a {@link LuaValue} again, + * the function {@link Buffer#value()} is used. + * @see LuaValue + * @see LuaValue#buffer() + * @see LuaString + */ +public final class Buffer { + + /** Default capacity for a buffer: 64 */ + private static final int DEFAULT_CAPACITY = 64; + + /** Shared static array with no bytes */ + private static final byte[] NOBYTES = {}; + + /** Bytes in this buffer */ + private byte[] bytes; + + /** Length of this buffer */ + private int length; + + /** Offset into the byte array */ + private int offset; + + /** Value of this buffer, when not represented in bytes */ + private LuaValue value; + + /** + * Create buffer with default capacity + * @see #DEFAULT_CAPACITY + */ + public Buffer() { + this(DEFAULT_CAPACITY); + } + + /** + * Create buffer with specified initial capacity + * @param initialCapacity the initial capacity + */ + public Buffer( int initialCapacity ) { + bytes = new byte[ initialCapacity ]; + length = 0; + offset = 0; + value = null; + } + + /** + * Create buffer with specified initial value + * @param value the initial value + */ + public Buffer(LuaValue value) { + bytes = NOBYTES; + length = offset = 0; + this.value = value; + } + + /** + * Get buffer contents as a {@link LuaValue} + * @return value as a {@link LuaValue}, converting as necessary + */ + public LuaValue value() { + return value != null? value: this.tostring(); + } + + /** + * Set buffer contents as a {@link LuaValue} + * @param value value to set + */ + public Buffer setvalue(LuaValue value) { + bytes = NOBYTES; + offset = length = 0; + this.value = value; + return this; + } + + /** + * Convert the buffer to a {@link LuaString} + * @return the value as a {@link LuaString} + */ + public final LuaString tostring() { + realloc( length, 0 ); + return LuaString.valueOf( bytes, offset, length ); + } + + /** + * Convert the buffer to a Java String + * @return the value as a Java String + */ + public String tojstring() { + return value().tojstring(); + } + + /** + * Convert the buffer to a Java String + * @return the value as a Java String + */ + public String toString() { + return tojstring(); + } + + /** + * Append a single byte to the buffer. + * @return {@code this} to allow call chaining + */ + public final Buffer append( byte b ) { + makeroom( 0, 1 ); + bytes[ offset + length++ ] = b; + return this; + } + + /** + * Append a {@link LuaValue} to the buffer. + * @return {@code this} to allow call chaining + */ + public final Buffer append( LuaValue val ) { + append( val.strvalue() ); + return this; + } + + /** + * Append a {@link LuaString} to the buffer. + * @return {@code this} to allow call chaining + */ + public final Buffer append( LuaString str ) { + final int n = str.m_length; + makeroom( 0, n ); + str.copyInto( 0, bytes, offset + length, n ); + length += n; + return this; + } + + /** + * Append a Java String to the buffer. + * The Java string will be converted to bytes using the UTF8 encoding. + * @return {@code this} to allow call chaining + * @see LuaString#encodeToUtf8(char[], byte[], int) + */ + public final Buffer append( String str ) { + char[] chars = str.toCharArray(); + /* DAN200 START */ + /* + final int n = LuaString.lengthAsUtf8( chars ); + makeroom( 0, n ); + LuaString.encodeToUtf8( chars, bytes, offset + length ); + length += n; + */ + makeroom( 0, chars.length ); + for( int i=0; i + * The {@link LuaNumber} will be converted to a string before concatenating. + * @param lhs the left-hand-side value onto which we are concatenating {@code this} + * @return {@link Buffer} for use in call chaining. + */ + public Buffer concatTo(LuaNumber lhs) { + return value!=null&&!value.isstring()? setvalue(lhs.concat(value)): prepend(lhs.strvalue()); + } + + /** Concatenate bytes from a {@link LuaString} onto the front of this buffer + * @param s the left-hand-side value which we will concatenate onto the front of {@code this} + * @return {@link Buffer} for use in call chaining. + */ + public Buffer prepend(LuaString s) { + int n = s.m_length; + makeroom( n, 0 ); + System.arraycopy( s.m_bytes, s.m_offset, bytes, offset-n, n ); + offset -= n; + length += n; + value = null; + return this; + } + + /** Ensure there is enough room before and after the bytes. + * @param nbefore number of unused bytes which must precede the data after this completes + * @param nafter number of unused bytes which must follow the data after this completes + */ + public final void makeroom( int nbefore, int nafter ) { + if ( value != null ) { + LuaString s = value.strvalue(); + value = null; + length = s.m_length; + offset = nbefore; + bytes = new byte[nbefore+length+nafter]; + System.arraycopy(s.m_bytes, s.m_offset, bytes, offset, length); + } else if ( offset+length+nafter > bytes.length || offset +* The {@link LoadState} class exposes one main function, +* namely {@link #load(InputStream, String, LuaValue)}, +* to be used to load code from a particular input stream. +*

+* A simple pattern for loading and executing code is +*

 {@code
+* LuaValue _G = JsePlatform.standardGlobals();
+* LoadState.load( new FileInputStream("main.lua"), "main.lua", _G ).call();
+* } 
+* This should work regardless of which {@link LuaCompiler} +* has been installed. +*

+* +* Prior to loading code, a compiler should be installed. +*

+* By default, when using {@link JsePlatform} or {@JmePlatform} +* to construct globals, the {@link LuaC} compiler is installed. +*

+* To override the default compiler with, say, the {@link LuaJC} +* lua-to-java bytecode compiler, install it before loading, +* for example: +*

 {@code
+* LuaValue _G = JsePlatform.standardGlobals();
+* LuaJC.install();
+* LoadState.load( new FileInputStream("main.lua"), "main.lua", _G ).call();
+* } 
+* +* @see LuaCompiler +* @see LuaClosure +* @see LuaFunction +* @see LoadState#compiler +* @see LoadState#load(InputStream, String, LuaValue) +* @see LuaC +* @see LuaJC +*/ +public class LoadState { + + /** format corresponding to non-number-patched lua, all numbers are floats or doubles */ + public static final int NUMBER_FORMAT_FLOATS_OR_DOUBLES = 0; + + /** format corresponding to non-number-patched lua, all numbers are ints */ + public static final int NUMBER_FORMAT_INTS_ONLY = 1; + + /** format corresponding to number-patched lua, all numbers are 32-bit (4 byte) ints */ + public static final int NUMBER_FORMAT_NUM_PATCH_INT32 = 4; + + // type constants + public static final int LUA_TINT = (-2); + public static final int LUA_TNONE = (-1); + public static final int LUA_TNIL = 0; + public static final int LUA_TBOOLEAN = 1; + public static final int LUA_TLIGHTUSERDATA = 2; + public static final int LUA_TNUMBER = 3; + public static final int LUA_TSTRING = 4; + public static final int LUA_TTABLE = 5; + public static final int LUA_TFUNCTION = 6; + public static final int LUA_TUSERDATA = 7; + public static final int LUA_TTHREAD = 8; + public static final int LUA_TVALUE = 9; + + /** Interface for the compiler, if it is installed. + *

+ * See the {@link LuaClosure} documentation for examples of how to use the compiler. + * @see LuaClosure + * @see #load(InputStream, String, LuaValue) + * */ + public interface LuaCompiler { + + /** Load into a Closure or LuaFunction from a Stream and initializes the environment + * @throws IOException */ + public LuaFunction load(InputStream stream, String filename, LuaValue env) throws IOException; + } + + /** Compiler instance, if installed */ + public static LuaCompiler compiler = null; + + /** Signature byte indicating the file is a compiled binary chunk */ + private static final byte[] LUA_SIGNATURE = { '\033', 'L', 'u', 'a' }; + + /** Name for compiled chunks */ + public static final String SOURCE_BINARY_STRING = "binary string"; + + + /** for header of binary files -- this is Lua 5.1 */ + public static final int LUAC_VERSION = 0x51; + + /** for header of binary files -- this is the official format */ + public static final int LUAC_FORMAT = 0; + + /** size of header of binary files */ + public static final int LUAC_HEADERSIZE = 12; + + // values read from the header + private int luacVersion; + private int luacFormat; + private boolean luacLittleEndian; + private int luacSizeofInt; + private int luacSizeofSizeT; + private int luacSizeofInstruction; + private int luacSizeofLuaNumber; + private int luacNumberFormat; + + /** input stream from which we are loading */ + public final DataInputStream is; + + /** Name of what is being loaded? */ + String name; + + private static final LuaValue[] NOVALUES = {}; + private static final Prototype[] NOPROTOS = {}; + private static final LocVars[] NOLOCVARS = {}; + private static final LuaString[] NOSTRVALUES = {}; + private static final int[] NOINTS = {}; + + /** Read buffer */ + private byte[] buf = new byte[512]; + + + /** Load a 4-byte int value from the input stream + * @return the int value laoded. + **/ + int loadInt() throws IOException { + is.readFully(buf,0,4); + return luacLittleEndian? + (buf[3] << 24) | ((0xff & buf[2]) << 16) | ((0xff & buf[1]) << 8) | (0xff & buf[0]): + (buf[0] << 24) | ((0xff & buf[1]) << 16) | ((0xff & buf[2]) << 8) | (0xff & buf[3]); + } + + /** Load an array of int values from the input stream + * @return the array of int values laoded. + **/ + int[] loadIntArray() throws IOException { + int n = loadInt(); + if ( n == 0 ) + return NOINTS; + + // read all data at once + int m = n << 2; + if ( buf.length < m ) + buf = new byte[m]; + is.readFully(buf,0,m); + int[] array = new int[n]; + for ( int i=0, j=0; i> 52) & 0x7ffL) - 1023; + + if ( e >= 0 && e < 31 ) { + long f = bits & 0xFFFFFFFFFFFFFL; + int shift = 52 - e; + long intPrecMask = ( 1L << shift ) - 1; + if ( ( f & intPrecMask ) == 0 ) { + int intValue = (int)( f >> shift ) | ( 1 << e ); + return LuaInteger.valueOf( ( ( bits >> 63 ) != 0 ) ? -intValue : intValue ); + } + } + + return LuaValue.valueOf( Double.longBitsToDouble(bits) ); + } + + /** + * Load a number from a binary chunk + * @return the {@link LuaValue} loaded + * @throws IOException if an i/o exception occurs + */ + LuaValue loadNumber() throws IOException { + if ( luacNumberFormat == NUMBER_FORMAT_INTS_ONLY ) { + return LuaInteger.valueOf( loadInt() ); + } else { + return longBitsToLuaNumber( loadInt64() ); + } + } + + /** + * Load a list of constants from a binary chunk + * @param f the function prototype + * @throws IOException if an i/o exception occurs + */ + void loadConstants(Prototype f) throws IOException { + int n = loadInt(); + LuaValue[] values = n>0? new LuaValue[n]: NOVALUES; + for ( int i=0; i0? new Prototype[n]: NOPROTOS; + for ( int i=0; i0? new LocVars[n]: NOLOCVARS; + for ( int i=0; i0? new LuaString[n]: NOSTRVALUES; + for ( int i=0; i + * This is a direct translation of C lua distribution header file constants + * for bytecode creation and processing. + */ +public class Lua { + /** version is supplied by ant build task */ + public static final String _VERSION = "Luaj 0.0"; + + /** use return values from previous op */ + public static final int LUA_MULTRET = -1; + + /** masks for new-style vararg */ + public static final int VARARG_HASARG = 1; + public static final int VARARG_ISVARARG = 2; + public static final int VARARG_NEEDSARG = 4; + + // from lopcodes.h + + /*=========================================================================== + We assume that instructions are unsigned numbers. + All instructions have an opcode in the first 6 bits. + Instructions can have the following fields: + `A' : 8 bits + `B' : 9 bits + `C' : 9 bits + `Bx' : 18 bits (`B' and `C' together) + `sBx' : signed Bx + + A signed argument is represented in excess K; that is, the number + value is the unsigned value minus K. K is exactly the maximum value + for that argument (so that -max is represented by 0, and +max is + represented by 2*max), which is half the maximum for the corresponding + unsigned argument. + ===========================================================================*/ + + + /* basic instruction format */ + public static final int iABC = 0; + public static final int iABx = 1; + public static final int iAsBx = 2; + + + /* + ** size and position of opcode arguments. + */ + public static final int SIZE_C = 9; + public static final int SIZE_B = 9; + public static final int SIZE_Bx = (SIZE_C + SIZE_B); + public static final int SIZE_A = 8; + + public static final int SIZE_OP = 6; + + public static final int POS_OP = 0; + public static final int POS_A = (POS_OP + SIZE_OP); + public static final int POS_C = (POS_A + SIZE_A); + public static final int POS_B = (POS_C + SIZE_C); + public static final int POS_Bx = POS_C; + + + public static final int MAX_OP = ((1<>1); /* `sBx' is signed */ + + public static final int MASK_OP = ((1<> POS_OP) & MAX_OP; + } + + public static int GETARG_A(int i) { + return (i >> POS_A) & MAXARG_A; + } + + public static int GETARG_B(int i) { + return (i >> POS_B) & MAXARG_B; + } + + public static int GETARG_C(int i) { + return (i >> POS_C) & MAXARG_C; + } + + public static int GETARG_Bx(int i) { + return (i >> POS_Bx) & MAXARG_Bx; + } + + public static int GETARG_sBx(int i) { + return ((i >> POS_Bx) & MAXARG_Bx) - MAXARG_sBx; + } + + + /* + ** Macros to operate RK indices + */ + + /** this bit 1 means constant (0 means register) */ + public static final int BITRK = (1 << (SIZE_B - 1)); + + /** test whether value is a constant */ + public static boolean ISK(int x) { + return 0 != ((x) & BITRK); + } + + /** gets the index of the constant */ + public static int INDEXK(int r) { + return ((int)(r) & ~BITRK); + } + + public static final int MAXINDEXRK = (BITRK - 1); + + /** code a constant index as a RK value */ + public static int RKASK(int x) { + return ((x) | BITRK); + } + + + /** + ** invalid register that fits in 8 bits + */ + public static final int NO_REG = MAXARG_A; + + + /* + ** R(x) - register + ** Kst(x) - constant (in constant table) + ** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x) + */ + + + /* + ** grep "ORDER OP" if you change these enums + */ + + /*---------------------------------------------------------------------- + name args description + ------------------------------------------------------------------------*/ + public static final int OP_MOVE = 0;/* A B R(A) := R(B) */ + public static final int OP_LOADK = 1;/* A Bx R(A) := Kst(Bx) */ + public static final int OP_LOADBOOL = 2;/* A B C R(A) := (Bool)B; if (C) pc++ */ + public static final int OP_LOADNIL = 3; /* A B R(A) := ... := R(B) := nil */ + public static final int OP_GETUPVAL = 4; /* A B R(A) := UpValue[B] */ + + public static final int OP_GETGLOBAL = 5; /* A Bx R(A) := Gbl[Kst(Bx)] */ + public static final int OP_GETTABLE = 6; /* A B C R(A) := R(B)[RK(C)] */ + + public static final int OP_SETGLOBAL = 7; /* A Bx Gbl[Kst(Bx)] := R(A) */ + public static final int OP_SETUPVAL = 8; /* A B UpValue[B] := R(A) */ + public static final int OP_SETTABLE = 9; /* A B C R(A)[RK(B)] := RK(C) */ + + public static final int OP_NEWTABLE = 10; /* A B C R(A) := {} (size = B,C) */ + + public static final int OP_SELF = 11; /* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */ + + public static final int OP_ADD = 12; /* A B C R(A) := RK(B) + RK(C) */ + public static final int OP_SUB = 13; /* A B C R(A) := RK(B) - RK(C) */ + public static final int OP_MUL = 14; /* A B C R(A) := RK(B) * RK(C) */ + public static final int OP_DIV = 15; /* A B C R(A) := RK(B) / RK(C) */ + public static final int OP_MOD = 16; /* A B C R(A) := RK(B) % RK(C) */ + public static final int OP_POW = 17; /* A B C R(A) := RK(B) ^ RK(C) */ + public static final int OP_UNM = 18; /* A B R(A) := -R(B) */ + public static final int OP_NOT = 19; /* A B R(A) := not R(B) */ + public static final int OP_LEN = 20; /* A B R(A) := length of R(B) */ + + public static final int OP_CONCAT = 21; /* A B C R(A) := R(B).. ... ..R(C) */ + + public static final int OP_JMP = 22; /* sBx pc+=sBx */ + + public static final int OP_EQ = 23; /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ + public static final int OP_LT = 24; /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ + public static final int OP_LE = 25; /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ + + public static final int OP_TEST = 26; /* A C if not (R(A) <=> C) then pc++ */ + public static final int OP_TESTSET = 27; /* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ + + public static final int OP_CALL = 28; /* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ + public static final int OP_TAILCALL = 29; /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ + public static final int OP_RETURN = 30; /* A B return R(A), ... ,R(A+B-2) (see note) */ + + public static final int OP_FORLOOP = 31; /* A sBx R(A)+=R(A+2); + if R(A) =) R(A)*/ + public static final int OP_CLOSURE = 36; /* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ + public static final int OP_VARARG = 37; /* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ + + public static final int NUM_OPCODES = OP_VARARG + 1; + + /* pseudo-opcodes used in parsing only. */ + public static final int OP_GT = 63; // > + public static final int OP_GE = 62; // >= + public static final int OP_NEQ = 61; // ~= + public static final int OP_AND = 60; // and + public static final int OP_OR = 59; // or + + /*=========================================================================== + Notes: + (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, + and can be 0: OP_CALL then sets `top' to last_result+1, so + next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. + + (*) In OP_VARARG, if (B == 0) then use actual number of varargs and + set top (like in OP_CALL with C == 0). + + (*) In OP_RETURN, if (B == 0) then return up to `top' + + (*) In OP_SETLIST, if (B == 0) then B = `top'; + if (C == 0) then next `instruction' is real C + + (*) For comparisons, A specifies what condition the test should accept + (true or false). + + (*) All `skips' (pc++) assume that next instruction is a jump + ===========================================================================*/ + + + /* + ** masks for instruction properties. The format is: + ** bits 0-1: op mode + ** bits 2-3: C arg mode + ** bits 4-5: B arg mode + ** bit 6: instruction set register A + ** bit 7: operator is a test + */ + + public static final int OpArgN = 0; /* argument is not used */ + public static final int OpArgU = 1; /* argument is used */ + public static final int OpArgR = 2; /* argument is a register or a jump offset */ + public static final int OpArgK = 3; /* argument is a constant or register/constant */ + + public static final int[] luaP_opmodes = { + /* T A B C mode opcode */ + (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_MOVE */ + (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgN<<2) | (iABx), /* OP_LOADK */ + (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_LOADBOOL */ + (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_LOADNIL */ + (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_GETUPVAL */ + (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgN<<2) | (iABx), /* OP_GETGLOBAL */ + (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgK<<2) | (iABC), /* OP_GETTABLE */ + (0<<7) | (0<<6) | (OpArgK<<4) | (OpArgN<<2) | (iABx), /* OP_SETGLOBAL */ + (0<<7) | (0<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_SETUPVAL */ + (0<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_SETTABLE */ + (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_NEWTABLE */ + (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgK<<2) | (iABC), /* OP_SELF */ + (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_ADD */ + (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_SUB */ + (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_MUL */ + (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_DIV */ + (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_MOD */ + (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_POW */ + (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_UNM */ + (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_NOT */ + (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_LEN */ + (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgR<<2) | (iABC), /* OP_CONCAT */ + (0<<7) | (0<<6) | (OpArgR<<4) | (OpArgN<<2) | (iAsBx), /* OP_JMP */ + (1<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_EQ */ + (1<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_LT */ + (1<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_LE */ + (1<<7) | (1<<6) | (OpArgR<<4) | (OpArgU<<2) | (iABC), /* OP_TEST */ + (1<<7) | (1<<6) | (OpArgR<<4) | (OpArgU<<2) | (iABC), /* OP_TESTSET */ + (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_CALL */ + (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_TAILCALL */ + (0<<7) | (0<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_RETURN */ + (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iAsBx), /* OP_FORLOOP */ + (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iAsBx), /* OP_FORPREP */ + (1<<7) | (0<<6) | (OpArgN<<4) | (OpArgU<<2) | (iABC), /* OP_TFORLOOP */ + (0<<7) | (0<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_SETLIST */ + (0<<7) | (0<<6) | (OpArgN<<4) | (OpArgN<<2) | (iABC), /* OP_CLOSE */ + (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABx), /* OP_CLOSURE */ + (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_VARARG */ + }; + + public static int getOpMode(int m) { + return luaP_opmodes[m] & 3; + } + public static int getBMode(int m) { + return (luaP_opmodes[m] >> 4) & 3; + } + public static int getCMode(int m) { + return (luaP_opmodes[m] >> 2) & 3; + } + public static boolean testAMode(int m) { + return 0 != (luaP_opmodes[m] & (1 << 6)); + } + public static boolean testTMode(int m) { + return 0 != (luaP_opmodes[m] & (1 << 7)); + } + + /* number of list items to accumulate before a SETLIST instruction */ + public static final int LFIELDS_PER_FLUSH = 50; + +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/LuaBoolean.java b/luaj-2.0.3/src/core/org/luaj/vm2/LuaBoolean.java new file mode 100644 index 0000000000..4192174154 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/LuaBoolean.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2009-2011 Luaj.org. 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. + ******************************************************************************/ +package org.luaj.vm2; + +/** + * Extension of {@link LuaValue} which can hold a Java boolean as its value. + *

+ * These instance are not instantiated directly by clients. + * Instead, there are exactly twon instances of this class, + * {@link LuaValue#TRUE} and {@link LuaValue#FALSE} + * representing the lua values {@code true} and {@link false}. + * The function {@link LuaValue#valueOf(boolean)} will always + * return one of these two values. + *

+ * Any {@link LuaValue} can be converted to its equivalent + * boolean representation using {@link LuaValue#toboolean()} + *

+ * @see LuaValue + * @see LuaValue#valueOf(boolean) + * @see LuaValue#TRUE + * @see LuaValue#FALSE + */ +public final class LuaBoolean extends LuaValue { + + /** The singleton instance representing lua {@code true} */ + static final LuaBoolean _TRUE = new LuaBoolean(true); + + /** The singleton instance representing lua {@code false} */ + static final LuaBoolean _FALSE = new LuaBoolean(false); + + /** Shared static metatable for boolean values represented in lua. */ + public static LuaValue s_metatable; + + /** The value of the boolean */ + public final boolean v; + + LuaBoolean(boolean b) { + this.v = b; + } + + public int type() { + return LuaValue.TBOOLEAN; + } + + public String typename() { + return "boolean"; + } + + public boolean isboolean() { + return true; + } + + public LuaValue not() { + return v ? FALSE : LuaValue.TRUE; + } + + /** + * Return the boolean value for this boolean + * @return value as a Java boolean + */ + public boolean booleanValue() { + return v; + } + + public boolean toboolean() { + return v; + } + + public String tojstring() { + return v ? "true" : "false"; + } + + public boolean optboolean(boolean defval) { + return this.v; + } + + public boolean checkboolean() { + return v; + } + + public LuaValue getmetatable() { + return s_metatable; + } +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/LuaClosure.java b/luaj-2.0.3/src/core/org/luaj/vm2/LuaClosure.java new file mode 100644 index 0000000000..8deb56b47d --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/LuaClosure.java @@ -0,0 +1,521 @@ +/******************************************************************************* +* Copyright (c) 2009 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import org.luaj.vm2.LoadState.LuaCompiler; +import org.luaj.vm2.compiler.LuaC; +import org.luaj.vm2.lib.DebugLib; + +/** + * Extension of {@link LuaFunction} which executes lua bytecode. + *

+ * A {@link LuaClosure} is a combination of a {@link Prototype} + * and a {@link LuaValue} to use as an environment for execution. + *

+ * There are three main ways {@link LuaClosure} instances are created: + *

    + *
  • Construct an instance using {@link #LuaClosure(Prototype, LuaValue)}
  • + *
  • Construct it indirectly by loading a chunk via {@link LuaCompiler#load(java.io.InputStream, String, LuaValue)} + *
  • Execute the lua bytecode {@link Lua#OP_CLOSURE} as part of bytecode processing + *
+ *

+ * To construct it directly, the {@link Prototype} is typically created via a compiler such as {@link LuaC}: + *

 {@code
+ * InputStream is = new ByteArrayInputStream("print('hello,world').getBytes());
+ * Prototype p = LuaC.instance.compile(is, "script");
+ * LuaValue _G = JsePlatform.standardGlobals()
+ * LuaClosure f = new LuaClosure(p, _G);
+ * }
+ *

+ * To construct it indirectly, the {@link LuaC} compiler may be used, + * which implements the {@link LuaCompiler} interface: + *

 {@code
+ * LuaFunction f = LuaC.instance.load(is, "script", _G);
+ * }
+ *

+ * Typically, a closure that has just been loaded needs to be initialized by executing it, + * and its return value can be saved if needed: + *

 {@code
+ * LuaValue r = f.call();
+ * _G.set( "mypkg", r ) 
+ * }
+ *

+ * In the preceding, the loaded value is typed as {@link LuaFunction} + * to allow for the possibility of other compilers such as {@link LuaJC} + * producing {@link LuaFunction} directly without + * creating a {@link Prototype} or {@link LuaClosure}. + *

+ * Since a {@link LuaClosure} is a {@link LuaFunction} which is a {@link LuaValue}, + * all the value operations can be used directly such as: + *

    + *
  • {@link LuaValue#setfenv(LuaValue)}
  • + *
  • {@link LuaValue#call()}
  • + *
  • {@link LuaValue#call(LuaValue)}
  • + *
  • {@link LuaValue#invoke()}
  • + *
  • {@link LuaValue#invoke(Varargs)}
  • + *
  • {@link LuaValue#method(String)}
  • + *
  • {@link LuaValue#method(String,LuaValue)}
  • + *
  • {@link LuaValue#invokemethod(String)}
  • + *
  • {@link LuaValue#invokemethod(String,Varargs)}
  • + *
  • ...
  • + *
+ * @see LuaValue + * @see LuaFunction + * @see LuaValue#isclosure() + * @see LuaValue#checkclosure() + * @see LuaValue#optclosure(LuaClosure) + * @see LoadState + * @see LoadState#compiler + */ +public class LuaClosure extends LuaFunction { + private static final UpValue[] NOUPVALUES = new UpValue[0]; + + public final Prototype p; + public final UpValue[] upValues; + + LuaClosure() { + p = null; + upValues = null; + } + /** Supply the initial environment */ + public LuaClosure(Prototype p, LuaValue env) { + super( env ); + this.p = p; + this.upValues = p.nups>0? new UpValue[p.nups]: NOUPVALUES; + } + + protected LuaClosure(int nupvalues, LuaValue env) { + super( env ); + this.p = null; + this.upValues = nupvalues>0? new UpValue[nupvalues]: NOUPVALUES; + } + + public boolean isclosure() { + return true; + } + + public LuaClosure optclosure(LuaClosure defval) { + return this; + } + + public LuaClosure checkclosure() { + return this; + } + + public LuaValue getmetatable() { + return s_metatable; + } + + public final LuaValue call() { + LuaValue[] stack = new LuaValue[p.maxstacksize]; + System.arraycopy(NILS, 0, stack, 0, p.maxstacksize); + return execute(stack,NONE).arg1(); + } + + public final LuaValue call(LuaValue arg) { + LuaValue[] stack = new LuaValue[p.maxstacksize]; + System.arraycopy(NILS, 0, stack, 0, p.maxstacksize); + switch ( p.numparams ) { + default: stack[0]=arg; return execute(stack,NONE).arg1(); + case 0: return execute(stack,arg).arg1(); + } + } + + public final LuaValue call(LuaValue arg1, LuaValue arg2) { + LuaValue[] stack = new LuaValue[p.maxstacksize]; + System.arraycopy(NILS, 0, stack, 0, p.maxstacksize); + switch ( p.numparams ) { + default: stack[0]=arg1; stack[1]=arg2; return execute(stack,NONE).arg1(); + case 1: stack[0]=arg1; return execute(stack,arg2).arg1(); + case 0: return execute(stack,p.is_vararg!=0? varargsOf(arg1,arg2): NONE).arg1(); + } + } + + public final LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { + LuaValue[] stack = new LuaValue[p.maxstacksize]; + System.arraycopy(NILS, 0, stack, 0, p.maxstacksize); + switch ( p.numparams ) { + default: stack[0]=arg1; stack[1]=arg2; stack[2]=arg3; return execute(stack,NONE).arg1(); + case 2: stack[0]=arg1; stack[1]=arg2; return execute(stack,arg3).arg1(); + case 1: stack[0]=arg1; return execute(stack,p.is_vararg!=0? varargsOf(arg2,arg3): NONE).arg1(); + case 0: return execute(stack,p.is_vararg!=0? varargsOf(arg1,arg2,arg3): NONE).arg1(); + } + } + + public final Varargs invoke(Varargs varargs) { + return onInvoke( varargs ).eval(); + } + + public Varargs onInvoke(Varargs varargs) { + LuaValue[] stack = new LuaValue[p.maxstacksize]; + System.arraycopy(NILS, 0, stack, 0, p.maxstacksize); + for ( int i=0; i0? new UpValue[stack.length]: null; + + // create varargs "arg" table + if ( p.is_vararg >= Lua.VARARG_NEEDSARG ) + stack[p.numparams] = new LuaTable(varargs); + + // debug wants args to this function + if (DebugLib.DEBUG_ENABLED) + DebugLib.debugSetupCall(varargs, stack); + + // process instructions + LuaThread.CallStack cs = LuaThread.onCall( this ); + try { + while ( true ) { + if (DebugLib.DEBUG_ENABLED) + DebugLib.debugBytecode(pc, v, top); + + // pull out instruction + i = code[pc++]; + a = ((i>>6) & 0xff); + + // process the op code + switch ( i & 0x3f ) { + + case Lua.OP_MOVE:/* A B R(A):= R(B) */ + stack[a] = stack[i>>>23]; + continue; + + case Lua.OP_LOADK:/* A Bx R(A):= Kst(Bx) */ + stack[a] = k[i>>>14]; + continue; + + case Lua.OP_LOADBOOL:/* A B C R(A):= (Bool)B: if (C) pc++ */ + stack[a] = (i>>>23!=0)? LuaValue.TRUE: LuaValue.FALSE; + if ((i&(0x1ff<<14)) != 0) + pc++; /* skip next instruction (if C) */ + continue; + + case Lua.OP_LOADNIL: /* A B R(A):= ...:= R(B):= nil */ + for ( b=i>>>23; a<=b; ) + stack[a++] = LuaValue.NIL; + continue; + + case Lua.OP_GETUPVAL: /* A B R(A):= UpValue[B] */ + stack[a] = upValues[i>>>23].getValue(); + continue; + + case Lua.OP_GETGLOBAL: /* A Bx R(A):= Gbl[Kst(Bx)] */ + stack[a] = env.get(k[i>>>14]); + continue; + + case Lua.OP_GETTABLE: /* A B C R(A):= R(B)[RK(C)] */ + stack[a] = stack[i>>>23].get((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]); + continue; + + case Lua.OP_SETGLOBAL: /* A Bx Gbl[Kst(Bx)]:= R(A) */ + env.set(k[i>>>14], stack[a]); + continue; + + case Lua.OP_SETUPVAL: /* A B UpValue[B]:= R(A) */ + upValues[i>>>23].setValue(stack[a]); + continue; + + case Lua.OP_SETTABLE: /* A B C R(A)[RK(B)]:= RK(C) */ + stack[a].set(((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]), (c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]); + continue; + + case Lua.OP_NEWTABLE: /* A B C R(A):= {} (size = B,C) */ + stack[a] = new LuaTable(i>>>23,(i>>14)&0x1ff); + continue; + + case Lua.OP_SELF: /* A B C R(A+1):= R(B): R(A):= R(B)[RK(C)] */ + stack[a+1] = (o = stack[i>>>23]); + stack[a] = o.get((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]); + continue; + + case Lua.OP_ADD: /* A B C R(A):= RK(B) + RK(C) */ + stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).add((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]); + continue; + + case Lua.OP_SUB: /* A B C R(A):= RK(B) - RK(C) */ + stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).sub((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]); + continue; + + case Lua.OP_MUL: /* A B C R(A):= RK(B) * RK(C) */ + stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).mul((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]); + continue; + + case Lua.OP_DIV: /* A B C R(A):= RK(B) / RK(C) */ + stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).div((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]); + continue; + + case Lua.OP_MOD: /* A B C R(A):= RK(B) % RK(C) */ + stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).mod((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]); + continue; + + case Lua.OP_POW: /* A B C R(A):= RK(B) ^ RK(C) */ + stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).pow((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]); + continue; + + case Lua.OP_UNM: /* A B R(A):= -R(B) */ + stack[a] = stack[i>>>23].neg(); + continue; + + case Lua.OP_NOT: /* A B R(A):= not R(B) */ + stack[a] = stack[i>>>23].not(); + continue; + + case Lua.OP_LEN: /* A B R(A):= length of R(B) */ + stack[a] = stack[i>>>23].len(); + continue; + + case Lua.OP_CONCAT: /* A B C R(A):= R(B).. ... ..R(C) */ + b = i>>>23; + c = (i>>14)&0x1ff; + { + if ( c > b+1 ) { + Buffer sb = stack[c].buffer(); + while ( --c>=b ) + sb = stack[c].concat(sb); + stack[a] = sb.value(); + } else { + stack[a] = stack[c-1].concat(stack[c]); + } + } + continue; + + case Lua.OP_JMP: /* sBx pc+=sBx */ + pc += (i>>>14)-0x1ffff; + continue; + + case Lua.OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ + if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).eq_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) ) + ++pc; + continue; + + case Lua.OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ + if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).lt_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) ) + ++pc; + continue; + + case Lua.OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ + if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).lteq_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) ) + ++pc; + continue; + + case Lua.OP_TEST: /* A C if not (R(A) <=> C) then pc++ */ + if ( stack[a].toboolean() != ((i&(0x1ff<<14))!=0) ) + ++pc; + continue; + + case Lua.OP_TESTSET: /* A B C if (R(B) <=> C) then R(A):= R(B) else pc++ */ + /* note: doc appears to be reversed */ + if ( (o=stack[i>>>23]).toboolean() != ((i&(0x1ff<<14))!=0) ) + ++pc; + else + stack[a] = o; // TODO: should be sBx? + continue; + + case Lua.OP_CALL: /* A B C R(A), ... ,R(A+C-2):= R(A)(R(A+1), ... ,R(A+B-1)) */ + switch ( i & (Lua.MASK_B | Lua.MASK_C) ) { + case (1<>>23; + c = (i>>14)&0x1ff; + v = b>0? + varargsOf(stack,a+1,b-1): // exact arg count + varargsOf(stack, a+1, top-v.narg()-(a+1), v); // from prev top + v = stack[a].invoke(v); + if ( c > 0 ) { + while ( --c > 0 ) + stack[a+c-1] = v.arg(c); + v = NONE; // TODO: necessary? + } else { + top = a + v.narg(); + } + continue; + } + + case Lua.OP_TAILCALL: /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ + switch ( i & Lua.MASK_B ) { + case (1<>>23; + v = b>0? + varargsOf(stack,a+1,b-1): // exact arg count + varargsOf(stack, a+1, top-v.narg()-(a+1), v); // from prev top + return new TailcallVarargs( stack[a], v ); + } + + case Lua.OP_RETURN: /* A B return R(A), ... ,R(A+B-2) (see note) */ + b = i>>>23; + switch ( b ) { + case 0: return varargsOf(stack, a, top-v.narg()-a, v); + case 1: return NONE; + case 2: return stack[a]; + default: + return varargsOf(stack, a, b-1); + } + + case Lua.OP_FORLOOP: /* A sBx R(A)+=R(A+2): if R(A) >>14)-0x1ffff; + } + } + continue; + + case Lua.OP_FORPREP: /* A sBx R(A)-=R(A+2): pc+=sBx */ + { + LuaValue init = stack[a].checknumber("'for' initial value must be a number"); + LuaValue limit = stack[a + 1].checknumber("'for' limit must be a number"); + LuaValue step = stack[a + 2].checknumber("'for' step must be a number"); + stack[a] = init.sub(step); + stack[a + 1] = limit; + stack[a + 2] = step; + pc += (i>>>14)-0x1ffff; + } + continue; + + case Lua.OP_TFORLOOP: /* + * A C R(A+3), ... ,R(A+2+C):= R(A)(R(A+1), + * R(A+2)): if R(A+3) ~= nil then R(A+2)=R(A+3) + * else pc++ + */ + // TODO: stack call on for loop body, such as: stack[a].call(ci); + v = stack[a].invoke(varargsOf(stack[a+1],stack[a+2])); + if ( (o=v.arg1()).isnil() ) + ++pc; + else { + stack[a+2] = stack[a+3] = o; + for ( c=(i>>14)&0x1ff; c>1; --c ) + stack[a+2+c] = v.arg(c); + v = NONE; // todo: necessary? + } + continue; + + case Lua.OP_SETLIST: /* A B C R(A)[(C-1)*FPF+i]:= R(A+i), 1 <= i <= B */ + { + if ( (c=(i>>14)&0x1ff) == 0 ) + c = code[pc++]; + int offset = (c-1) * Lua.LFIELDS_PER_FLUSH; + o = stack[a]; + if ( (b=i>>>23) == 0 ) { + b = top - a - 1; + int m = b - v.narg(); + int j=1; + for ( ;j<=m; j++ ) + o.set(offset+j, stack[a + j]); + for ( ;j<=b; j++ ) + o.set(offset+j, v.arg(j-m)); + } else { + o.presize( offset + b ); + for (int j=1; j<=b; j++) + o.set(offset+j, stack[a + j]); + } + } + continue; + + case Lua.OP_CLOSE: /* A close all variables in the stack up to (>=) R(A)*/ + for ( b=openups.length; --b>=a; ) + if ( openups[b]!=null ) { + openups[b].close(); + openups[b] = null; + } + continue; + + case Lua.OP_CLOSURE: /* A Bx R(A):= closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ + { + Prototype newp = p.p[i>>>14]; + LuaClosure newcl = new LuaClosure(newp, env); + for ( int j=0, nup=newp.nups; j>>23; + newcl.upValues[j] = (i&4) != 0? + upValues[b]: + openups[b]!=null? openups[b]: (openups[b]=new UpValue(stack,b)); + } + stack[a] = newcl; + } + continue; + + case Lua.OP_VARARG: /* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ + b = i>>>23; + if ( b == 0 ) { + top = a + (b = varargs.narg()); + v = varargs; + } else { + for ( int j=1; j=0; ) + if ( openups[u] != null ) + openups[u].close(); + } + } + + protected LuaValue getUpvalue(int i) { + return upValues[i].getValue(); + } + + protected void setUpvalue(int i, LuaValue v) { + upValues[i].setValue(v); + } +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/LuaDouble.java b/luaj-2.0.3/src/core/org/luaj/vm2/LuaDouble.java new file mode 100644 index 0000000000..85b151ce8a --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/LuaDouble.java @@ -0,0 +1,288 @@ +/******************************************************************************* +* Copyright (c) 2009-2011 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2; + +import org.luaj.vm2.lib.MathLib; + +/** + * Extension of {@link LuaNumber} which can hold a Java double as its value. + *

+ * These instance are not instantiated directly by clients, but indirectly + * via the static functions {@link LuaValue#valueOf(int)} or {@link LuaValue#valueOf(double)} + * functions. This ensures that values which can be represented as int + * are wrapped in {@link LuaInteger} instead of {@link LuaDouble}. + *

+ * Almost all API's implemented in LuaDouble are defined and documented in {@link LuaValue}. + *

+ * However the constants {@link #NAN}, {@link #POSINF}, {@link #NEGINF}, + * {@link #JSTR_NAN}, {@link #JSTR_POSINF}, and {@link #JSTR_NEGINF} may be useful + * when dealing with Nan or Infinite values. + *

+ * LuaDouble also defines functions for handling the unique math rules of lua devision and modulo in + *

    + *
  • {@link #ddiv(double, double)}
  • + *
  • {@link #ddiv_d(double, double)}
  • + *
  • {@link #dmod(double, double)}
  • + *
  • {@link #dmod_d(double, double)}
  • + *
+ *

+ * @see LuaValue + * @see LuaNumber + * @see LuaInteger + * @see LuaValue#valueOf(int) + * @see LuaValue#valueOf(double) + */ +public class LuaDouble extends LuaNumber { + + /** Constant LuaDouble representing NaN (not a number) */ + public static final LuaDouble NAN = new LuaDouble( Double.NaN ); + + /** Constant LuaDouble representing positive infinity */ + public static final LuaDouble POSINF = new LuaDouble( Double.POSITIVE_INFINITY ); + + /** Constant LuaDouble representing negative infinity */ + public static final LuaDouble NEGINF = new LuaDouble( Double.NEGATIVE_INFINITY ); + + /** Constant String representation for NaN (not a number), "nan" */ + public static final String JSTR_NAN = "nan"; + + /** Constant String representation for positive infinity, "inf" */ + public static final String JSTR_POSINF = "inf"; + + /** Constant String representation for negative infinity, "-inf" */ + public static final String JSTR_NEGINF = "-inf"; + + /** The value being held by this instance. */ + final double v; + + public static LuaNumber valueOf(double d) { + int id = (int) d; + return d==id? (LuaNumber) LuaInteger.valueOf(id): (LuaNumber) new LuaDouble(d); + } + + /** Don't allow ints to be boxed by DoubleValues */ + private LuaDouble(double d) { + this.v = d; + } + + public int hashCode() { + long l = Double.doubleToLongBits(v); + return ((int)(l>>32)) | (int) l; + } + + public boolean islong() { + return v == (long) v; + } + + public byte tobyte() { return (byte) (long) v; } + public char tochar() { return (char) (long) v; } + public double todouble() { return v; } + public float tofloat() { return (float) v; } + public int toint() { return (int) (long) v; } + public long tolong() { return (long) v; } + public short toshort() { return (short) (long) v; } + + public double optdouble(double defval) { return v; } + public int optint(int defval) { return (int) (long) v; } + public LuaInteger optinteger(LuaInteger defval) { return LuaInteger.valueOf((int) (long)v); } + public long optlong(long defval) { return (long) v; } + + public LuaInteger checkinteger() { return LuaInteger.valueOf( (int) (long) v ); } + + // unary operators + public LuaValue neg() { return valueOf(-v); } + + // object equality, used for key comparison + public boolean equals(Object o) { return o instanceof LuaDouble? ((LuaDouble)o).v == v: false; } + + // equality w/ metatable processing + public LuaValue eq( LuaValue val ) { return val.raweq(v)? TRUE: FALSE; } + public boolean eq_b( LuaValue val ) { return val.raweq(v); } + + // equality w/o metatable processing + public boolean raweq( LuaValue val ) { return val.raweq(v); } + public boolean raweq( double val ) { return v == val; } + public boolean raweq( int val ) { return v == val; } + + // basic binary arithmetic + public LuaValue add( LuaValue rhs ) { return rhs.add(v); } + public LuaValue add( double lhs ) { return LuaDouble.valueOf(lhs + v); } + public LuaValue sub( LuaValue rhs ) { return rhs.subFrom(v); } + public LuaValue sub( double rhs ) { return LuaDouble.valueOf(v - rhs); } + public LuaValue sub( int rhs ) { return LuaDouble.valueOf(v - rhs); } + public LuaValue subFrom( double lhs ) { return LuaDouble.valueOf(lhs - v); } + public LuaValue mul( LuaValue rhs ) { return rhs.mul(v); } + public LuaValue mul( double lhs ) { return LuaDouble.valueOf(lhs * v); } + public LuaValue mul( int lhs ) { return LuaDouble.valueOf(lhs * v); } + public LuaValue pow( LuaValue rhs ) { return rhs.powWith(v); } + public LuaValue pow( double rhs ) { return MathLib.dpow(v,rhs); } + public LuaValue pow( int rhs ) { return MathLib.dpow(v,rhs); } + public LuaValue powWith( double lhs ) { return MathLib.dpow(lhs,v); } + public LuaValue powWith( int lhs ) { return MathLib.dpow(lhs,v); } + public LuaValue div( LuaValue rhs ) { return rhs.divInto(v); } + public LuaValue div( double rhs ) { return LuaDouble.ddiv(v,rhs); } + public LuaValue div( int rhs ) { return LuaDouble.ddiv(v,rhs); } + public LuaValue divInto( double lhs ) { return LuaDouble.ddiv(lhs,v); } + public LuaValue mod( LuaValue rhs ) { return rhs.modFrom(v); } + public LuaValue mod( double rhs ) { return LuaDouble.dmod(v,rhs); } + public LuaValue mod( int rhs ) { return LuaDouble.dmod(v,rhs); } + public LuaValue modFrom( double lhs ) { return LuaDouble.dmod(lhs,v); } + + + /** Divide two double numbers according to lua math, and return a {@link LuaValue} result. + * @param lhs Left-hand-side of the division. + * @param rhs Right-hand-side of the division. + * @return {@link LuaValue} for the result of the division, + * taking into account positive and negiative infinity, and Nan + * @see #ddiv_d(double, double) + */ + public static LuaValue ddiv(double lhs, double rhs) { + return rhs!=0? valueOf( lhs / rhs ): lhs>0? POSINF: lhs==0? NAN: NEGINF; + } + + /** Divide two double numbers according to lua math, and return a double result. + * @param lhs Left-hand-side of the division. + * @param rhs Right-hand-side of the division. + * @return Value of the division, taking into account positive and negative infinity, and Nan + * @see #ddiv(double, double) + */ + public static double ddiv_d(double lhs, double rhs) { + return rhs!=0? lhs / rhs: lhs>0? Double.POSITIVE_INFINITY: lhs==0? Double.NaN: Double.NEGATIVE_INFINITY; + } + + /** Take modulo double numbers according to lua math, and return a {@link LuaValue} result. + * @param lhs Left-hand-side of the modulo. + * @param rhs Right-hand-side of the modulo. + * @return {@link LuaValue} for the result of the modulo, + * using lua's rules for modulo + * @see #dmod_d(double, double) + */ + public static LuaValue dmod(double lhs, double rhs) { + return rhs!=0? valueOf( lhs-rhs*Math.floor(lhs/rhs) ): NAN; + } + + /** Take modulo for double numbers according to lua math, and return a double result. + * @param lhs Left-hand-side of the modulo. + * @param rhs Right-hand-side of the modulo. + * @return double value for the result of the modulo, + * using lua's rules for modulo + * @see #dmod(double, double) + */ + public static double dmod_d(double lhs, double rhs) { + return rhs!=0? lhs-rhs*Math.floor(lhs/rhs): Double.NaN; + } + + // relational operators + public LuaValue lt( LuaValue rhs ) { return rhs.gt_b(v)? LuaValue.TRUE: FALSE; } + public LuaValue lt( double rhs ) { return v < rhs? TRUE: FALSE; } + public LuaValue lt( int rhs ) { return v < rhs? TRUE: FALSE; } + public boolean lt_b( LuaValue rhs ) { return rhs.gt_b(v); } + public boolean lt_b( int rhs ) { return v < rhs; } + public boolean lt_b( double rhs ) { return v < rhs; } + public LuaValue lteq( LuaValue rhs ) { return rhs.gteq_b(v)? LuaValue.TRUE: FALSE; } + public LuaValue lteq( double rhs ) { return v <= rhs? TRUE: FALSE; } + public LuaValue lteq( int rhs ) { return v <= rhs? TRUE: FALSE; } + public boolean lteq_b( LuaValue rhs ) { return rhs.gteq_b(v); } + public boolean lteq_b( int rhs ) { return v <= rhs; } + public boolean lteq_b( double rhs ) { return v <= rhs; } + public LuaValue gt( LuaValue rhs ) { return rhs.lt_b(v)? LuaValue.TRUE: FALSE; } + public LuaValue gt( double rhs ) { return v > rhs? TRUE: FALSE; } + public LuaValue gt( int rhs ) { return v > rhs? TRUE: FALSE; } + public boolean gt_b( LuaValue rhs ) { return rhs.lt_b(v); } + public boolean gt_b( int rhs ) { return v > rhs; } + public boolean gt_b( double rhs ) { return v > rhs; } + public LuaValue gteq( LuaValue rhs ) { return rhs.lteq_b(v)? LuaValue.TRUE: FALSE; } + public LuaValue gteq( double rhs ) { return v >= rhs? TRUE: FALSE; } + public LuaValue gteq( int rhs ) { return v >= rhs? TRUE: FALSE; } + public boolean gteq_b( LuaValue rhs ) { return rhs.lteq_b(v); } + public boolean gteq_b( int rhs ) { return v >= rhs; } + public boolean gteq_b( double rhs ) { return v >= rhs; } + + // string comparison + public int strcmp( LuaString rhs ) { typerror("attempt to compare number with string"); return 0; } + + public String tojstring() { + /* + if ( v == 0.0 ) { // never occurs in J2me + long bits = Double.doubleToLongBits( v ); + return ( bits >> 63 == 0 ) ? "0" : "-0"; + } + */ + long l = (long) v; + if ( l == v ) + return Long.toString(l); + if ( Double.isNaN(v) ) + return JSTR_NAN; + if ( Double.isInfinite(v) ) + return (v<0? JSTR_NEGINF: JSTR_POSINF); + return Float.toString((float)v); + } + + public LuaString strvalue() { + return LuaString.valueOf(tojstring()); + } + + public LuaString optstring(LuaString defval) { + return LuaString.valueOf(tojstring()); + } + + public LuaValue tostring() { + return LuaString.valueOf(tojstring()); + } + + public String optjstring(String defval) { + return tojstring(); + } + + public LuaNumber optnumber(LuaNumber defval) { + return this; + } + + public boolean isnumber() { + return true; + } + + public boolean isstring() { + return true; + } + + public LuaValue tonumber() { + return this; + } + public int checkint() { return (int) (long) v; } + public long checklong() { return (long) v; } + public LuaNumber checknumber() { return this; } + public double checkdouble() { return v; } + + public String checkjstring() { + return tojstring(); + } + public LuaString checkstring() { + return LuaString.valueOf(tojstring()); + } + + public LuaValue checkvalidkey() { + if ( Double.isNaN(v) ) + throw new LuaError("table index expected, got nan"); + return this; + } +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/LuaError.java b/luaj-2.0.3/src/core/org/luaj/vm2/LuaError.java new file mode 100644 index 0000000000..fd9c62e4e5 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/LuaError.java @@ -0,0 +1,132 @@ +/******************************************************************************* +* Copyright (c) 2009-2011 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2; + +import org.luaj.vm2.lib.DebugLib; + +/** + * RuntimeException that is thrown and caught in response to a lua error. + *

+ * {@link LuaError} is used wherever a lua call to {@code error()} + * would be used within a script. + *

+ * Since it is an unchecked exception inheriting from {@link RuntimeException}, + * Java method signatures do notdeclare this exception, althoug it can + * be thrown on almost any luaj Java operation. + * This is analagous to the fact that any lua script can throw a lua error at any time. + *

+ */ +public class LuaError extends RuntimeException { + private static final long serialVersionUID = 1L; + + private String traceback; + + /** + * Run the error hook if there is one + * @param msg the message to use in error hook processing. + * */ + private static String errorHook(String msg) { + LuaThread thread = LuaThread.getRunning(); + if ( thread.err != null ) { + LuaValue errfunc = thread.err; + thread.err = null; + try { + return errfunc.call( LuaValue.valueOf(msg) ).tojstring(); + } catch ( Throwable t ) { + return "error in error handling"; + } finally { + thread.err = errfunc; + } + } + return msg; + } + + private Throwable cause; + + /** Construct LuaError when a program exception occurs. + *

+ * All errors generated from lua code should throw LuaError(String) instead. + * @param cause the Throwable that caused the error, if known. + */ + public LuaError(Throwable cause) { + super( errorHook( addFileLine( "vm error: "+cause ) ) ); + this.cause = cause; + this.traceback = DebugLib.traceback(1); + } + + /** + * Construct a LuaError with a specific message. + * + * @param message message to supply + */ + public LuaError(String message) { + super( errorHook( addFileLine( message ) ) ); + this.traceback = DebugLib.traceback(1); + } + + /** + * Construct a LuaError with a message, and level to draw line number information from. + * @param message message to supply + * @param level where to supply line info from in call stack + */ + public LuaError(String message, int level) { + super( errorHook( addFileLine( message, level ) ) ); + this.traceback = DebugLib.traceback(1); + } + + /** + * Add file and line info to a message at a particular level + * @param message the String message to use + * @param level where to supply line info from in call stack + * */ + private static String addFileLine( String message, int level ) { + if ( message == null ) return null; + if ( level == 0 ) return message; + String fileline = DebugLib.fileline(level-1); + return fileline!=null? fileline+": "+message: message; + } + + /** Add file and line info for the nearest enclosing closure + * @param message the String message to use + * */ + private static String addFileLine( String message ) { + if ( message == null ) return null; + String fileline = DebugLib.fileline(); + return fileline!=null? fileline+": "+message: message; + } + + /** Print the message and stack trace */ + public void printStackTrace() { + System.out.println( toString() ); + if ( traceback != null ) + System.out.println( traceback ); + } + + /** + * Get the cause, if any. + */ + public Throwable getCause() { + return cause; + } + + +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/LuaFunction.java b/luaj-2.0.3/src/core/org/luaj/vm2/LuaFunction.java new file mode 100644 index 0000000000..5a4f114632 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/LuaFunction.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2009-2011 Luaj.org. 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. + ******************************************************************************/ +package org.luaj.vm2; + +/** + * Base class for functions implemented in Java. + *

+ * Direct subclass include {@link LibFunction} which is the base class for + * all built-in library functions coded in Java, + * and {@link LuaClosure}, which represents a lua closure + * whose bytecode is interpreted when the function is invoked. + * @see LuaValue + * @see LibFunction + * @see LuaClosure + */ +abstract +public class LuaFunction extends LuaValue { + + /** Shared static metatable for all functions and closures. */ + public static LuaValue s_metatable; + + protected LuaValue env; + + public LuaFunction() { + this.env = NIL; + } + + public LuaFunction(LuaValue env) { + this.env = env; + } + + public int type() { + return TFUNCTION; + } + + public String typename() { + return "function"; + } + + public boolean isfunction() { + return true; + } + + public LuaValue checkfunction() { + return this; + } + + public LuaFunction optfunction(LuaFunction defval) { + return this; + } + + public LuaValue getmetatable() { + return s_metatable; + } + + public LuaValue getfenv() { + return env; + } + + public void setfenv(LuaValue env) { + this.env = env!=null? env: NIL; + } +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/LuaInteger.java b/luaj-2.0.3/src/core/org/luaj/vm2/LuaInteger.java new file mode 100644 index 0000000000..008efdd4b8 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/LuaInteger.java @@ -0,0 +1,215 @@ +/******************************************************************************* +* Copyright (c) 2009 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2; + +import org.luaj.vm2.lib.MathLib; + +/** + * Extension of {@link LuaNumber} which can hold a Java int as its value. + *

+ * These instance are not instantiated directly by clients, but indirectly + * via the static functions {@link LuaValue#valueOf(int)} or {@link LuaValue#valueOf(double)} + * functions. This ensures that policies regarding pooling of instances are + * encapsulated. + *

+ * There are no API's specific to LuaInteger that are useful beyond what is already + * exposed in {@link LuaValue}. + * + * @see LuaValue + * @see LuaNumber + * @see LuaDouble + * @see LuaValue#valueOf(int) + * @see LuaValue#valueOf(double) + */ +public class LuaInteger extends LuaNumber { + + private static final LuaInteger[] intValues = new LuaInteger[512]; + static { + for ( int i=0; i<512; i++ ) + intValues[i] = new LuaInteger(i-256); + } + + public static LuaInteger valueOf(int i) { + return i<=255 && i>=-256? intValues[i+256]: new LuaInteger(i); + }; + + // TODO consider moving this to LuaValue + /** Return a LuaNumber that represents the value provided + * @param l long value to represent. + * @return LuaNumber that is eithe LuaInteger or LuaDouble representing l + * @see LuaValue#valueOf(int) + * @see LuaValue#valueOf(double) + */ + public static LuaNumber valueOf(long l) { + int i = (int) l; + return l==i? (i<=255 && i>=-256? intValues[i+256]: + (LuaNumber) new LuaInteger(i)): + (LuaNumber) LuaDouble.valueOf(l); + } + + /** The value being held by this instance. */ + public final int v; + + /** + * Package protected constructor. + * @see LuaValue#valueOf(int) + **/ + LuaInteger(int i) { + this.v = i; + } + + public boolean isint() { return true; } + public boolean isinttype() { return true; } + public boolean islong() { return true; } + + public byte tobyte() { return (byte) v; } + public char tochar() { return (char) v; } + public double todouble() { return v; } + public float tofloat() { return v; } + public int toint() { return v; } + public long tolong() { return v; } + public short toshort() { return (short) v; } + + public double optdouble(double defval) { return v; } + public int optint(int defval) { return v; } + public LuaInteger optinteger(LuaInteger defval) { return this; } + public long optlong(long defval) { return v; } + + public String tojstring() { + return Integer.toString(v); + } + + public LuaString strvalue() { + return LuaString.valueOf(Integer.toString(v)); + } + + public LuaString optstring(LuaString defval) { + return LuaString.valueOf(Integer.toString(v)); + } + + public LuaValue tostring() { + return LuaString.valueOf(Integer.toString(v)); + } + + public String optjstring(String defval) { + return Integer.toString(v); + } + + public LuaInteger checkinteger() { + return this; + } + + public boolean isstring() { + return true; + } + + public int hashCode() { + return v; + } + + // unary operators + public LuaValue neg() { return valueOf(-(long)v); } + + // object equality, used for key comparison + public boolean equals(Object o) { return o instanceof LuaInteger? ((LuaInteger)o).v == v: false; } + + // equality w/ metatable processing + public LuaValue eq( LuaValue val ) { return val.raweq(v)? TRUE: FALSE; } + public boolean eq_b( LuaValue val ) { return val.raweq(v); } + + // equality w/o metatable processing + public boolean raweq( LuaValue val ) { return val.raweq(v); } + public boolean raweq( double val ) { return v == val; } + public boolean raweq( int val ) { return v == val; } + + // arithmetic operators + public LuaValue add( LuaValue rhs ) { return rhs.add(v); } + public LuaValue add( double lhs ) { return LuaDouble.valueOf(lhs + v); } + public LuaValue add( int lhs ) { return LuaInteger.valueOf(lhs + (long)v); } + public LuaValue sub( LuaValue rhs ) { return rhs.subFrom(v); } + public LuaValue sub( double rhs ) { return LuaDouble.valueOf(v - rhs); } + public LuaValue sub( int rhs ) { return LuaDouble.valueOf(v - rhs); } + public LuaValue subFrom( double lhs ) { return LuaDouble.valueOf(lhs - v); } + public LuaValue subFrom( int lhs ) { return LuaInteger.valueOf(lhs - (long)v); } + public LuaValue mul( LuaValue rhs ) { return rhs.mul(v); } + public LuaValue mul( double lhs ) { return LuaDouble.valueOf(lhs * v); } + public LuaValue mul( int lhs ) { return LuaInteger.valueOf(lhs * (long)v); } + public LuaValue pow( LuaValue rhs ) { return rhs.powWith(v); } + public LuaValue pow( double rhs ) { return MathLib.dpow(v,rhs); } + public LuaValue pow( int rhs ) { return MathLib.dpow(v,rhs); } + public LuaValue powWith( double lhs ) { return MathLib.dpow(lhs,v); } + public LuaValue powWith( int lhs ) { return MathLib.dpow(lhs,v); } + public LuaValue div( LuaValue rhs ) { return rhs.divInto(v); } + public LuaValue div( double rhs ) { return LuaDouble.ddiv(v,rhs); } + public LuaValue div( int rhs ) { return LuaDouble.ddiv(v,rhs); } + public LuaValue divInto( double lhs ) { return LuaDouble.ddiv(lhs,v); } + public LuaValue mod( LuaValue rhs ) { return rhs.modFrom(v); } + public LuaValue mod( double rhs ) { return LuaDouble.dmod(v,rhs); } + public LuaValue mod( int rhs ) { return LuaDouble.dmod(v,rhs); } + public LuaValue modFrom( double lhs ) { return LuaDouble.dmod(lhs,v); } + + // relational operators + public LuaValue lt( LuaValue rhs ) { return rhs.gt_b(v)? TRUE: FALSE; } + public LuaValue lt( double rhs ) { return v < rhs? TRUE: FALSE; } + public LuaValue lt( int rhs ) { return v < rhs? TRUE: FALSE; } + public boolean lt_b( LuaValue rhs ) { return rhs.gt_b(v); } + public boolean lt_b( int rhs ) { return v < rhs; } + public boolean lt_b( double rhs ) { return v < rhs; } + public LuaValue lteq( LuaValue rhs ) { return rhs.gteq_b(v)? TRUE: FALSE; } + public LuaValue lteq( double rhs ) { return v <= rhs? TRUE: FALSE; } + public LuaValue lteq( int rhs ) { return v <= rhs? TRUE: FALSE; } + public boolean lteq_b( LuaValue rhs ) { return rhs.gteq_b(v); } + public boolean lteq_b( int rhs ) { return v <= rhs; } + public boolean lteq_b( double rhs ) { return v <= rhs; } + public LuaValue gt( LuaValue rhs ) { return rhs.lt_b(v)? TRUE: FALSE; } + public LuaValue gt( double rhs ) { return v > rhs? TRUE: FALSE; } + public LuaValue gt( int rhs ) { return v > rhs? TRUE: FALSE; } + public boolean gt_b( LuaValue rhs ) { return rhs.lt_b(v); } + public boolean gt_b( int rhs ) { return v > rhs; } + public boolean gt_b( double rhs ) { return v > rhs; } + public LuaValue gteq( LuaValue rhs ) { return rhs.lteq_b(v)? TRUE: FALSE; } + public LuaValue gteq( double rhs ) { return v >= rhs? TRUE: FALSE; } + public LuaValue gteq( int rhs ) { return v >= rhs? TRUE: FALSE; } + public boolean gteq_b( LuaValue rhs ) { return rhs.lteq_b(v); } + public boolean gteq_b( int rhs ) { return v >= rhs; } + public boolean gteq_b( double rhs ) { return v >= rhs; } + + // string comparison + public int strcmp( LuaString rhs ) { typerror("attempt to compare number with string"); return 0; } + + public int checkint() { + return v; + } + public long checklong() { + return v; + } + public double checkdouble() { + return v; + } + public String checkjstring() { + return String.valueOf(v); + } + public LuaString checkstring() { + return valueOf( String.valueOf(v) ); + } + +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/LuaNil.java b/luaj-2.0.3/src/core/org/luaj/vm2/LuaNil.java new file mode 100644 index 0000000000..a3960bc6cc --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/LuaNil.java @@ -0,0 +1,104 @@ +/******************************************************************************* +* Copyright (c) 2009-2011 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2; + +/** + * Class to encapsulate behavior of the singleton instance {@code nil} + *

+ * There will be one instance of this class, {@link LuaValue#NIL}, + * per Java virtual machine. + * However, the {@link Varargs} instance {@link LuaValue#NONE} + * which is the empty list, + * is also considered treated as a nil value by default. + *

+ * Although it is possible to test for nil using Java == operator, + * the recommended approach is to use the method {@link LuaValue#isnil()} + * instead. By using that any ambiguities between + * {@link LuaValue#NIL} and {@link LuaValue#NONE} are avoided. + * @see LuaValue + * @see LuaValue#NIL + */ +public class LuaNil extends LuaValue { + + static final LuaNil _NIL = new LuaNil(); + + public static LuaValue s_metatable; + + LuaNil() {} + + public int type() { + return LuaValue.TNIL; + } + + public String typename() { + return "nil"; + } + + public String tojstring() { + return "nil"; + } + + public LuaValue not() { + return LuaValue.TRUE; + } + + public boolean toboolean() { + return false; + } + + public boolean isnil() { + return true; + } + + public LuaValue getmetatable() { + return s_metatable; + } + + public boolean equals(Object o) { + return o instanceof LuaNil; + } + + public LuaValue checknotnil() { + return argerror("value"); + } + + public LuaValue checkvalidkey() { + return typerror("table index"); + } + + // optional argument conversions - nil alwas falls badk to default value + public boolean optboolean(boolean defval) { return defval; } + public LuaClosure optclosure(LuaClosure defval) { return defval; } + public double optdouble(double defval) { return defval; } + public LuaFunction optfunction(LuaFunction defval) { return defval; } + public int optint(int defval) { return defval; } + public LuaInteger optinteger(LuaInteger defval) { return defval; } + public long optlong(long defval) { return defval; } + public LuaNumber optnumber(LuaNumber defval) { return defval; } + public LuaTable opttable(LuaTable defval) { return defval; } + public LuaThread optthread(LuaThread defval) { return defval; } + public String optjstring(String defval) { return defval; } + public LuaString optstring(LuaString defval) { return defval; } + public Object optuserdata(Object defval) { return defval; } + public Object optuserdata(Class c, Object defval) { return defval; } + public LuaValue optvalue(LuaValue defval) { return defval; } +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/LuaNumber.java b/luaj-2.0.3/src/core/org/luaj/vm2/LuaNumber.java new file mode 100644 index 0000000000..ef97221828 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/LuaNumber.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2009-2011 Luaj.org. 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. + ******************************************************************************/ +package org.luaj.vm2; + +/** + * Base class for representing numbers as lua values directly. + *

+ * The main subclasses are {@link LuaInteger} which holds values that fit in a java int, + * and {@link LuaDouble} which holds all other number values. + * @see LuaInteger + * @see LuaDouble + * @see LuaValue + * + */ +abstract +public class LuaNumber extends LuaValue { + + /** Shared static metatable for all number values represented in lua. */ + public static LuaValue s_metatable; + + public int type() { + return TNUMBER; + } + + public String typename() { + return "number"; + } + + public LuaNumber checknumber() { + return this; + } + + public LuaNumber checknumber(String errmsg) { + return this; + } + + public LuaNumber optnumber(LuaNumber defval) { + return this; + } + + public LuaValue tonumber() { + return this; + } + + public boolean isnumber() { + return true; + } + + public boolean isstring() { + return true; + } + + public LuaValue getmetatable() { + return s_metatable; + } + + public LuaValue concat(LuaValue rhs) { return rhs.concatTo(this); } + public Buffer concat(Buffer rhs) { return rhs.concatTo(this); } + public LuaValue concatTo(LuaNumber lhs) { return strvalue().concatTo(lhs.strvalue()); } + public LuaValue concatTo(LuaString lhs) { return strvalue().concatTo(lhs); } + +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/LuaString.java b/luaj-2.0.3/src/core/org/luaj/vm2/LuaString.java new file mode 100644 index 0000000000..5d33ba26c0 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/LuaString.java @@ -0,0 +1,749 @@ +/******************************************************************************* +* Copyright (c) 2009-2011 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2; + + +import java.io.ByteArrayInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.String; +import java.lang.ref.WeakReference; +import java.util.Hashtable; + +import org.luaj.vm2.lib.MathLib; +import org.luaj.vm2.lib.StringLib; + +/** + * Subclass of {@link LuaValue} for representing lua strings. + *

+ * Because lua string values are more nearly sequences of bytes than + * sequences of characters or unicode code points, the {@link LuaString} + * implementation holds the string value in an internal byte array. + *

+ * {@link LuaString} values are generally not mutable once constructed, + * so multiple {@link LuaString} values can chare a single byte array. + *

+ * Currently {@link LuaString}s are pooled via a centrally managed weak table. + * To ensure that as many string values as possible take advantage of this, + * Constructors are not exposed directly. As with number, booleans, and nil, + * instance construction should be via {@link LuaValue#valueOf(byte[])} or similar API. + *

+ * When Java Strings are used to initialize {@link LuaString} data, the UTF8 encoding is assumed. + * The functions + * {@link LuaString#lengthAsUtf8(char[]), + * {@link LuaString#encodeToUtf8(char[], byte[], int)}, and + * {@link LuaString#decodeAsUtf8(byte[], int, int) + * are used to convert back and forth between UTF8 byte arrays and character arrays. + * + * @see LuaValue + * @see LuaValue#valueOf(String) + * @see LuaValue#valueOf(byte[]) + */ +public class LuaString extends LuaValue { + + /** The singleton instance representing lua {@code true} */ + public static LuaValue s_metatable; + + /** The bytes for the string */ + public final byte[] m_bytes; + + /** The offset into the byte array, 0 means start at the first byte */ + public final int m_offset; + + /** The number of bytes that comprise this string */ + public final int m_length; + + private static final Hashtable index_java = new Hashtable(); + + private final static LuaString index_get(Hashtable indextable, Object key) { + WeakReference w = (WeakReference) indextable.get(key); + return w!=null? (LuaString) w.get(): null; + } + + private final static void index_set(Hashtable indextable, Object key, LuaString value) { + indextable.put(key, new WeakReference(value)); + } + + /** + * Get a {@link LuaString} instance whose bytes match + * the supplied Java String using the UTF8 encoding. + * @param string Java String containing characters to encode as UTF8 + * @return {@link LuaString} with UTF8 bytes corresponding to the supplied String + */ + public static LuaString valueOf(String string) { + LuaString s = index_get( index_java, string ); + if ( s != null ) return s; + char[] c = string.toCharArray(); + /* DAN200 START */ + /* + byte[] b = new byte[lengthAsUtf8(c)]; + encodeToUtf8(c, b, 0); + */ + byte[] b = new byte[c.length]; + for( int i=0; i + * The array is used directly after this is called, so clients must not change contents. + *

+ * @param bytes byte buffer + * @param off offset into the byte buffer + * @param len length of the byte buffer + * @return {@link LuaString} wrapping the byte buffer + */ + public static LuaString valueOf(byte[] bytes, int off, int len) { + return new LuaString(bytes, off, len); + } + + /** Construct a {@link LuaString} using the supplied characters as byte values. + *

+ * Only th elow-order 8-bits of each character are used, the remainder is ignored. + *

+ * This is most useful for constructing byte sequences that do not conform to UTF8. + * @param bytes array of char, whose values are truncated at 8-bits each and put into a byte array. + * @return {@link LuaString} wrapping a copy of the byte buffer + */ + public static LuaString valueOf(char[] bytes) { + int n = bytes.length; + byte[] b = new byte[n]; + for ( int i=0; i + * The array is used directly after this is called, so clients must not change contents. + *

+ * @param bytes byte buffer + * @return {@link LuaString} wrapping the byte buffer + */ + public static LuaString valueOf(byte[] bytes) { + return valueOf(bytes, 0, bytes.length); + } + + /** Construct a {@link LuaString} around a byte array without copying the contents. + *

+ * The array is used directly after this is called, so clients must not change contents. + *

+ * @param bytes byte buffer + * @param offset offset into the byte buffer + * @param length length of the byte buffer + * @return {@link LuaString} wrapping the byte buffer + */ + private LuaString(byte[] bytes, int offset, int length) { + this.m_bytes = bytes; + this.m_offset = offset; + this.m_length = length; + } + + public boolean isstring() { + return true; + } + + public LuaValue getmetatable() { + return s_metatable; + } + + public int type() { + return LuaValue.TSTRING; + } + + public String typename() { + return "string"; + } + + public String tojstring() { + /* DAN200 START */ + /* + return decodeAsUtf8(m_bytes, m_offset, m_length); + */ + char[] chars = new char[ m_length ]; + for( int i=0; i0? LuaValue.TRUE: FALSE; } + public boolean lt_b( LuaValue rhs ) { return rhs.strcmp(this)>0; } + public boolean lt_b( int rhs ) { typerror("attempt to compare string with number"); return false; } + public boolean lt_b( double rhs ) { typerror("attempt to compare string with number"); return false; } + public LuaValue lteq( LuaValue rhs ) { return rhs.strcmp(this)>=0? LuaValue.TRUE: FALSE; } + public boolean lteq_b( LuaValue rhs ) { return rhs.strcmp(this)>=0; } + public boolean lteq_b( int rhs ) { typerror("attempt to compare string with number"); return false; } + public boolean lteq_b( double rhs ) { typerror("attempt to compare string with number"); return false; } + public LuaValue gt( LuaValue rhs ) { return rhs.strcmp(this)<0? LuaValue.TRUE: FALSE; } + public boolean gt_b( LuaValue rhs ) { return rhs.strcmp(this)<0; } + public boolean gt_b( int rhs ) { typerror("attempt to compare string with number"); return false; } + public boolean gt_b( double rhs ) { typerror("attempt to compare string with number"); return false; } + public LuaValue gteq( LuaValue rhs ) { return rhs.strcmp(this)<=0? LuaValue.TRUE: FALSE; } + public boolean gteq_b( LuaValue rhs ) { return rhs.strcmp(this)<=0; } + public boolean gteq_b( int rhs ) { typerror("attempt to compare string with number"); return false; } + public boolean gteq_b( double rhs ) { typerror("attempt to compare string with number"); return false; } + + // concatenation + public LuaValue concat(LuaValue rhs) { return rhs.concatTo(this); } + public Buffer concat(Buffer rhs) { return rhs.concatTo(this); } + public LuaValue concatTo(LuaNumber lhs) { return concatTo(lhs.strvalue()); } + public LuaValue concatTo(LuaString lhs) { + byte[] b = new byte[lhs.m_length+this.m_length]; + System.arraycopy(lhs.m_bytes, lhs.m_offset, b, 0, lhs.m_length); + System.arraycopy(this.m_bytes, this.m_offset, b, lhs.m_length, this.m_length); + return new LuaString(b, 0, b.length); + } + + // string comparison + public int strcmp(LuaValue lhs) { return -lhs.strcmp(this); } + public int strcmp(LuaString rhs) { + for ( int i=0, j=0; i>5)+1; /* if string is too long, don't hash all its chars */ + for (int l1=m_length; l1>=step; l1-=step) /* compute hash */ + h = h ^ ((h<<5)+(h>>2)+(((int) m_bytes[m_offset+l1-1] ) & 0x0FF )); + return h; + } + + // object comparison, used in key comparison + public boolean equals( Object o ) { + if ( o instanceof LuaString ) { + return raweq( (LuaString) o ); + } + return false; + } + + // equality w/ metatable processing + public LuaValue eq( LuaValue val ) { return val.raweq(this)? TRUE: FALSE; } + public boolean eq_b( LuaValue val ) { return val.raweq(this); } + + // equality w/o metatable processing + public boolean raweq( LuaValue val ) { + return val.raweq(this); + } + + public boolean raweq( LuaString s ) { + if ( this == s ) + return true; + if ( s.m_length != m_length ) + return false; + if ( s.m_bytes == m_bytes && s.m_offset == m_offset ) + return true; + if ( s.hashCode() != hashCode() ) + return false; + for ( int i=0; i=0 ) + if ( a[i++]!=b[j++] ) + return false; + return true; + } + + public void write(DataOutputStream writer, int i, int len) throws IOException { + writer.write(m_bytes,m_offset+i,len); + } + + public LuaValue len() { + return LuaInteger.valueOf(m_length); + } + + public int length() { + return m_length; + } + + public int luaByte(int index) { + return m_bytes[m_offset + index] & 0x0FF; + } + + public int charAt( int index ) { + if ( index < 0 || index >= m_length ) + throw new IndexOutOfBoundsException(); + return luaByte( index ); + } + + public String checkjstring() { + return tojstring(); + } + + public LuaString checkstring() { + return this; + } + + /** Convert value to an input stream. + * + * @return {@link InputStream} whose data matches the bytes in this {@link LuaString} + */ + public InputStream toInputStream() { + return new ByteArrayInputStream(m_bytes, m_offset, m_length); + } + + /** + * Copy the bytes of the string into the given byte array. + * @param strOffset offset from which to copy + * @param bytes destination byte array + * @param arrayOffset offset in destination + * @param len number of bytes to copy + */ + public void copyInto( int strOffset, byte[] bytes, int arrayOffset, int len ) { + System.arraycopy( m_bytes, m_offset+strOffset, bytes, arrayOffset, len ); + } + + /** Java version of strpbrk - find index of any byte that in an accept string. + * @param accept {@link LuaString} containing characters to look for. + * @return index of first match in the {@code accept} string, or -1 if not found. + */ + public int indexOfAny( LuaString accept ) { + final int ilimit = m_offset + m_length; + final int jlimit = accept.m_offset + accept.m_length; + for ( int i = m_offset; i < ilimit; ++i ) { + for ( int j = accept.m_offset; j < jlimit; ++j ) { + if ( m_bytes[i] == accept.m_bytes[j] ) { + return i - m_offset; + } + } + } + return -1; + } + + /** + * Find the index of a byte starting at a point in this string + * @param b the byte to look for + * @param start the first index in the string + * @return index of first match found, or -1 if not found. + */ + public int indexOf( byte b, int start ) { + for ( int i=0, j=m_offset+start; i < m_length; ++i ) { + if ( m_bytes[j++] == b ) + return i; + } + return -1; + } + + /** + * Find the index of a string starting at a point in this string + * @param s the string to search for + * @param start the first index in the string + * @return index of first match found, or -1 if not found. + */ + public int indexOf( LuaString s, int start ) { + final int slen = s.length(); + final int limit = m_offset + m_length - slen; + for ( int i = m_offset + start; i <= limit; ++i ) { + if ( equals( m_bytes, i, s.m_bytes, s.m_offset, slen ) ) { + /* DAN200 START */ + //return i; + return i - m_offset; + /* DAN200 END */ + } + } + return -1; + } + + /** + * Find the last index of a string in this string + * @param s the string to search for + * @return index of last match found, or -1 if not found. + */ + public int lastIndexOf( LuaString s ) { + final int slen = s.length(); + final int limit = m_offset + m_length - slen; + for ( int i = limit; i >= m_offset; --i ) { + if ( equals( m_bytes, i, s.m_bytes, s.m_offset, slen ) ) { + /* DAN200 START */ + //return i; + return i - m_offset; + /* DAN200 END */ + } + } + return -1; + } + + + /** + * Convert to Java String interpreting as utf8 characters. + * + * @param bytes byte array in UTF8 encoding to convert + * @param offset starting index in byte array + * @param length number of bytes to convert + * @return Java String corresponding to the value of bytes interpreted using UTF8 + * @see #lengthAsUtf8(char[]) + * @see #encodeToUtf8(char[], byte[], int) + * @see #isValidUtf8() + */ + /* DAN200 START */ + //public static String decodeAsUtf8(byte[] bytes, int offset, int length) { + private static String decodeAsUtf8(byte[] bytes, int offset, int length) { + /* DAN200 END */ + int i,j,n,b; + for ( i=offset,j=offset+length,n=0; i=0||i>=j)? b: + (b<-32||i+1>=j)? (((b&0x3f) << 6) | (bytes[i++]&0x3f)): + (((b&0xf) << 12) | ((bytes[i++]&0x3f)<<6) | (bytes[i++]&0x3f))); + } + return new String(chars); + } + + /** + * Count the number of bytes required to encode the string as UTF-8. + * @param chars Array of unicode characters to be encoded as UTF-8 + * @return count of bytes needed to encode using UTF-8 + * @see #encodeToUtf8(char[], byte[], int) + * @see #decodeAsUtf8(byte[], int, int) + * @see #isValidUtf8() + */ + /* DAN200 START */ + //public static int lengthAsUtf8(char[] chars) { + private static int lengthAsUtf8(char[] chars) { + /* DAN200 END */ + int i,b; + char c; + for ( i=b=chars.length; --i>=0; ) + if ( (c=chars[i]) >=0x80 ) + b += (c>=0x800)? 2: 1; + return b; + } + + /** + * Encode the given Java string as UTF-8 bytes, writing the result to bytes + * starting at offset. + *

+ * The string should be measured first with lengthAsUtf8 + * to make sure the given byte array is large enough. + * @param chars Array of unicode characters to be encoded as UTF-8 + * @param bytes byte array to hold the result + * @param off offset into the byte array to start writing + * @see #lengthAsUtf8(char[]) + * @see #decodeAsUtf8(byte[], int, int) + * @see #isValidUtf8() + */ + /* DAN200 START */ + //public static void encodeToUtf8(char[] chars, byte[] bytes, int off) { + private static void encodeToUtf8(char[] chars, byte[] bytes, int off) { + /* DAN200 END */ + final int n = chars.length; + char c; + for ( int i=0, j=off; i>6) & 0x1f)); + bytes[j++] = (byte) (0x80 | ( c & 0x3f)); + } else { + bytes[j++] = (byte) (0xE0 | ((c>>12) & 0x0f)); + bytes[j++] = (byte) (0x80 | ((c>>6) & 0x3f)); + bytes[j++] = (byte) (0x80 | ( c & 0x3f)); + } + } + } + + /** Check that a byte sequence is valid UTF-8 + * @return true if it is valid UTF-8, otherwise false + * @see #lengthAsUtf8(char[]) + * @see #encodeToUtf8(char[], byte[], int) + * @see #decodeAsUtf8(byte[], int, int) + */ + public boolean isValidUtf8() { + int i,j,n,b,e=0; + for ( i=m_offset,j=m_offset+m_length,n=0; i= 0 ) continue; + if ( ((c & 0xE0) == 0xC0) + && i= 2 && base <= 36 ) { + int i=m_offset,j=m_offset+m_length; + while ( i=j ) + return Double.NaN; + if ( ( base == 10 || base == 16 ) && ( m_bytes[i]=='0' && i+1='0'&&m_bytes[i]<='9')? '0': + m_bytes[i]>='A'&&m_bytes[i]<='Z'? ('A'-10): ('a'-10)); + if ( digit < 0 || digit >= base ) + return Double.NaN; + x = x * base + digit; + } + return neg? -x: x; + } + + /** + * Scan and convert a double value, or return Double.NaN if not a double. + * @param start the index to start searching from + * @param end the first index beyond the search range + * @return double value if conversion is valid, + * or Double.NaN if not + */ + private double scandouble(int start, int end) { + if ( end>start+64 ) end=start+64; + for ( int i=start; i + * Almost all API's implemented in {@link LuaTable} are defined and documented in {@link LuaValue}. + *

+ * If a table is needed, the one of the type-checking functions can be used such as + * {@link #istable()}, + * {@link #checktable()}, or + * {@link #opttable(LuaTable)} + *

+ * The main table operations are defined on {@link LuaValue} + * for getting and setting values with and without metatag processing: + *

    + *
  • {@link #get(LuaValue)}
  • + *
  • {@link #set(LuaValue,LuaValue)}
  • + *
  • {@link #rawget(LuaValue)}
  • + *
  • {@link #rawset(LuaValue,LuaValue)}
  • + *
  • plus overloads such as {@link #get(String)}, {@link #get(int)}, and so on
  • + *
+ *

+ * To iterate over key-value pairs from Java, use + *

 {@code
+ * LuaValue k = LuaValue.NIL;
+ * while ( true ) {
+ *    Varargs n = table.next(k);
+ *    if ( (k = n.arg1()).isnil() )
+ *       break;
+ *    LuaValue v = n.arg(2)
+ *    process( k, v )
+ * }}
+ * + *

+ * As with other types, {@link LuaTable} instances should be constructed via one of the table constructor + * methods on {@link LuaValue}: + *

    + *
  • {@link LuaValue#tableOf()} empty table
  • + *
  • {@link LuaValue#tableOf(int, int)} table with capacity
  • + *
  • {@link LuaValue#listOf(LuaValue[])} initialize array part
  • + *
  • {@link LuaValue#listOf(LuaValue[], Varargs)} initialize array part
  • + *
  • {@link LuaValue#tableOf(LuaValue[])} initialize named hash part
  • + *
  • {@link LuaValue#tableOf(Varargs, int)} initialize named hash part
  • + *
  • {@link LuaValue#tableOf(LuaValue[], LuaValue[])} initialize array and named parts
  • + *
  • {@link LuaValue#tableOf(LuaValue[], LuaValue[], Varargs)} initialize array and named parts
  • + *
+ * @see LuaValue + */ +public class LuaTable extends LuaValue { + private static final int MIN_HASH_CAPACITY = 2; + private static final LuaString N = valueOf("n"); + + /** the array values */ + protected LuaValue[] array; + + /** the hash keys */ + protected LuaValue[] hashKeys; + + /** the hash values */ + protected LuaValue[] hashValues; + + /** the number of hash entries */ + protected int hashEntries; + + /** metatable for this table, or null */ + protected LuaValue m_metatable; + + /** Construct empty table */ + public LuaTable() { + array = NOVALS; + hashKeys = NOVALS; + hashValues = NOVALS; + } + + /** + * Construct table with preset capacity. + * @param narray capacity of array part + * @param nhash capacity of hash part + */ + public LuaTable(int narray, int nhash) { + presize(narray, nhash); + } + + /** + * Construct table with named and unnamed parts. + * @param named Named elements in order {@code key-a, value-a, key-b, value-b, ... } + * @param unnamed Unnamed elements in order {@code value-1, value-2, ... } + * @param lastarg Additional unnamed values beyond {@code unnamed.length} + */ + public LuaTable(LuaValue[] named, LuaValue[] unnamed, Varargs lastarg) { + int nn = (named!=null? named.length: 0); + int nu = (unnamed!=null? unnamed.length: 0); + int nl = (lastarg!=null? lastarg.narg(): 0); + presize(nu+nl, nn-(nn>>1)); + for ( int i=0; i array.length ) + array = resize( array, narray ); + } + + public void presize(int narray, int nhash) { + if ( nhash > 0 && nhash < MIN_HASH_CAPACITY ) + nhash = MIN_HASH_CAPACITY; + array = (narray>0? new LuaValue[narray]: NOVALS); + hashKeys = (nhash>0? new LuaValue[nhash]: NOVALS); + hashValues = (nhash>0? new LuaValue[nhash]: NOVALS); + hashEntries = 0; + } + + /** Resize the table */ + private static LuaValue[] resize( LuaValue[] old, int n ) { + LuaValue[] v = new LuaValue[n]; + System.arraycopy(old, 0, v, 0, old.length); + return v; + } + + /** + * Get the length of the array part of the table. + * @return length of the array part, does not relate to count of objects in the table. + */ + protected int getArrayLength() { + return array.length; + } + + /** + * Get the length of the hash part of the table. + * @return length of the hash part, does not relate to count of objects in the table. + */ + protected int getHashLength() { + return hashValues.length; + } + + public LuaValue getmetatable() { + return m_metatable; + } + + public LuaValue setmetatable(LuaValue metatable) { + m_metatable = metatable; + LuaValue mode; + if ( m_metatable!=null && (mode=m_metatable.rawget(MODE)).isstring() ) { + String m = mode.tojstring(); + boolean k = m.indexOf('k')>=0; + boolean v = m.indexOf('v')>=0; + return changemode(k,v); + } + return this; + } + + /** + * Change the mode of a table + * @param weakkeys true to make the table have weak keys going forward + * @param weakvalues true to make the table have weak values going forward + * @return {@code this} or a new {@link WeakTable} if the mode change requires copying. + */ + protected LuaTable changemode(boolean weakkeys, boolean weakvalues) { + if ( weakkeys || weakvalues ) + return new WeakTable(weakkeys, weakvalues, this); + return this; + } + + public LuaValue get( int key ) { + LuaValue v = rawget(key); + return v.isnil() && m_metatable!=null? gettable(this,valueOf(key)): v; + } + + public LuaValue get( LuaValue key ) { + LuaValue v = rawget(key); + return v.isnil() && m_metatable!=null? gettable(this,key): v; + } + + public LuaValue rawget( int key ) { + if ( key>0 && key<=array.length ) + return array[key-1]!=null? array[key-1]: NIL; + return hashget( LuaInteger.valueOf(key) ); + } + + public LuaValue rawget( LuaValue key ) { + if ( key.isinttype() ) { + int ikey = key.toint(); + if ( ikey>0 && ikey<=array.length ) + return array[ikey-1]!=null? array[ikey-1]: NIL; + } + return hashget( key ); + } + + protected LuaValue hashget(LuaValue key) { + if ( hashEntries > 0 ) { + LuaValue v = hashValues[hashFindSlot(key)]; + return v!=null? v: NIL; + } + return NIL; + } + + public void set( int key, LuaValue value ) { + if ( m_metatable==null || ! rawget(key).isnil() || ! settable(this,LuaInteger.valueOf(key),value) ) + rawset(key, value); + } + + /** caller must ensure key is not nil */ + public void set( LuaValue key, LuaValue value ) { + key.checkvalidkey(); + if ( m_metatable==null || ! rawget(key).isnil() || ! settable(this,key,value) ) + rawset(key, value); + } + + public void rawset( int key, LuaValue value ) { + if ( ! arrayset(key, value) ) + hashset( LuaInteger.valueOf(key), value ); + } + + /** caller must ensure key is not nil */ + public void rawset( LuaValue key, LuaValue value ) { + if ( !key.isinttype() || !arrayset(key.toint(), value) ) + hashset( key, value ); + } + + /** Set an array element */ + private boolean arrayset( int key, LuaValue value ) { + if ( key>0 && key<=array.length ) { + array[key-1] = (value.isnil()? null: value); + return true; + } else if ( key==array.length+1 && !value.isnil() ) { + expandarray(); + array[key-1] = value; + return true; + } + return false; + } + + /** Expand the array part */ + private void expandarray() { + int n = array.length; + int m = Math.max(2,n*2); + array = resize(array, m); + for ( int i=n; i n) + return NONE; + LuaValue v = rawget(pos); + for ( LuaValue r=v; !r.isnil(); ) { + r = rawget(pos+1); + rawset(pos++, r); + } + return v.isnil()? NONE: v; + + } + + /** Insert an element at a position in a list-table + * + * @param pos the position to remove + * @param value The value to insert + */ + public void insert(int pos, LuaValue value) { + if ( pos == 0 ) + pos = length()+1; + while ( ! value.isnil() ) { + LuaValue v = rawget( pos ); + rawset(pos++, value); + value = v; + } + } + + /** Concatenate the contents of a table efficiently, using {@link Buffer} + * + * @param sep {@link LuaString} separater to apply between elements + * @param i the first element index + * @param j the last element index, inclusive + * @return {@link LuaString} value of the concatenation + */ + public LuaValue concat(LuaString sep, int i, int j) { + Buffer sb = new Buffer (); + if ( i<=j ) { + sb.append( get(i).checkstring() ); + while ( ++i<=j ) { + sb.append( sep ); + sb.append( get(i).checkstring() ); + } + } + return sb.tostring(); + } + + public LuaValue getn() { + for ( int n=getArrayLength(); n>0; --n ) + if ( !rawget(n).isnil() ) + return LuaInteger.valueOf(n); + return ZERO; + } + + public int length() { + int a = getArrayLength(); + int n = a+1,m=0; + while ( !rawget(n).isnil() ) { + m = n; + n += a+getHashLength()+1; + } + while ( n > m+1 ) { + int k = (n+m) / 2; + if ( !rawget(k).isnil() ) + m = k; + else + n = k; + } + return m; + } + + public LuaValue len() { + return LuaInteger.valueOf(length()); + } + + /** Return table.maxn() as defined by lua 5.0. + *

+ * Provided for compatibility, not a scalable operation. + * @return value for maxn + */ + public int maxn() { + int n = 0; + for ( int i=0; i n ) + n = key; + } + } + return n; + } + + /** + * Get the next element after a particular key in the table + * @return key,value or nil + */ + public Varargs next( LuaValue key ) { + int i = 0; + do { + // find current key index + if ( ! key.isnil() ) { + if ( key.isinttype() ) { + i = key.toint(); + if ( i>0 && i<=array.length ) { + if ( array[i-1] == null ) + error( "invalid key to 'next'" ); + break; + } + } + if ( hashKeys.length == 0 ) + error( "invalid key to 'next'" ); + i = hashFindSlot(key); + if ( hashKeys[i] == null ) + error( "invalid key to 'next'" ); + i += 1+array.length; + } + } while ( false ); + + // check array part + for ( ; i 0 ) { + int slot = hashFindSlot( key ); + hashClearSlot( slot ); + } + } + + /** + * Clear a particular slot in the table + * @param i slot to clear. + */ + protected void hashClearSlot( int i ) { + if ( hashKeys[ i ] != null ) { + + int j = i; + int n = hashKeys.length; + while ( hashKeys[ j = ( ( j + 1 ) % n ) ] != null ) { + final int k = ( ( hashKeys[ j ].hashCode() )& 0x7FFFFFFF ) % n; + if ( ( j > i && ( k <= i || k > j ) ) || + ( j < i && ( k <= i && k > j ) ) ) { + hashKeys[ i ] = hashKeys[ j ]; + hashValues[ i ] = hashValues[ j ]; + i = j; + } + } + + --hashEntries; + hashKeys[ i ] = null; + hashValues[ i ] = null; + + if ( hashEntries == 0 ) { + hashKeys = NOVALS; + hashValues = NOVALS; + } + } + } + + private boolean checkLoadFactor() { + // Using a load factor of (n+1) >= 7/8 because that is easy to compute without + // overflow or division. + final int hashCapacity = hashKeys.length; + return hashEntries >= (hashCapacity - (hashCapacity>>3)); + } + + private void rehash() { + final int oldCapacity = hashKeys.length; + final int newCapacity = oldCapacity+(oldCapacity>>2)+MIN_HASH_CAPACITY; + + final LuaValue[] oldKeys = hashKeys; + final LuaValue[] oldValues = hashValues; + + hashKeys = new LuaValue[ newCapacity ]; + hashValues = new LuaValue[ newCapacity ]; + + for ( int i = 0; i < oldCapacity; ++i ) { + final LuaValue k = oldKeys[i]; + if ( k != null ) { + final LuaValue v = oldValues[i]; + final int slot = hashFindSlot( k ); + hashKeys[slot] = k; + hashValues[slot] = v; + } + } + } + + // ----------------- sort support ----------------------------- + // + // implemented heap sort from wikipedia + // + // Only sorts the contiguous array part. + // + /** Sort the table using a comparator. + * @param comparator {@link LuaValue} to be called to compare elements. + */ + public void sort(LuaValue comparator) { + int n = array.length; + while ( n > 0 && array[n-1] == null ) + --n; + if ( n > 1 ) + heapSort(n, comparator); + } + + private void heapSort(int count, LuaValue cmpfunc) { + heapify(count, cmpfunc); + for ( int end=count-1; end>0; ) { + swap(end, 0); + siftDown(0, --end, cmpfunc); + } + } + + private void heapify(int count, LuaValue cmpfunc) { + for ( int start=count/2-1; start>=0; --start ) + siftDown(start, count - 1, cmpfunc); + } + + private void siftDown(int start, int end, LuaValue cmpfunc) { + for ( int root=start; root*2+1 <= end; ) { + int child = root*2+1; + if (child < end && compare(child, child + 1, cmpfunc)) + ++child; + if (compare(root, child, cmpfunc)) { + swap(root, child); + root = child; + } else + return; + } + } + + private boolean compare(int i, int j, LuaValue cmpfunc) { + LuaValue a = array[i]; + LuaValue b = array[j]; + if ( a == null || b == null ) + return false; + if ( ! cmpfunc.isnil() ) { + return cmpfunc.call(a,b).toboolean(); + } else { + return a.lt_b(b); + } + } + + private void swap(int i, int j) { + LuaValue a = array[i]; + array[i] = array[j]; + array[j] = a; + } + + /** This may be deprecated in a future release. + * It is recommended to count via iteration over next() instead + * @return count of keys in the table + * */ + public int keyCount() { + LuaValue k = LuaValue.NIL; + for ( int i=0; true; i++ ) { + Varargs n = next(k); + if ( (k = n.arg1()).isnil() ) + return i; + } + } + + /** This may be deprecated in a future release. + * It is recommended to use next() instead + * @return array of keys in the table + * */ + public LuaValue[] keys() { + Vector l = new Vector(); + LuaValue k = LuaValue.NIL; + while ( true ) { + Varargs n = next(k); + if ( (k = n.arg1()).isnil() ) + break; + l.addElement( k ); + } + LuaValue[] a = new LuaValue[l.size()]; + l.copyInto(a); + return a; + } + + // equality w/ metatable processing + public LuaValue eq( LuaValue val ) { return eq_b(val)? TRUE: FALSE; } + public boolean eq_b( LuaValue val ) { + if ( this == val ) return true; + if ( m_metatable == null || !val.istable() ) return false; + LuaValue valmt = val.getmetatable(); + return valmt!=null && LuaValue.eqmtcall(this, m_metatable, val, valmt); + } +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/LuaThread.java b/luaj-2.0.3/src/core/org/luaj/vm2/LuaThread.java new file mode 100644 index 0000000000..2ff24265e5 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/LuaThread.java @@ -0,0 +1,433 @@ +/******************************************************************************* +* Copyright (c) 2007-2012 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. +******************************************************************************/ +package org.luaj.vm2; + + +/* DAN200 START */ +import java.lang.ref.WeakReference; +import java.util.Enumeration; +import java.util.Vector; +/* DAN200 END */ + +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.DebugLib; + +/** + * Subclass of {@link LuaValue} that implements + * a lua coroutine thread using Java Threads. + *

+ * A LuaThread is typically created in response to a scripted call to + * {@code coroutine.create()} + *

+ * The threads must be initialized with the globals, so that + * the global environment may be passed along according to rules of lua. + * This is done via a call to {@link #setGlobals(LuaValue)} + * at some point during globals initialization. + * See {@link BaseLib} for additional documentation and example code. + *

+ * The utility classes {@link JsePlatform} and {@link JmePlatform} + * see to it that this initialization is done properly. + * For this reason it is highly recommended to use one of these classes + * when initializing globals. + *

+ * The behavior of coroutine threads matches closely the behavior + * of C coroutine library. However, because of the use of Java threads + * to manage call state, it is possible to yield from anywhere in luaj. + *

+ * Each Java thread wakes up at regular intervals and checks a weak reference + * to determine if it can ever be resumed. If not, it throws + * {@link OrphanedThread} which is an {@link java.lang.Error}. + * Applications should not catch {@link OrphanedThread}, because it can break + * the thread safety of luaj. + * + * @see LuaValue + * @see JsePlatform + * @see JmePlatform + * @see CoroutineLib + */ +public class LuaThread extends LuaValue { + + public static LuaValue s_metatable; + + public static int coroutine_count = 0; + + /** Interval at which to check for lua threads that are no longer referenced. + * This can be changed by Java startup code if desired. + */ + static long thread_orphan_check_interval = 30000; + + private static final int STATUS_INITIAL = 0; + private static final int STATUS_SUSPENDED = 1; + private static final int STATUS_RUNNING = 2; + private static final int STATUS_NORMAL = 3; + private static final int STATUS_DEAD = 4; + private static final String[] STATUS_NAMES = { + "suspended", + "suspended", + "running", + "normal", + "dead",}; + + private LuaValue env; + private final State state; + + /** Field to hold state of error condition during debug hook function calls. */ + public LuaValue err; + + final CallStack callstack = new CallStack(); + + public static final int MAX_CALLSTACK = 256; + + private static final LuaThread main_thread = new LuaThread(); + + // state of running thread including call stack + private static LuaThread running_thread = main_thread; + + /** Interval to check for LuaThread dereferencing. */ + public static int GC_INTERVAL = 30000; + + /** Thread-local used by DebugLib to store debugging state. */ + public Object debugState; + + /* DAN200 START */ + private Vector children = new Vector(); + /* DAN200 END */ + + /** Private constructor for main thread only */ + private LuaThread() { + state = new State(this, null); + state.status = STATUS_RUNNING; + } + + /** + * Create a LuaThread around a function and environment + * @param func The function to execute + * @param env The environment to apply to the thread + */ + public LuaThread(LuaValue func, LuaValue env) { + LuaValue.assert_(func != null, "function cannot be null"); + this.env = env; + state = new State(this, func); + } + + public int type() { + return LuaValue.TTHREAD; + } + + public String typename() { + return "thread"; + } + + public boolean isthread() { + return true; + } + + public LuaThread optthread(LuaThread defval) { + return this; + } + + public LuaThread checkthread() { + return this; + } + + public LuaValue getmetatable() { + return s_metatable; + } + + public LuaValue getfenv() { + return env; + } + + public void setfenv(LuaValue env) { + this.env = env; + } + + public String getStatus() { + return STATUS_NAMES[state.status]; + } + + /** + * Get the currently running thread. + * @return {@link LuaThread} that is currenly running + */ + public static LuaThread getRunning() { + return running_thread; + } + + /** + * Test if this is the main thread + * @return true if this is the main thread + */ + public static boolean isMainThread(LuaThread r) { + return r == main_thread; + } + + /** + * Set the globals of the current thread. + *

+ * This must be done once before any other code executes. + * @param globals The global variables for the main ghread. + */ + public static void setGlobals(LuaValue globals) { + running_thread.env = globals; + } + + /** Get the current thread's environment + * @return {@link LuaValue} containing the global variables of the current thread. + */ + public static LuaValue getGlobals() { + LuaValue e = running_thread.env; + return e!=null? e: LuaValue.error("LuaThread.setGlobals() not initialized"); + } + + /** + * Callback used at the beginning of a call to prepare for possible getfenv/setfenv calls + * @param function Function being called + * @return CallStack which is used to signal the return or a tail-call recursion + * @see DebugLib + */ + public static final CallStack onCall(LuaFunction function) { + CallStack cs = running_thread.callstack; + cs.onCall(function); + return cs; + } + + /** + * Get the function called as a specific location on the stack. + * @param level 1 for the function calling this one, 2 for the next one. + * @return LuaFunction on the call stack, or null if outside of range of active stack + */ + public static final LuaFunction getCallstackFunction(int level) { + return running_thread.callstack.getFunction(level); + } + + /** + * Replace the error function of the currently running thread. + * @param errfunc the new error function to use. + * @return the previous error function. + */ + public static LuaValue setErrorFunc(LuaValue errfunc) { + LuaValue prev = running_thread.err; + running_thread.err = errfunc; + return prev; + } + + /** Yield the current thread with arguments + * + * @param args The arguments to send as return values to {@link #resume(Varargs)} + * @return {@link Varargs} provided as arguments to {@link #resume(Varargs)} + */ + public static Varargs yield(Varargs args) { + State s = running_thread.state; + if (s.function == null) + throw new LuaError("cannot yield main thread"); + return s.lua_yield(args); + } + + /** Start or resume this thread + * + * @param args The arguments to send as return values to {@link #yield(Varargs)} + * @return {@link Varargs} provided as arguments to {@link #yield(Varargs)} + */ + public Varargs resume(Varargs args) { + if (this.state.status > STATUS_SUSPENDED) + return LuaValue.varargsOf(LuaValue.FALSE, + LuaValue.valueOf("cannot resume "+LuaThread.STATUS_NAMES[this.state.status]+" coroutine")); + return state.lua_resume(this, args); + } + + /* DAN200 START */ + public void addChild( LuaThread thread ) { + this.children.addElement( new WeakReference( thread ) ); + } + + public Varargs abandon() { + if( this.state.status > STATUS_SUSPENDED ) { + return LuaValue.varargsOf( LuaValue.FALSE, LuaValue.valueOf( "cannot abandon " + STATUS_NAMES[this.state.status] + " coroutine" ) ); + } else { + this.state.lua_abandon( this ); + + Enumeration it = this.children.elements(); + while( it.hasMoreElements() ) { + WeakReference ref = (WeakReference)it.nextElement(); + LuaThread thread = (LuaThread)ref.get(); + if(thread != null && !thread.getStatus().equals("dead")) { + thread.abandon(); + } + } + + this.children.removeAllElements(); + return LuaValue.varargsOf( new LuaValue[] { LuaValue.TRUE } ); + } + } + /* DAN200 END */ + + static class State implements Runnable { + final WeakReference lua_thread; + final LuaValue function; + Varargs args = LuaValue.NONE; + Varargs result = LuaValue.NONE; + String error = null; + int status = LuaThread.STATUS_INITIAL; + /* DAN200 START */ + boolean abandoned = false; + /* DAN200 END */ + + State(LuaThread lua_thread, LuaValue function) { + this.lua_thread = new WeakReference(lua_thread); + this.function = function; + } + + public synchronized void run() { + try { + Varargs a = this.args; + this.args = LuaValue.NONE; + this.result = function.invoke(a); + } catch (Throwable t) { + this.error = t.getMessage(); + } finally { + this.status = LuaThread.STATUS_DEAD; + this.notify(); + } + } + + synchronized Varargs lua_resume(LuaThread new_thread, Varargs args) { + LuaThread previous_thread = LuaThread.running_thread; + try { + LuaThread.running_thread = new_thread; + this.args = args; + if (this.status == STATUS_INITIAL) { + this.status = STATUS_RUNNING; + new Thread(this, "Coroutine-"+(++coroutine_count)).start(); + } else { + this.notify(); + } + previous_thread.state.status = STATUS_NORMAL; + this.status = STATUS_RUNNING; + this.wait(); + return (this.error != null? + LuaValue.varargsOf(LuaValue.FALSE, LuaValue.valueOf(this.error)): + LuaValue.varargsOf(LuaValue.TRUE, this.result)); + } catch (InterruptedException ie) { + throw new OrphanedThread(); + } finally { + running_thread = previous_thread; + running_thread.state.status =STATUS_RUNNING; + this.args = LuaValue.NONE; + this.result = LuaValue.NONE; + this.error = null; + } + } + + synchronized Varargs lua_yield(Varargs args) { + try { + this.result = args; + this.status = STATUS_SUSPENDED; + this.notify(); + do { + this.wait(thread_orphan_check_interval); + /* DAN200 START */ + //if (this.lua_thread.get() == null) { + if( this.abandoned || this.lua_thread.get() == null ) { + /* DAN200 END */ + this.status = STATUS_DEAD; + throw new OrphanedThread(); + } + } while (this.status == STATUS_SUSPENDED); + return this.args; + } catch (InterruptedException ie) { + this.status = STATUS_DEAD; + throw new OrphanedThread(); + } finally { + this.args = LuaValue.NONE; + this.result = LuaValue.NONE; + } + } + + /* DAN200 START */ + synchronized void lua_abandon(LuaThread thread) { + LuaThread current = LuaThread.running_thread; + + try { + current.state.status = STATUS_NORMAL; + this.abandoned = true; + if(this.status == STATUS_INITIAL) { + this.status = STATUS_DEAD; + } else { + this.notify(); + this.wait(); + } + } catch (InterruptedException var7) { + this.status = STATUS_DEAD; + } finally { + current.state.status = STATUS_RUNNING; + this.args = LuaValue.NONE; + this.result = LuaValue.NONE; + this.error = null; + } + } + /* DAN200 END */ + } + + public static class CallStack { + final LuaFunction[] functions = new LuaFunction[MAX_CALLSTACK]; + int calls = 0; + + /** + * Method to indicate the start of a call + * @see DebugLib + */ + final void onCall(LuaFunction function) { + functions[calls++] = function; + if (DebugLib.DEBUG_ENABLED) + DebugLib.debugOnCall(running_thread, calls, function); + } + + /** + * Method to signal the end of a call + * @see DebugLib + */ + public final void onReturn() { + functions[--calls] = null; + if (DebugLib.DEBUG_ENABLED) + DebugLib.debugOnReturn(running_thread, calls); + } + + /** + * Get number of calls in stack + * @return number of calls in current call stack + * @see DebugLib + */ + public final int getCallstackDepth() { + return calls; + } + + /** + * Get the function at a particular level of the stack. + * @param level # of levels back from the top of the stack. + * @return LuaFunction, or null if beyond the stack limits. + */ + LuaFunction getFunction(int level) { + return level>0 && level<=calls? functions[calls-level]: null; + } + } +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/LuaUserdata.java b/luaj-2.0.3/src/core/org/luaj/vm2/LuaUserdata.java new file mode 100644 index 0000000000..cf2b7b2873 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/LuaUserdata.java @@ -0,0 +1,126 @@ +/******************************************************************************* +* Copyright (c) 2009 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2; + + +public class LuaUserdata extends LuaValue { + + public final Object m_instance; + public LuaValue m_metatable; + + public LuaUserdata(Object obj) { + m_instance = obj; + } + + public LuaUserdata(Object obj, LuaValue metatable) { + m_instance = obj; + m_metatable = metatable; + } + + public String tojstring() { + return String.valueOf(m_instance); + } + + public int type() { + return LuaValue.TUSERDATA; + } + + public String typename() { + return "userdata"; + } + + public int hashCode() { + return m_instance.hashCode(); + } + + public Object userdata() { + return m_instance; + } + + public boolean isuserdata() { return true; } + public boolean isuserdata(Class c) { return c.isAssignableFrom(m_instance.getClass()); } + public Object touserdata() { return m_instance; } + public Object touserdata(Class c) { return c.isAssignableFrom(m_instance.getClass())? m_instance: null; } + public Object optuserdata(Object defval) { return m_instance; } + public Object optuserdata(Class c, Object defval) { + if (!c.isAssignableFrom(m_instance.getClass())) + typerror(c.getName()); + return m_instance; + } + + public LuaValue getmetatable() { + return m_metatable; + } + + public LuaValue setmetatable(LuaValue metatable) { + this.m_metatable = metatable; + return this; + } + + public Object checkuserdata() { + return m_instance; + } + + public Object checkuserdata(Class c) { + if ( c.isAssignableFrom(m_instance.getClass()) ) + return m_instance; + return typerror(c.getName()); + } + + public LuaValue get( LuaValue key ) { + return m_metatable!=null? gettable(this,key): NIL; + } + + public void set( LuaValue key, LuaValue value ) { + if ( m_metatable==null || ! settable(this,key,value) ) + error( "cannot set "+key+" for userdata" ); + } + + public boolean equals( Object val ) { + if ( this == val ) + return true; + if ( ! (val instanceof LuaUserdata) ) + return false; + LuaUserdata u = (LuaUserdata) val; + return m_instance.equals(u.m_instance); + } + + // equality w/ metatable processing + public LuaValue eq( LuaValue val ) { return eq_b(val)? TRUE: FALSE; } + public boolean eq_b( LuaValue val ) { + if ( val.raweq(this) ) return true; + if ( m_metatable == null || !val.isuserdata() ) return false; + LuaValue valmt = val.getmetatable(); + return valmt!=null && LuaValue.eqmtcall(this, m_metatable, val, valmt); + } + + // equality w/o metatable processing + public boolean raweq( LuaValue val ) { return val.raweq(this); } + public boolean raweq( LuaUserdata val ) { + return this == val || (m_metatable == val.m_metatable && m_instance.equals(val.m_instance)); + } + + // __eq metatag processing + public boolean eqmt( LuaValue val ) { + return m_metatable!=null && val.isuserdata()? LuaValue.eqmtcall(this, m_metatable, val, val.getmetatable()): false; + } +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/LuaValue.java b/luaj-2.0.3/src/core/org/luaj/vm2/LuaValue.java new file mode 100644 index 0000000000..76907b7540 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/LuaValue.java @@ -0,0 +1,3648 @@ +/******************************************************************************* +* Copyright (c) 2009-2011 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2; + + +/** + * Base class for all concrete lua type values. + *

+ * Establishes base implementations for all the operations on lua types. + * This allows Java clients to deal essentially with one type for all Java values, namely {@link LuaValue}. + *

+ * Constructors are provided as static methods for common Java types, such as + * {@link LuaValue#valueOf(int)} or {@link LuaValue#valueOf(String)} + * to allow for instance pooling. + *

+ * Constants are defined for the lua values + * {@link #NIL}, {@link #TRUE}, and {@link #FALSE}. + * A constant {@link #NONE} is defined which is a {@link Varargs} list having no values. + *

+ * Operations are performed on values directly via their Java methods. + * For example, the following code divides two numbers: + *

 {@code
+ * LuaValue a = LuaValue.valueOf( 5 );
+ * LuaValue b = LuaValue.valueOf( 4 );
+ * LuaValue c = a.div(b);
+ * } 
+ * Note that in this example, c will be a {@link LuaDouble}, but would be a {@link LuaInteger} + * if the value of a were changed to 8, say. + * In general the value of c in practice will vary depending on both the types and values of a and b + * as well as any metatable/metatag processing that occurs. + *

+ * Field access and function calls are similar, with common overloads to simplify Java usage: + *

 {@code
+ * LuaValue globals = JsePlatform.standardGlobals();
+ * LuaValue sqrt = globals.get("math").get("sqrt");
+ * LuaValue print = globals.get("print");
+ * LuaValue d = sqrt.call( a );
+ * print.call( LuaValue.valueOf("sqrt(5):"), a );
+ * } 
+ *

+ * To supply variable arguments or get multiple return values, use + * {@link invoke(Varargs)} or {@link invokemethod(LuaValue, Varargs)} methods: + *

 {@code
+ * LuaValue modf = globals.get("math").get("modf");
+ * Varargs r = modf.invoke( d );
+ * print.call( r.arg(1), r.arg(2) );
+ * } 
+ *

+ * To load and run a script, {@link LoadState} is used: + *

 {@code
+ * LoadState.load( new FileInputStream("main.lua"), "main.lua", globals ).call();
+ * } 
+ *

+ * although {@code require} could also be used: + *

 {@code
+ * globals.get("require").call(LuaValue.valueOf("main"));
+ * } 
+ * For this to work the file must be in the current directory, or in the class path, + * dependening on the platform. + * See {@link JsePlatform} and {@link JmePlatform} for details. + *

+ * In general a {@link LuaError} may be thrown on any operation when the + * types supplied to any operation are illegal from a lua perspective. + * Examples could be attempting to concatenate a NIL value, or attempting arithmetic + * on values that are not number. + *

+ * There are several methods for preinitializing tables, such as: + *

    + *
  • {@link #listOf(LuaValue[])} for unnamed elements
  • + *
  • {@link #tableOf(LuaValue[])} for named elements
  • + *
  • {@link #tableOf(LuaValue[], LuaValue[], Varargs)} for mixtures
  • + *
+ *

+ * Predefined constants exist for the standard lua type constants + * {@link TNIL}, {@link TBOOLEAN}, {@link TLIGHTUSERDATA}, {@link TNUMBER}, {@link TSTRING}, + * {@link TTABLE}, {@link TFUNCTION}, {@link TUSERDATA}, {@link TTHREAD}, + * and extended lua type constants + * {@link TINT}, {@link TNONE}, {@link TVALUE} + *

+ * Predefined constants exist for all strings used as metatags: + * {@link INDEX}, {@link NEWINDEX}, {@link CALL}, {@link MODE}, {@link METATABLE}, + * {@link ADD}, {@link SUB}, {@link DIV}, {@link MUL}, {@link POW}, + * {@link MOD}, {@link UNM}, {@link LEN}, {@link EQ}, {@link LT}, + * {@link LE}, {@link TOSTRING}, and {@link CONCAT}. + * + * @see JsePlatform + * @see JmePlatform + * @see LoadState + * @see Varargs + */ +abstract +public class LuaValue extends Varargs { + + + /** Type enumeration constant for lua numbers that are ints, for compatibility with lua 5.1 number patch only */ + public static final int TINT = (-2); + + /** Type enumeration constant for lua values that have no type, for example weak table entries */ + public static final int TNONE = (-1); + + /** Type enumeration constant for lua nil */ + public static final int TNIL = 0; + + /** Type enumeration constant for lua booleans */ + public static final int TBOOLEAN = 1; + + /** Type enumeration constant for lua light userdata, for compatibility with C-based lua only */ + public static final int TLIGHTUSERDATA = 2; + + /** Type enumeration constant for lua numbers */ + public static final int TNUMBER = 3; + + /** Type enumeration constant for lua strings */ + public static final int TSTRING = 4; + + /** Type enumeration constant for lua tables */ + public static final int TTABLE = 5; + + /** Type enumeration constant for lua functions */ + public static final int TFUNCTION = 6; + + /** Type enumeration constant for lua userdatas */ + public static final int TUSERDATA = 7; + + /** Type enumeration constant for lua threads */ + public static final int TTHREAD = 8; + + /** Type enumeration constant for unknown values, for compatibility with C-based lua only */ + public static final int TVALUE = 9; + + /** String array constant containing names of each of the lua value types + * @see #type() + * @see #typename() + */ + public static final String[] TYPE_NAMES = { + "nil", + "boolean", + "lightuserdata", + "number", + "string", + "table", + "function", + "userdata", + "thread", + "value", + }; + + /** LuaValue constant corresponding to lua {@code nil} */ + public static final LuaValue NIL = LuaNil._NIL; + + /** LuaBoolean constant corresponding to lua {@code true} */ + public static final LuaBoolean TRUE = LuaBoolean._TRUE; + + /** LuaBoolean constant corresponding to lua {@code false} */ + public static final LuaBoolean FALSE = LuaBoolean._FALSE; + + /** LuaValue constant corresponding to a {@link Varargs} list of no values */ + public static final LuaValue NONE = None._NONE; + + /** LuaValue number constant equal to 0 */ + public static final LuaNumber ZERO = LuaInteger.valueOf(0); + + /** LuaValue number constant equal to 1 */ + public static final LuaNumber ONE = LuaInteger.valueOf(1); + + /** LuaValue number constant equal to -1 */ + public static final LuaNumber MINUSONE = LuaInteger.valueOf(-1); + + /** LuaValue array constant with no values */ + public static final LuaValue[] NOVALS = {}; + + + /** LuaString constant with value "__index" for use as metatag */ + public static final LuaString INDEX = valueOf("__index"); + + /** LuaString constant with value "__newindex" for use as metatag */ + public static final LuaString NEWINDEX = valueOf("__newindex"); + + /** LuaString constant with value "__call" for use as metatag */ + public static final LuaString CALL = valueOf("__call"); + + /** LuaString constant with value "__mode" for use as metatag */ + public static final LuaString MODE = valueOf("__mode"); + + /** LuaString constant with value "__metatable" for use as metatag */ + public static final LuaString METATABLE = valueOf("__metatable"); + + /** LuaString constant with value "__add" for use as metatag */ + public static final LuaString ADD = valueOf("__add"); + + /** LuaString constant with value "__sub" for use as metatag */ + public static final LuaString SUB = valueOf("__sub"); + + /** LuaString constant with value "__div" for use as metatag */ + public static final LuaString DIV = valueOf("__div"); + + /** LuaString constant with value "__mul" for use as metatag */ + public static final LuaString MUL = valueOf("__mul"); + + /** LuaString constant with value "__pow" for use as metatag */ + public static final LuaString POW = valueOf("__pow"); + + /** LuaString constant with value "__mod" for use as metatag */ + public static final LuaString MOD = valueOf("__mod"); + + /** LuaString constant with value "__unm" for use as metatag */ + public static final LuaString UNM = valueOf("__unm"); + + /** LuaString constant with value "__len" for use as metatag */ + public static final LuaString LEN = valueOf("__len"); + + /** LuaString constant with value "__eq" for use as metatag */ + public static final LuaString EQ = valueOf("__eq"); + + /** LuaString constant with value "__lt" for use as metatag */ + public static final LuaString LT = valueOf("__lt"); + + /** LuaString constant with value "__le" for use as metatag */ + public static final LuaString LE = valueOf("__le"); + + /** LuaString constant with value "__tostring" for use as metatag */ + public static final LuaString TOSTRING = valueOf("__tostring"); + + /** LuaString constant with value "__concat" for use as metatag */ + public static final LuaString CONCAT = valueOf("__concat"); + + /** LuaString constant with value "" */ + public static final LuaString EMPTYSTRING = valueOf(""); + + /** Limit on lua stack size */ + private static int MAXSTACK = 250; + + /** Array of {@link NIL} values to optimize filling stacks using System.arraycopy(). + * Must not be modified. + */ + public static final LuaValue[] NILS = new LuaValue[MAXSTACK]; + static { + for ( int i=0; i + * + * @return name from type name list {@link #TYPE_NAMES} + * corresponding to the type of this value: + * "nil", "boolean", "number", "string", + * "table", "function", "userdata", "thread" + * @see #type() + */ + abstract public String typename(); + + /** Check if {@code this} is a {@code boolean} + * @return true if this is a {@code boolean}, otherwise false + * @see #isboolean() + * @see #toboolean() + * @see #checkboolean() + * @see #optboolean(boolean) + * @see #TOBOLEAN + */ + public boolean isboolean() { return false; } + + /** Check if {@code this} is a {@code function} that is a closure, + * meaning interprets lua bytecode for its execution + * @return true if this is a {@code closure}, otherwise false + * @see #isfunction() + * @see #checkclosure() + * @see #optclosure(LuaClosure) + * @see #TFUNCTION + */ + public boolean isclosure() { return false; } + + /** Check if {@code this} is a {@code function} + * @return true if this is a {@code function}, otherwise false + * @see #isclosure() + * @see #checkfunction() + * @see #optfunciton(LuaFunction) + * @see #TFUNCTION + */ + public boolean isfunction() { return false; } + + /** Check if {@code this} is a {@code number} and is representable by java int + * without rounding or truncation + * @return true if this is a {@code number} + * meaning derives from {@link LuaNumber} + * or derives from {@link LuaString} and is convertible to a number, + * and can be represented by int, + * otherwise false + * @see #isinttype() + * @see #islong() + * @see #tonumber() + * @see #checkint() + * @see #optint(int) + * @see #TNUMBER + */ + public boolean isint() { return false; } + + /** Check if {@code this} is a {@link LuaInteger} + *

+ * No attempt to convert from string will be made by this call. + * @return true if this is a {@code LuaInteger}, + * otherwise false + * @see #isint() + * @see #isnumber() + * @see #tonumber() + * @see #TNUMBER + */ + public boolean isinttype() { return false; } + + /** Check if {@code this} is a {@code number} and is representable by java long + * without rounding or truncation + * @return true if this is a {@code number} + * meaning derives from {@link LuaNumber} + * or derives from {@link LuaString} and is convertible to a number, + * and can be represented by long, + * otherwise false + * @see #tonumber() + * @see #checklong() + * @see #optlong(long) + * @see #TNUMBER + */ + public boolean islong() { return false; } + + /** Check if {@code this} is {@code nil} + * @return true if this is {@code nil}, otherwise false + * @see #NIL + * @see #NONE + * @see #checknotnil() + * @see #optvalue(LuaValue) + * @see Varargs#isnoneornil(int) + * @see #TNIL + * @see #TNONE + */ + public boolean isnil() { return false; } + + /** Check if {@code this} is a {@code number} + * @return true if this is a {@code number}, + * meaning derives from {@link LuaNumber} + * or derives from {@link LuaString} and is convertible to a number, + * otherwise false + * @see #tonumber() + * @see #checknumber() + * @see #optnumber(LuaNumber) + * @see #TNUMBER + */ + public boolean isnumber() { return false; } // may convert from string + + /** Check if {@code this} is a {@code string} + * @return true if this is a {@code string}, + * meaning derives from {@link LuaString} or {@link LuaNumber}, + * otherwise false + * @see #tostring() + * @see #checkstring() + * @see #optstring(LuaString) + * @see #TSTRING + */ + public boolean isstring() { return false; } + + /** Check if {@code this} is a {@code thread} + * @return true if this is a {@code thread}, otherwise false + * @see #checkthread() + * @see #optthread(LuaThread) + * @see #TTHREAD + */ + public boolean isthread() { return false; } + + /** Check if {@code this} is a {@code table} + * @return true if this is a {@code table}, otherwise false + * @see #checktable() + * @see #opttable(LuaTable) + * @see #TTABLE + */ + public boolean istable() { return false; } + + /** Check if {@code this} is a {@code userdata} + * @return true if this is a {@code userdata}, otherwise false + * @see #isuserdata(Class) + * @see #touserdata() + * @see #checkuserdata() + * @see #optuserdata(Object) + * @see #TUSERDATA + */ + public boolean isuserdata() { return false; } + + /** Check if {@code this} is a {@code userdata} of type {@code c} + * @param c Class to test instance against + * @return true if this is a {@code userdata} + * and the instance is assignable to {@code c}, + * otherwise false + * @see #isuserdata() + * @see #touserdata(Class) + * @see #checkuserdata(Class) + * @see #optuserdata(Object,Class) + * @see #TUSERDATA + */ + public boolean isuserdata(Class c) { return false; } + + /** Convert to boolean false if {@link #NIL} or {@link FALSE}, true if anything else + * @return Value cast to byte if number or string convertible to number, otherwise 0 + * @see #optboolean(boolean) + * @see #checkboolean() + * @see #isboolean() + * @see TBOOLEAN + */ + public boolean toboolean() { return true; } + + /** Convert to byte if numeric, or 0 if not. + * @return Value cast to byte if number or string convertible to number, otherwise 0 + * @see #toint() + * @see #todouble() + * @see #optbyte(byte) + * @see #checknumber() + * @see #isnumber() + * @see TNUMBER + */ + public byte tobyte() { return 0; } + + /** Convert to char if numeric, or 0 if not. + * @return Value cast to char if number or string convertible to number, otherwise 0 + * @see #toint() + * @see #todouble() + * @see #optchar(char) + * @see #checknumber() + * @see #isnumber() + * @see TNUMBER + */ + public char tochar() { return 0; } + + /** Convert to double if numeric, or 0 if not. + * @return Value cast to double if number or string convertible to number, otherwise 0 + * @see #toint() + * @see #tobyte() + * @see #tochar() + * @see #toshort() + * @see #tolong() + * @see #tofloat() + * @see #optdouble(double) + * @see #checknumber() + * @see #isnumber() + * @see TNUMBER + */ + public double todouble() { return 0; } + + /** Convert to float if numeric, or 0 if not. + * @return Value cast to float if number or string convertible to number, otherwise 0 + * @see #toint() + * @see #todouble() + * @see #optfloat(float) + * @see #checknumber() + * @see #isnumber() + * @see TNUMBER + */ + public float tofloat() { return 0; } + + /** Convert to int if numeric, or 0 if not. + * @return Value cast to int if number or string convertible to number, otherwise 0 + * @see #tobyte() + * @see #tochar() + * @see #toshort() + * @see #tolong() + * @see #tofloat() + * @see #todouble() + * @see #optint(int) + * @see #checknumber() + * @see #isnumber() + * @see TNUMBER + */ + public int toint() { return 0; } + + /** Convert to long if numeric, or 0 if not. + * @return Value cast to long if number or string convertible to number, otherwise 0 + * @see #isint() + * @see #isinttype() + * @see #toint() + * @see #todouble() + * @see #optlong(long) + * @see #checknumber() + * @see #isnumber() + * @see TNUMBER + */ + public long tolong() { return 0; } + + /** Convert to short if numeric, or 0 if not. + * @return Value cast to short if number or string convertible to number, otherwise 0 + * @see #toint() + * @see #todouble() + * @see #optshort(short) + * @see #checknumber() + * @see #isnumber() + * @see TNUMBER + */ + public short toshort() { return 0; } + + /** Convert to human readable String for any type. + * @return String for use by human readers based on type. + * @see #tostring() + * @see #optjstring(String) + * @see #checkjstring() + * @see #isstring() + * @see TSTRING + */ + public String tojstring() { return typename() + ": " + Integer.toHexString(hashCode()); } + + /** Convert to userdata instance, or null. + * @return userdata instance if userdata, or null if not {@link LuaUserdata} + * @see #optuserdata(Object) + * @see #checkuserdata() + * @see #isuserdata() + * @see #TUSERDATA + */ + public Object touserdata() { return null; } + + /** Convert to userdata instance if specific type, or null. + * @return userdata instance if is a userdata whose instance derives from {@code c}, + * or null if not {@link LuaUserdata} + * @see #optuserdata(Class,Object) + * @see #checkuserdata(Class) + * @see #isuserdata(Class) + * @see #TUSERDATA + */ + public Object touserdata(Class c) { return null; } + + /** + * Convert the value to a human readable string using {@link #tojstring()} + * @return String value intended to be human readible. + * @see #tostring() + * @see #tojstring() + * @see #optstring(LuaString) + * @see #checkstring() + * @see #toString() + */ + public String toString() { return tojstring(); } + + /** Conditionally convert to lua number without throwing errors. + *

+ * In lua all numbers are strings, but not all strings are numbers. + * This function will return + * the {@link LuaValue} {@code this} if it is a number + * or a string convertible to a number, + * and {@link NIL} for all other cases. + *

+ * This allows values to be tested for their "numeric-ness" without + * the penalty of throwing exceptions, + * nor the cost of converting the type and creating storage for it. + * @return {@code this} if it is a {@link LuaNumber} + * or {@link LuaString} that can be converted to a number, + * otherwise {@link #NIL} + * @see #tostring() + * @see #optnumber(LuaNumber) + * @see #checknumber() + * @see #toint() + * @see #todouble() + */ + public LuaValue tonumber() { return NIL; } + + /** Conditionally convert to lua string without throwing errors. + *

+ * In lua all numbers are strings, so this function will return + * the {@link LuaValue} {@code this} if it is a string or number, + * and {@link NIL} for all other cases. + *

+ * This allows values to be tested for their "string-ness" without + * the penalty of throwing exceptions. + * @return {@code this} if it is a {@link LuaString} or {@link LuaNumber}, + * otherwise {@link NIL} + * @see #tonumber() + * @see #tojstring() + * @see #optstring(LuaString) + * @see #checkstring() + * @see #toString() + */ + public LuaValue tostring() { return NIL; } + + /** Check that optional argument is a boolean and return its boolean value + * @param defval boolean value to return if {@code this} is nil or none + * @return {@code this} cast to boolean if a {@LuaBoolean}, + * {@code defval} if nil or none, + * throws {@link LuaError} otherwise + * @throws LuaError if was not a boolean or nil or none. + * @see #checkboolean() + * @see #isboolean() + * @see #TBOOLEAN + */ + public boolean optboolean(boolean defval) { argerror("boolean"); return false; } + + /** Check that optional argument is a closure and return as {@link LuaClosure} + *

+ * A {@link LuaClosure} is a {@LuaFunction} that executes lua byteccode. + * @param defval {@link LuaClosure} to return if {@code this} is nil or none + * @return {@code this} cast to {@link LuaClosure} if a function, + * {@code defval} if nil or none, + * throws {@link LuaError} otherwise + * @throws LuaError if was not a closure or nil or none. + * @see #checkclosure() + * @see #isclosure() + * @see #TFUNCTION + */ + public LuaClosure optclosure(LuaClosure defval) { argerror("closure"); return null; } + + /** Check that optional argument is a number or string convertible to number and return as double + * @param defval double to return if {@code this} is nil or none + * @return {@code this} cast to double if numeric, + * {@code defval} if nil or none, + * throws {@link LuaError} otherwise + * @throws LuaError if was not numeric or nil or none. + * @see #optint(int) + * @see #optinteger(LuaInteger) + * @see #checkdouble() + * @see #todouble() + * @see #tonumber() + * @see #isnumber() + * @see #TNUMBER + */ + public double optdouble(double defval) { argerror("double"); return 0; } + + /** Check that optional argument is a function and return as {@link LuaFunction} + *

+ * A {@link LuaFunction} may either be a Java function that implements + * functionality directly in Java, + * or a {@link LuaClosure} + * which is a {@link LuaFunction} that executes lua bytecode. + * @param defval {@link LuaFunction} to return if {@code this} is nil or none + * @return {@code this} cast to {@link LuaFunction} if a function, + * {@code defval} if nil or none, + * throws {@link LuaError} otherwise + * @throws LuaError if was not a function or nil or none. + * @see #checkfunction() + * @see #isfunction() + * @see #TFUNCTION + */ + public LuaFunction optfunction(LuaFunction defval) { argerror("function"); return null; } + + /** Check that optional argument is a number or string convertible to number and return as int + * @param defval int to return if {@code this} is nil or none + * @return {@code this} cast to int if numeric, + * {@code defval} if nil or none, + * throws {@link LuaError} otherwise + * @throws LuaError if was not numeric or nil or none. + * @see #optdouble(double) + * @see #optlong(long) + * @see #optinteger(LuaInteger) + * @see #checkint() + * @see #toint() + * @see #tonumber() + * @see #isnumber() + * @see #TNUMBER + */ + public int optint(int defval) { argerror("int"); return 0; } + + /** Check that optional argument is a number or string convertible to number and return as {@link LuaInteger} + * @param defval {@link LuaInteger} to return if {@code this} is nil or none + * @return {@code this} converted and wrapped in {@link LuaInteger} if numeric, + * {@code defval} if nil or none, + * throws {@link LuaError} otherwise + * @throws LuaError if was not numeric or nil or none. + * @see #optdouble(double) + * @see #optint(int) + * @see #checkint() + * @see #toint() + * @see #tonumber() + * @see #isnumber() + * @see #TNUMBER + */ + public LuaInteger optinteger(LuaInteger defval) { argerror("integer"); return null; } + + /** Check that optional argument is a number or string convertible to number and return as long + * @param defval long to return if {@code this} is nil or none + * @return {@code this} cast to long if numeric, + * {@code defval} if nil or none, + * throws {@link LuaError} otherwise + * @throws LuaError if was not numeric or nil or none. + * @see #optdouble(double) + * @see #optint(int) + * @see #checkint() + * @see #toint() + * @see #tonumber() + * @see #isnumber() + * @see #TNUMBER + */ + public long optlong(long defval) { argerror("long"); return 0; } + + /** Check that optional argument is a number or string convertible to number and return as {@link LuaNumber} + * @param defval {@link LuaNumber} to return if {@code this} is nil or none + * @return {@code this} cast to {@link LuaNumber} if numeric, + * {@code defval} if nil or none, + * throws {@link LuaError} otherwise + * @throws LuaError if was not numeric or nil or none. + * @see #optdouble(double) + * @see #optlong(long) + * @see #optint(int) + * @see #checkint() + * @see #toint() + * @see #tonumber() + * @see #isnumber() + * @see #TNUMBER + */ + public LuaNumber optnumber(LuaNumber defval) { argerror("number"); return null; } + + /** Check that optional argument is a string or number and return as Java String + * @param defval {@link LuaString} to return if {@code this} is nil or none + * @return {@code this} converted to String if a string or number, + * {@code defval} if nil or none, + * throws {@link LuaError} if some other type + * @throws LuaError if was not a string or number or nil or none. + * @see #tojstring() + * @see #optstring(LuaString) + * @see #checkjstring() + * @see #toString() + * @see #TSTRING + */ + public String optjstring(String defval) { argerror("String"); return null; } + + /** Check that optional argument is a string or number and return as {@link LuaString} + * @param defval {@link LuaString} to return if {@code this} is nil or none + * @return {@code this} converted to {@link LuaString} if a string or number, + * {@code defval} if nil or none, + * throws {@link LuaError} if some other type + * @throws LuaError if was not a string or number or nil or none. + * @see #tojstring() + * @see #optjstring(String) + * @see #checkstring() + * @see #toString() + * @see #TSTRING + */ + public LuaString optstring(LuaString defval) { argerror("string"); return null; } + + /** Check that optional argument is a table and return as {@link LuaTable} + * @param defval {@link LuaTable} to return if {@code this} is nil or none + * @return {@code this} cast to {@link LuaTable} if a table, + * {@code defval} if nil or none, + * throws {@link LuaError} if some other type + * @throws LuaError if was not a table or nil or none. + * @see #checktable() + * @see #istable() + * @see #TTABLE + */ + public LuaTable opttable(LuaTable defval) { argerror("table"); return null; } + + /** Check that optional argument is a thread and return as {@link LuaThread} + * @param defval {@link LuaThread} to return if {@code this} is nil or none + * @return {@code this} cast to {@link LuaTable} if a thread, + * {@code defval} if nil or none, + * throws {@link LuaError} if some other type + * @throws LuaError if was not a thread or nil or none. + * @see #checkthread() + * @see #isthread() + * @see #TTHREAD + */ + public LuaThread optthread(LuaThread defval) { argerror("thread"); return null; } + + /** Check that optional argument is a userdata and return the Object instance + * @param defval Object to return if {@code this} is nil or none + * @return Object instance of the userdata if a {@link LuaUserdata}, + * {@code defval} if nil or none, + * throws {@link LuaError} if some other type + * @throws LuaError if was not a userdata or nil or none. + * @see #checkuserdata() + * @see #isuserdata() + * @see #optuserdata(Class, Object) + * @see #TUSERDATA + */ + public Object optuserdata(Object defval) { argerror("object"); return null; } + + /** Check that optional argument is a userdata whose instance is of a type + * and return the Object instance + * @param c Class to test userdata instance against + * @param defval Object to return if {@code this} is nil or none + * @return Object instance of the userdata if a {@link LuaUserdata} and instance is assignable to {@code c}, + * {@code defval} if nil or none, + * throws {@link LuaError} if some other type + * @throws LuaError if was not a userdata whose instance is assignable to {@code c} or nil or none. + * @see #checkuserdata(Class) + * @see #isuserdata(Class) + * @see #optuserdata(Object) + * @see #TUSERDATA + */ + public Object optuserdata(Class c, Object defval) { argerror(c.getName()); return null; } + + /** Perform argument check that this is not nil or none. + * @param defval {@link LuaValue} to return if {@code this} is nil or none + * @return {@code this} if not nil or none, else {@code defval} + * @see #NIL + * @see #NONE + * @see #isnil() + * @see Varargs#isnoneornil(int) + * @see #TNIL + * @see #TNONE + */ + public LuaValue optvalue(LuaValue defval) { return this; } + + + /** Check that the value is a {@link LuaBoolean}, + * or throw {@link LuaError} if not + * @return boolean value for {@code this} if it is a {@link LuaBoolean} + * @throws LuaError if not a {@link LuaBoolean} + * @see #optboolean(boolean) + * @see #TBOOLEAN + */ + public boolean checkboolean() { argerror("boolean"); return false; } + + /** Check that the value is a {@link LuaClosure} , + * or throw {@link LuaError} if not + *

+ * {@link LuaClosure} is a subclass of {@LuaFunction} that interprets lua bytecode. + * @return {@code this} cast as {@link LuaClosure} + * @throws LuaError if not a {@link LuaClosure} + * @see #checkfunction() + * @see #optclosure(LuaClosure) + * @see #isclosure() + * @see #TFUNCTION + */ + public LuaClosure checkclosure() { argerror("closure"); return null; } + + /** Check that the value is numeric and return the value as a double, + * or throw {@link LuaError} if not numeric + *

+ * Values that are {@link LuaNumber} and values that are {@link LuaString} + * that can be converted to a number will be converted to double. + * @return value cast to a double if numeric + * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} that can't be converted to number + * @see #checkint() + * @see #checkinteger() + * @see #checklong() + * @see #optdouble(double) + * @see #TNUMBER + */ + public double checkdouble() { argerror("double"); return 0; } + + /** Check that the value is a function , or throw {@link LuaError} if not + *

+ * A function is considered anything whose {@link type()} returns {@link TFUNCTION}. + * In practice it will be either a built-in Java function, typically deriving from + * {@link LuaFunction} or a {@link LuaClosure} which represents lua source compiled + * into lua bytecode. + * @return {@code this} if if a lua function or closure + * @throws LuaError if not a function + * @see #checkclosure() + */ + public LuaValue checkfunction() { argerror("function"); return null; } + + /** Check that the value is numeric, and convert and cast value to int, or throw {@link LuaError} if not numeric + *

+ * Values that are {@link LuaNumber} will be cast to int and may lose precision. + * Values that are {@link LuaString} that can be converted to a number will be converted, + * then cast to int, so may also lose precision. + * @return value cast to a int if numeric + * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} that can't be converted to number + * @see #checkinteger() + * @see #checklong() + * @see #checkdouble() + * @see #optint(int) + * @see #TNUMBER + */ + public int checkint() { argerror("int"); return 0; } + + /** Check that the value is numeric, and convert and cast value to int, or throw {@link LuaError} if not numeric + *

+ * Values that are {@link LuaNumber} will be cast to int and may lose precision. + * Values that are {@link LuaString} that can be converted to a number will be converted, + * then cast to int, so may also lose precision. + * @return value cast to a int and wrapped in {@link LuaInteger} if numeric + * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} that can't be converted to number + * @see #checkint() + * @see #checklong() + * @see #checkdouble() + * @see #optinteger(LuaInteger) + * @see #TNUMBER + */ + public LuaInteger checkinteger() { argerror("integer"); return null; } + + /** Check that the value is numeric, and convert and cast value to long, or throw {@link LuaError} if not numeric + *

+ * Values that are {@link LuaNumber} will be cast to long and may lose precision. + * Values that are {@link LuaString} that can be converted to a number will be converted, + * then cast to long, so may also lose precision. + * @return value cast to a long if numeric + * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} that can't be converted to number + * @see #checkint() + * @see #checkinteger() + * @see #checkdouble() + * @see #optlong(long) + * @see #TNUMBER + */ + public long checklong() { argerror("long"); return 0; } + + /** Check that the value is numeric, and return as a LuaNumber if so, or throw {@link LuaError} + *

+ * Values that are {@link LuaString} that can be converted to a number will be converted and returned. + * @return value as a {@link LuaNumber} if numeric + * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} that can't be converted to number + * @see #checkint() + * @see #checkinteger() + * @see #checkdouble() + * @see #checklong() + * @see #optnumber(LuaNumber) + * @see #TNUMBER + */ + public LuaNumber checknumber() { argerror("number"); return null; } + + /** Check that the value is numeric, and return as a LuaNumber if so, or throw {@link LuaError} + *

+ * Values that are {@link LuaString} that can be converted to a number will be converted and returned. + * @param msg String message to supply if conversion fails + * @return value as a {@link LuaNumber} if numeric + * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} that can't be converted to number + * @see #checkint() + * @see #checkinteger() + * @see #checkdouble() + * @see #checklong() + * @see #optnumber(LuaNumber) + * @see #TNUMBER + */ + public LuaNumber checknumber(String msg) { throw new LuaError(msg); } + + /** Convert this value to a Java String. + *

+ * The string representations here will roughly match what is produced by the + * C lua distribution, however hash codes have no relationship, + * and there may be differences in number formatting. + * @return String representation of the value + * @see #checkstring() + * @see #optjstring(String) + * @see #tojstring() + * @see #isstring + * @see #TSTRING + */ + public String checkjstring() { argerror("string"); return null; } + + /** Check that this is a lua string, or throw {@link LuaError} if it is not. + *

+ * In lua all numbers are strings, so this will succeed for + * anything that derives from {@link LuaString} or {@link LuaNumber}. + * Numbers will be converted to {@link LuaString}. + * + * @return {@link LuaString} representation of the value if it is a {@link LuaString} or {@link LuaNumber} + * @throws LuaError if {@code this} is not a {@link LuaTable} + * @see #checkjstring() + * @see #optstring(LuaString) + * @see #tostring() + * @see #isstring() + * @see #TSTRING + */ + public LuaString checkstring() { argerror("string"); return null; } + + /** Check that this is a {@link LuaTable}, or throw {@link LuaError} if it is not + * @return {@code this} if it is a {@link LuaTable} + * @throws LuaError if {@code this} is not a {@link LuaTable} + * @see #istable() + * @see #opttable(LuaTable) + * @see #TTABLE + */ + public LuaTable checktable() { argerror("table"); return null; } + + /** Check that this is a {@link LuaThread}, or throw {@link LuaError} if it is not + * @return {@code this} if it is a {@link LuaThread} + * @throws LuaError if {@code this} is not a {@link LuaThread} + * @see #isthread() + * @see #optthread(LuaThread) + * @see #TTHREAD + */ + public LuaThread checkthread() { argerror("thread"); return null; } + + /** Check that this is a {@link LuaUserdata}, or throw {@link LuaError} if it is not + * @return {@code this} if it is a {@link LuaUserdata} + * @throws LuaError if {@code this} is not a {@link LuaUserdata} + * @see #isuserdata() + * @see #optuserdata(Object) + * @see #checkuserdata(Class) + * @see #TUSERDATA + */ + public Object checkuserdata() { argerror("userdata"); return null; } + + /** Check that this is a {@link LuaUserdata}, or throw {@link LuaError} if it is not + * @return {@code this} if it is a {@link LuaUserdata} + * @throws LuaError if {@code this} is not a {@link LuaUserdata} + * @see #isuserdata(Class) + * @see #optuserdata(Class, Object) + * @see #checkuserdata() + * @see #TUSERDATA + */ + public Object checkuserdata(Class c) { argerror("userdata"); return null; } + + /** Check that this is not the value {@link NIL}, or throw {@link LuaError} if it is + * @return {@code this} if it is not {@link NIL} + * @throws LuaError if {@code this} is {@link NIL} + * @see #optvalue(LuaValue) + */ + public LuaValue checknotnil() { return this; } + + /** Check that this is a valid key in a table index operation, or throw {@link LuaError} if not + * @return {@code this} if valid as a table key + * @throws LuaError if not valid as a table key + * @see #isnil() + * @see #isinttype() + */ + public LuaValue checkvalidkey() { return this; } + + /** + * Throw a {@link LuaError} with a particular message + * @param message String providing message details + * @throws LuaError in all cases + */ + public static LuaValue error(String message) { throw new LuaError(message); } + + /** + * Assert a condition is true, or throw a {@link LuaError} if not + * @param b condition to test + * @return returns no value when b is true, throws error not return if b is false + * @throws LuaError if b is not true + */ + public static void assert_(boolean b,String msg) { if(!b) throw new LuaError(msg); } + + /** + * Throw a {@link LuaError} indicating an invalid argument was supplied to a function + * @param expected String naming the type that was expected + * @throws LuaError in all cases + */ + protected LuaValue argerror(String expected) { throw new LuaError("bad argument: "+expected+" expected, got "+typename()); } + + /** + * Throw a {@link LuaError} indicating an invalid argument was supplied to a function + * @param iarg index of the argument that was invalid, first index is 1 + * @param msg String providing information about the invalid argument + * @throws LuaError in all cases + */ + public static LuaValue argerror(int iarg,String msg) { throw new LuaError("bad argument #"+iarg+": "+msg); } + + /** + * Throw a {@link LuaError} indicating an invalid type was supplied to a function + * @param expected String naming the type that was expected + * @throws LuaError in all cases + */ + protected LuaValue typerror(String expected) { throw new LuaError(expected+" expected, got "+typename()); } + + /** + * Throw a {@link LuaError} indicating an operation is not implemented + * @throws LuaError in all cases + */ + protected LuaValue unimplemented(String fun) { throw new LuaError("'"+fun+"' not implemented for "+typename()); } + + /** + * Throw a {@link LuaError} indicating an illegal operation occurred, + * typically involved in managing weak references + * @throws LuaError in all cases + */ + protected LuaValue illegal(String op,String typename) { throw new LuaError("illegal operation '"+op+"' for "+typename); } + + /** + * Throw a {@link LuaError} based on the len operator, + * typically due to an invalid operand type + * @throws LuaError in all cases + */ + protected LuaValue lenerror() { throw new LuaError("attempt to get length of "+typename()); } + + /** + * Throw a {@link LuaError} based on an arithmetic error such as add, or pow, + * typically due to an invalid operand type + * @throws LuaError in all cases + */ + protected LuaValue aritherror() { throw new LuaError("attempt to perform arithmetic on "+typename()); } + + /** + * Throw a {@link LuaError} based on an arithmetic error such as add, or pow, + * typically due to an invalid operand type + * @param fun String description of the function that was attempted + * @throws LuaError in all cases + */ + protected LuaValue aritherror(String fun) { throw new LuaError("attempt to perform arithmetic '"+fun+"' on "+typename()); } + + /** + * Throw a {@link LuaError} based on a comparison error such as greater-than or less-than, + * typically due to an invalid operand type + * @param rhs String description of what was on the right-hand-side of the comparison that resulted in the error. + * @throws LuaError in all cases + */ + protected LuaValue compareerror(String rhs) { throw new LuaError("attempt to compare "+typename()+" with "+rhs); } + + /** + * Throw a {@link LuaError} based on a comparison error such as greater-than or less-than, + * typically due to an invalid operand type + * @param rhs Right-hand-side of the comparison that resulted in the error. + * @throws LuaError in all cases + */ + protected LuaValue compareerror(LuaValue rhs) { throw new LuaError("attempt to compare "+typename()+" with "+rhs.typename()); } + + /** Get a value in a table including metatag processing using {@link INDEX}. + * @param key the key to look up, must not be {@link NIL} or null + * @return {@link LuaValue} for that key, or {@link NIL} if not found and no metatag + * @throws LuaError if {@code this} is not a table, + * or there is no {@link INDEX} metatag, + * or key is {@link NIL} + * @see #get(int) + * @see #get(String) + * @see #rawget(LuaValue) + */ + public LuaValue get( LuaValue key ) { return gettable(this,key); } + + /** Get a value in a table including metatag processing using {@link INDEX}. + * @param key the key to look up + * @return {@link LuaValue} for that key, or {@link NIL} if not found + * @throws LuaError if {@code this} is not a table, + * or there is no {@link INDEX} metatag + * @see #get(LuaValue) + * @see #rawget(int) + */ + public LuaValue get( int key ) { return get(LuaInteger.valueOf(key)); } + + /** Get a value in a table including metatag processing using {@link INDEX}. + * @param key the key to look up, must not be null + * @return {@link LuaValue} for that key, or {@link NIL} if not found + * @throws LuaError if {@code this} is not a table, + * or there is no {@link INDEX} metatag + * @see #get(LuaValue) + * @see #rawget(String) + */ + public LuaValue get( String key ) { return get(valueOf(key)); } + + /** Set a value in a table without metatag processing using {@link NEWINDEX}. + * @param key the key to use, must not be {@link NIL} or null + * @param value the value to use, can be {@link NIL}, must not be null + * @throws LuaError if {@code this} is not a table, + * or key is {@link NIL}, + * or there is no {@link NEWINDEX} metatag + */ + public void set( LuaValue key, LuaValue value ) { settable(this, key, value); } + + /** Set a value in a table without metatag processing using {@link NEWINDEX}. + * @param key the key to use + * @param value the value to use, can be {@link NIL}, must not be null + * @throws LuaError if {@code this} is not a table, + * or there is no {@link NEWINDEX} metatag + */ + public void set( int key, LuaValue value ) { set(LuaInteger.valueOf(key), value ); } + + /** Set a value in a table without metatag processing using {@link NEWINDEX}. + * @param key the key to use + * @param value the value to use, must not be null + * @throws LuaError if {@code this} is not a table, + * or there is no {@link NEWINDEX} metatag + */ + public void set( int key, String value ) { set(key, valueOf(value) ); } + + /** Set a value in a table without metatag processing using {@link NEWINDEX}. + * @param key the key to use, must not be {@link NIL} or null + * @param value the value to use, can be {@link NIL}, must not be null + * @throws LuaError if {@code this} is not a table, + * or there is no {@link NEWINDEX} metatag + */ + public void set( String key, LuaValue value ) { set(valueOf(key), value ); } + + /** Set a value in a table without metatag processing using {@link NEWINDEX}. + * @param key the key to use, must not be null + * @param value the value to use + * @throws LuaError if {@code this} is not a table, + * or there is no {@link NEWINDEX} metatag + */ + public void set( String key, double value ) { set(valueOf(key), valueOf(value) ); } + + /** Set a value in a table without metatag processing using {@link NEWINDEX}. + * @param key the key to use, must not be null + * @param value the value to use + * @throws LuaError if {@code this} is not a table, + * or there is no {@link NEWINDEX} metatag + */ + public void set( String key, int value ) { set(valueOf(key), valueOf(value) ); } + + /** Set a value in a table without metatag processing using {@link NEWINDEX}. + * @param key the key to use, must not be null + * @param value the value to use, must not be null + * @throws LuaError if {@code this} is not a table, + * or there is no {@link NEWINDEX} metatag + */ + public void set( String key, String value ) { set(valueOf(key), valueOf(value) ); } + + /** Get a value in a table without metatag processing. + * @param key the key to look up, must not be {@link NIL} or null + * @return {@link LuaValue} for that key, or {@link NIL} if not found + * @throws LuaError if {@code this} is not a table, or key is {@link NIL} + */ + public LuaValue rawget( LuaValue key ) { return unimplemented("rawget"); } + + /** Get a value in a table without metatag processing. + * @param key the key to look up + * @return {@link LuaValue} for that key, or {@link NIL} if not found + * @throws LuaError if {@code this} is not a table + */ + public LuaValue rawget( int key ) { return rawget(valueOf(key)); } + + /** Get a value in a table without metatag processing. + * @param key the key to look up, must not be null + * @return {@link LuaValue} for that key, or {@link NIL} if not found + * @throws LuaError if {@code this} is not a table + */ + public LuaValue rawget( String key ) { return rawget(valueOf(key)); } + + /** Set a value in a table without metatag processing. + * @param key the key to use, must not be {@link NIL} or null + * @param value the value to use, can be {@link NIL}, must not be null + * @throws LuaError if {@code this} is not a table, or key is {@link NIL} + */ + public void rawset( LuaValue key, LuaValue value ) { unimplemented("rawset"); } + + /** Set a value in a table without metatag processing. + * @param key the key to use + * @param value the value to use, can be {@link NIL}, must not be null + * @throws LuaError if {@code this} is not a table + */ + public void rawset( int key, LuaValue value ) { rawset(valueOf(key),value); } + + /** Set a value in a table without metatag processing. + * @param key the key to use + * @param value the value to use, can be {@link NIL}, must not be null + * @throws LuaError if {@code this} is not a table + */ + public void rawset( int key, String value ) { rawset(key,valueOf(value)); } + + /** Set a value in a table without metatag processing. + * @param key the key to use, must not be null + * @param value the value to use, can be {@link NIL}, must not be null + * @throws LuaError if {@code this} is not a table + */ + public void rawset( String key, LuaValue value ) { rawset(valueOf(key),value); } + + /** Set a value in a table without metatag processing. + * @param key the key to use, must not be null + * @param value the value to use + * @throws LuaError if {@code this} is not a table + */ + public void rawset( String key, double value ) { rawset(valueOf(key),valueOf(value)); } + + /** Set a value in a table without metatag processing. + * @param key the key to use, must not be null + * @param value the value to use + * @throws LuaError if {@code this} is not a table + */ + public void rawset( String key, int value ) { rawset(valueOf(key),valueOf(value)); } + + /** Set a value in a table without metatag processing. + * @param key the key to use, must not be null + * @param value the value to use, must not be null + * @throws LuaError if {@code this} is not a table + */ + public void rawset( String key, String value ) { rawset(valueOf(key),valueOf(value)); } + + /** Set list values in a table without invoking metatag processing + *

+ * Primarily used internally in response to a SETLIST bytecode. + * @param key0 the first key to set in the table + * @param values the list of values to set + * @throws LuaError if this is not a table. + */ + public void rawsetlist( int key0, Varargs values ) { for ( int i=0, n=values.narg(); i + * Primarily used internally in response to a SETLIST bytecode. + * @param i the number of array slots to preallocate in the table. + * @throws LuaError if this is not a table. + */ + public void presize( int i) { typerror("table"); } + + /** Find the next key,value pair if {@code this} is a table, + * return {@link NIL} if there are no more, or throw a {@link LuaError} if not a table. + *

+ * To iterate over all key-value pairs in a table you can use + *

 {@code
+	 * LuaValue k = LuaValue.NIL;
+	 * while ( true ) {
+	 *    Varargs n = table.next(k);
+	 *    if ( (k = n.arg1()).isnil() )
+	 *       break;
+	 *    LuaValue v = n.arg(2)
+	 *    process( k, v )
+	 * }}
+ * @param index {@link LuaInteger} value identifying a key to start from, + * or {@link NIL} to start at the beginning + * @return {@link Varargs} containing {key,value} for the next entry, + * or {@link NIL} if there are no more. + * @throws LuaError if {@code this} is not a table, or the supplied key is invalid. + * @see LuaTable + * @see #inext() + * @see #valueOf(int) + * @see Varargs#arg1() + * @see Varargs#arg(int) + * @see #isnil() + */ + public Varargs next(LuaValue index) { return typerror("table"); } + + /** Find the next integer-key,value pair if {@code this} is a table, + * return {@link NIL} if there are no more, or throw a {@link LuaError} if not a table. + *

+ * To iterate over integer keys in a table you can use + *

 {@code
+	 *   LuaValue k = LuaValue.NIL;
+	 *   while ( true ) {
+	 *      Varargs n = table.inext(k);
+	 *      if ( (k = n.arg1()).isnil() )
+	 *         break;
+	 *      LuaValue v = n.arg(2)
+	 *      process( k, v )
+	 *   }
+	 * } 
+ * @param index {@link LuaInteger} value identifying a key to start from, + * or {@link NIL} to start at the beginning + * @return {@link Varargs} containing {@code (key,value)} for the next entry, + * or {@link NONE} if there are no more. + * @throws LuaError if {@code this} is not a table, or the supplied key is invalid. + * @see LuaTable + * @see #next() + * @see #valueOf(int) + * @see Varargs#arg1() + * @see Varargs#arg(int) + * @see #isnil() + */ + public Varargs inext(LuaValue index) { return typerror("table"); } + + /** + * Load a library instance by setting its environment to {@code this} + * and calling it, which should iniitalize the library instance and + * install itself into this instance. + * @param library The callable {@link LuaValue} to load into {@code this} + * @return {@link LuaValue} containing the result of the initialization call. + */ + public LuaValue load(LuaValue library) { library.setfenv(this); return library.call(); } + + // varargs references + public LuaValue arg(int index) { return index==1? this: NIL; } + public int narg() { return 1; }; + public LuaValue arg1() { return this; } + + /** + * Get the metatable for this {@link LuaValue} + *

+ * For {@link LuaTable} and {@link LuaUserdata} instances, + * the metatable returned is this instance metatable. + * For all other types, the class metatable value will be returned. + * @return metatable, or null if it there is none + * @see LuaBoolean#s_metatable + * @see LuaNumber#s_metatable + * @see LuaNil#s_metatable + * @see LuaFunction#s_metatable + * @see LuaThread#s_metatable + */ + public LuaValue getmetatable() { return null; }; + + /** + * Set the metatable for this {@link LuaValue} + *

+ * For {@link LuaTable} and {@link LuaUserdata} instances, the metatable is per instance. + * For all other types, there is one metatable per type that can be set directly from java + * @param metatable {@link LuaValue} instance to serve as the metatable, or null to reset it. + * @return {@code this} to allow chaining of Java function calls + * @see LuaBoolean#s_metatable + * @see LuaNumber#s_metatable + * @see LuaNil#s_metatable + * @see LuaFunction#s_metatable + * @see LuaThread#s_metatable + */ + public LuaValue setmetatable(LuaValue metatable) { return argerror("table"); } + + /** + * Get the environemnt for an instance. + * @return {@link LuaValue} currently set as the instances environent. + */ + public LuaValue getfenv() { typerror("function or thread"); return null; } + + /** + * Set the environment on an object. + *

+ * Typically the environment is created once per application via a platform + * helper method such as {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} + * However, any object can serve as an environment if it contains suitable metatag + * values to implement {@link #get(LuaValue)} to provide the environment values. + * @param env {@link LuaValue} (typically a {@link LuaTable}) containing the environment. + * @see org.luaj.vm2.lib.jme.JmePlatform + * @see org.luaj.vm2.lib.jse.JsePlatform + */ + public void setfenv(LuaValue env) { typerror("function or thread"); } + + /** Call {@link this} with 0 arguments, including metatag processing, + * and return only the first return value. + *

+ * If {@code this} is a {@link LuaFunction}, call it, + * and return only its first return value, dropping any others. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * If the return value is a {@link Varargs}, only the 1st value will be returned. + * To get multiple values, use {@link #invoke()} instead. + *

+ * To call {@link this} as a method call, use {@link #method(LuaValue)} instead. + * + * @return First return value {@code (this())}, or {@link NIL} if there were none. + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #call(LuaValue) + * @see #call(LuaValue,LuaValue) + * @see #call(LuaValue, LuaValue, LuaValue) + * @see #invoke() + * @see #method(String) + * @see #method(LuaValue) + */ + public LuaValue call() { return callmt().call(this); } + + /** Call {@link this} with 1 argument, including metatag processing, + * and return only the first return value. + *

+ * If {@code this} is a {@link LuaFunction}, call it, + * and return only its first return value, dropping any others. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * If the return value is a {@link Varargs}, only the 1st value will be returned. + * To get multiple values, use {@link #invoke()} instead. + *

+ * To call {@link this} as a method call, use {@link #method(LuaValue)} instead. + * + * @param arg First argument to supply to the called function + * @return First return value {@code (this(arg))}, or {@link NIL} if there were none. + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #call() + * @see #call(LuaValue,LuaValue) + * @see #call(LuaValue, LuaValue, LuaValue) + * @see #invoke(LuaValue) + * @see #method(String,LuaValue) + * @see #method(LuaValue,LuaValue) + */ + public LuaValue call(LuaValue arg) { return callmt().call(this,arg); } + + /** Call {@link this} with 2 arguments, including metatag processing, + * and return only the first return value. + *

+ * If {@code this} is a {@link LuaFunction}, call it, + * and return only its first return value, dropping any others. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * If the return value is a {@link Varargs}, only the 1st value will be returned. + * To get multiple values, use {@link #invoke()} instead. + *

+ * To call {@link this} as a method call, use {@link #method(LuaValue)} instead. + * + * @param arg1 First argument to supply to the called function + * @param arg2 Second argument to supply to the called function + * @return First return value {@code (this(arg1,arg2))}, or {@link NIL} if there were none. + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #call() + * @see #call(LuaValue) + * @see #call(LuaValue, LuaValue, LuaValue) + * @see #invoke(LuaValue,LuaValue) + * @see #method(String,LuaValue,LuaValue) + * @see #method(LuaValue,LuaValue,LuaValue) + */ + public LuaValue call(LuaValue arg1, LuaValue arg2) { return callmt().call(this,arg1,arg2); } + + /** Call {@link this} with 3 arguments, including metatag processing, + * and return only the first return value. + *

+ * If {@code this} is a {@link LuaFunction}, call it, + * and return only its first return value, dropping any others. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * If the return value is a {@link Varargs}, only the 1st value will be returned. + * To get multiple values, use {@link #invoke()} instead. + *

+ * To call {@link this} as a method call, use {@link #method(LuaValue)} instead. + * + * @param arg1 First argument to supply to the called function + * @param arg2 Second argument to supply to the called function + * @param arg3 Second argument to supply to the called function + * @return First return value {@code (this(arg1,arg2,arg3))}, or {@link NIL} if there were none. + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #call() + * @see #call(LuaValue) + * @see #call(LuaValue, LuaValue) + * @see #invoke(LuaValue,LuaValue, LuaValue) + * @see #invokemethod(String,Varargs) + * @see #invokemethod(LuaValue,Varargs) + */ + public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { return callmt().invoke(new LuaValue[]{this,arg1,arg2,arg3}).arg1(); } + + /** Call named method on {@link this} with 0 arguments, including metatag processing, + * and return only the first return value. + *

+ * Look up {@code this[name]} and if it is a {@link LuaFunction}, + * call it inserting {@link this} as an additional first argument. + * and return only its first return value, dropping any others. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * If the return value is a {@link Varargs}, only the 1st value will be returned. + * To get multiple values, use {@link #invoke()} instead. + *

+ * To call {@link this} as a plain call, use {@link #call()} instead. + * + * @param name Name of the method to look up for invocation + * @return All values returned from {@code this:name()} as a {@link Varargs} instance + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #call() + * @see #invoke() + * @see #method(LuaValue) + * @see #method(String,LuaValue) + * @see #method(String,LuaValue,LuaValue) + */ + public LuaValue method(String name) { return this.get(name).call(this); } + + /** Call named method on {@link this} with 0 arguments, including metatag processing, + * and return only the first return value. + *

+ * Look up {@code this[name]} and if it is a {@link LuaFunction}, + * call it inserting {@link this} as an additional first argument, + * and return only its first return value, dropping any others. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * If the return value is a {@link Varargs}, only the 1st value will be returned. + * To get multiple values, use {@link #invoke()} instead. + *

+ * To call {@link this} as a plain call, use {@link #call()} instead. + * + * @param name Name of the method to look up for invocation + * @return All values returned from {@code this:name()} as a {@link Varargs} instance + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #call() + * @see #invoke() + * @see #method(String) + * @see #method(LuaValue,LuaValue) + * @see #method(LuaValue,LuaValue,LuaValue) + */ + public LuaValue method(LuaValue name) { return this.get(name).call(this); } + + /** Call named method on {@link this} with 1 argument, including metatag processing, + * and return only the first return value. + *

+ * Look up {@code this[name]} and if it is a {@link LuaFunction}, + * call it inserting {@link this} as an additional first argument, + * and return only its first return value, dropping any others. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * If the return value is a {@link Varargs}, only the 1st value will be returned. + * To get multiple values, use {@link #invoke()} instead. + *

+ * To call {@link this} as a plain call, use {@link #call(LuaValue)} instead. + * + * @param name Name of the method to look up for invocation + * @param arg Argument to supply to the method + * @return All values returned from {@code this:name(arg)} as a {@link Varargs} instance + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #call(LuaValue) + * @see #invoke(LuaValue) + * @see #method(LuaValue,LuaValue) + * @see #method(String) + * @see #method(String,LuaValue,LuaValue) + */ + public LuaValue method(String name, LuaValue arg) { return this.get(name).call(this,arg); } + + /** Call named method on {@link this} with 1 argument, including metatag processing, + * and return only the first return value. + *

+ * Look up {@code this[name]} and if it is a {@link LuaFunction}, + * call it inserting {@link this} as an additional first argument, + * and return only its first return value, dropping any others. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * If the return value is a {@link Varargs}, only the 1st value will be returned. + * To get multiple values, use {@link #invoke()} instead. + *

+ * To call {@link this} as a plain call, use {@link #call(LuaValue)} instead. + * + * @param name Name of the method to look up for invocation + * @param arg Argument to supply to the method + * @return All values returned from {@code this:name(arg)} as a {@link Varargs} instance + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #call(LuaValue) + * @see #invoke(LuaValue) + * @see #method(String,LuaValue) + * @see #method(LuaValue) + * @see #method(LuaValue,LuaValue,LuaValue) + */ + public LuaValue method(LuaValue name, LuaValue arg) { return this.get(name).call(this,arg); } + + /** Call named method on {@link this} with 2 arguments, including metatag processing, + * and return only the first return value. + *

+ * Look up {@code this[name]} and if it is a {@link LuaFunction}, + * call it inserting {@link this} as an additional first argument, + * and return only its first return value, dropping any others. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * If the return value is a {@link Varargs}, only the 1st value will be returned. + * To get multiple values, use {@link #invoke()} instead. + *

+ * To call {@link this} as a plain call, use {@link #call(LuaValue,LuaValue)} instead. + * + * @param name Name of the method to look up for invocation + * @param arg1 First argument to supply to the method + * @param arg2 Second argument to supply to the method + * @return All values returned from {@code this:name(arg1,arg2)} as a {@link Varargs} instance + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #call(LuaValue,LuaValue) + * @see #invoke(LuaValue,Varargs) + * @see #method(String,LuaValue) + * @see #method(LuaValue,LuaValue,LuaValue) + */ + public LuaValue method(String name, LuaValue arg1, LuaValue arg2) { return this.get(name).call(this,arg1,arg2); } + + /** Call named method on {@link this} with 2 arguments, including metatag processing, + * and return only the first return value. + *

+ * Look up {@code this[name]} and if it is a {@link LuaFunction}, + * call it inserting {@link this} as an additional first argument, + * and return only its first return value, dropping any others. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * If the return value is a {@link Varargs}, only the 1st value will be returned. + * To get multiple values, use {@link #invoke()} instead. + *

+ * To call {@link this} as a plain call, use {@link #call(LuaValue,LuaValue)} instead. + * + * @param name Name of the method to look up for invocation + * @param arg1 First argument to supply to the method + * @param arg2 Second argument to supply to the method + * @return All values returned from {@code this:name(arg1,arg2)} as a {@link Varargs} instance + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #call(LuaValue,LuaValue) + * @see #invoke(LuaValue,Varargs) + * @see #method(LuaValue,LuaValue) + * @see #method(String,LuaValue,LuaValue) + */ + public LuaValue method(LuaValue name, LuaValue arg1, LuaValue arg2) { return this.get(name).call(this,arg1,arg2); } + + /** Call {@link this} with 0 arguments, including metatag processing, + * and retain all return values in a {@link Varargs}. + *

+ * If {@code this} is a {@link LuaFunction}, call it, and return all values. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * To get a particular return value, us {@link Varargs#arg(int)} + *

+ * To call {@link this} as a method call, use {@link #invokemethod(LuaValue)} instead. + * + * @return All return values as a {@link Varargs} instance. + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #call() + * @see #invoke(Varargs) + * @see #invokemethod(String) + * @see #invokemethod(LuaValue) + */ + public Varargs invoke() { return invoke(NONE); } + + /** Call {@link this} with variable arguments, including metatag processing, + * and retain all return values in a {@link Varargs}. + *

+ * If {@code this} is a {@link LuaFunction}, call it, and return all values. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * To get a particular return value, us {@link Varargs#arg(int)} + *

+ * To call {@link this} as a method call, use {@link #invokemethod(LuaValue)} instead. + * + * @param args Varargs containing the arguments to supply to the called function + * @return All return values as a {@link Varargs} instance. + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #varargsOf(LuaValue[]) + * @see #call(LuaValue) + * @see #invoke() + * @see #invoke(LuaValue,Varargs) + * @see #invokemethod(String,Varargs) + * @see #invokemethod(LuaValue,Varargs) + */ + public Varargs invoke(Varargs args) { return callmt().invoke(this,args); } + + /** Call {@link this} with variable arguments, including metatag processing, + * and retain all return values in a {@link Varargs}. + *

+ * If {@code this} is a {@link LuaFunction}, call it, and return all values. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * To get a particular return value, us {@link Varargs#arg(int)} + *

+ * To call {@link this} as a method call, use {@link #invokemethod(LuaValue,Varargs)} instead. + * + * @param arg The first argument to supply to the called function + * @param varargs Varargs containing the remaining arguments to supply to the called function + * @return All return values as a {@link Varargs} instance. + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #varargsOf(LuaValue[]) + * @see #call(LuaValue,LuaValue) + * @see #invoke(LuaValue,Varargs) + * @see #invokemethod(String,Varargs) + * @see #invokemethod(LuaValue,Varargs) + */ + public Varargs invoke(LuaValue arg,Varargs varargs) { return invoke(varargsOf(arg,varargs)); } + + /** Call {@link this} with variable arguments, including metatag processing, + * and retain all return values in a {@link Varargs}. + *

+ * If {@code this} is a {@link LuaFunction}, call it, and return all values. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * To get a particular return value, us {@link Varargs#arg(int)} + *

+ * To call {@link this} as a method call, use {@link #invokemethod(LuaValue,Varargs)} instead. + * + * @param arg1 The first argument to supply to the called function + * @param arg2 The second argument to supply to the called function + * @param varargs Varargs containing the remaining arguments to supply to the called function + * @return All return values as a {@link Varargs} instance. + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #varargsOf(LuaValue[]) + * @see #call(LuaValue,LuaValue,LuaValue) + * @see #invoke(LuaValue,LuaValue,Varargs) + * @see #invokemethod(String,Varargs) + * @see #invokemethod(LuaValue,Varargs) + */ + public Varargs invoke(LuaValue arg1,LuaValue arg2,Varargs varargs) { return invoke(varargsOf(arg1,arg2,varargs)); } + + /** Call {@link this} with variable arguments, including metatag processing, + * and retain all return values in a {@link Varargs}. + *

+ * If {@code this} is a {@link LuaFunction}, call it, and return all values. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * To get a particular return value, us {@link Varargs#arg(int)} + *

+ * To call {@link this} as a method call, use {@link #invokemethod(LuaValue,Varargs)} instead. + * + * @param args Array of arguments to supply to the called function + * @return All return values as a {@link Varargs} instance. + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #varargsOf(LuaValue[]) + * @see #call(LuaValue,LuaValue,LuaValue) + * @see #invoke(LuaValue,LuaValue,Varargs) + * @see #invokemethod(String,LuaValue[]) + * @see #invokemethod(LuaValue,LuaValue[]) + */ + public Varargs invoke(LuaValue[] args) { return invoke(varargsOf(args)); } + + /** Call {@link this} with variable arguments, including metatag processing, + * and retain all return values in a {@link Varargs}. + *

+ * If {@code this} is a {@link LuaFunction}, call it, and return all values. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * To get a particular return value, us {@link Varargs#arg(int)} + *

+ * To call {@link this} as a method call, use {@link #invokemethod(LuaValue,Varargs)} instead. + * + * @param args Array of arguments to supply to the called function + * @param varargs Varargs containing additional arguments to supply to the called function + * @return All return values as a {@link Varargs} instance. + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #varargsOf(LuaValue[]) + * @see #call(LuaValue,LuaValue,LuaValue) + * @see #invoke(LuaValue,LuaValue,Varargs) + * @see #invokemethod(String,LuaValue[]) + * @see #invokemethod(LuaValue,LuaValue[]) + * @see #invokemethod(String,Varargs) + * @see #invokemethod(LuaValue,Varargs) + */ + public Varargs invoke(LuaValue[] args,Varargs varargs) { return invoke(varargsOf(args,varargs)); } + + /** Call named method on {@link this} with 0 arguments, including metatag processing, + * and retain all return values in a {@link Varargs}. + *

+ * Look up {@code this[name]} and if it is a {@link LuaFunction}, + * call it inserting {@link this} as an additional first argument, + * and return all return values as a {@link Varargs} instance. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * To get a particular return value, us {@link Varargs#arg(int)} + *

+ * To call {@link this} as a plain call, use {@link #invoke()} instead. + * + * @param name Name of the method to look up for invocation + * @return All values returned from {@code this:name()} as a {@link Varargs} instance + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #call() + * @see #invoke() + * @see #method(String) + * @see #invokemethod(LuaValue) + * @see #invokemethod(String,LuaValue) + */ + public Varargs invokemethod(String name) { return get(name).invoke(this); } + + /** Call named method on {@link this} with 0 arguments, including metatag processing, + * and retain all return values in a {@link Varargs}. + *

+ * Look up {@code this[name]} and if it is a {@link LuaFunction}, + * call it inserting {@link this} as an additional first argument, + * and return all return values as a {@link Varargs} instance. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * To get a particular return value, us {@link Varargs#arg(int)} + *

+ * To call {@link this} as a plain call, use {@link #invoke()} instead. + * + * @param name Name of the method to look up for invocation + * @return All values returned from {@code this:name()} as a {@link Varargs} instance + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #call() + * @see #invoke() + * @see #method(LuaValue) + * @see #invokemethod(String) + * @see #invokemethod(LuaValue,LuaValue) + */ + public Varargs invokemethod(LuaValue name) { return get(name).invoke(this); } + + /** Call named method on {@link this} with 1 argument, including metatag processing, + * and retain all return values in a {@link Varargs}. + *

+ * Look up {@code this[name]} and if it is a {@link LuaFunction}, + * call it inserting {@link this} as an additional first argument, + * and return all return values as a {@link Varargs} instance. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * To get a particular return value, us {@link Varargs#arg(int)} + *

+ * To call {@link this} as a plain call, use {@link #invoke(Varargs)} instead. + * + * @param name Name of the method to look up for invocation + * @param args {@link Varargs} containing arguments to supply to the called function after {@code this} + * @return All values returned from {@code this:name(args)} as a {@link Varargs} instance + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #call() + * @see #invoke(Varargs) + * @see #method(String) + * @see #invokemethod(LuaValue,Varargs) + * @see #invokemethod(String,LuaValue[]) + */ + public Varargs invokemethod(String name, Varargs args) { return get(name).invoke(varargsOf(this,args)); } + + /** Call named method on {@link this} with variable arguments, including metatag processing, + * and retain all return values in a {@link Varargs}. + *

+ * Look up {@code this[name]} and if it is a {@link LuaFunction}, + * call it inserting {@link this} as an additional first argument, + * and return all return values as a {@link Varargs} instance. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * To get a particular return value, us {@link Varargs#arg(int)} + *

+ * To call {@link this} as a plain call, use {@link #invoke(Varargs)} instead. + * + * @param name Name of the method to look up for invocation + * @param args {@link Varargs} containing arguments to supply to the called function after {@code this} + * @return All values returned from {@code this:name(args)} as a {@link Varargs} instance + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #call() + * @see #invoke(Varargs) + * @see #method(String) + * @see #invokemethod(String,Varargs) + * @see #invokemethod(LuaValue,LuaValue[]) + */ + public Varargs invokemethod(LuaValue name, Varargs args) { return get(name).invoke(varargsOf(this,args)); } + + /** Call named method on {@link this} with 1 argument, including metatag processing, + * and retain all return values in a {@link Varargs}. + *

+ * Look up {@code this[name]} and if it is a {@link LuaFunction}, + * call it inserting {@link this} as an additional first argument, + * and return all return values as a {@link Varargs} instance. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * To get a particular return value, us {@link Varargs#arg(int)} + *

+ * To call {@link this} as a plain call, use {@link #invoke(Varargs)} instead. + * + * @param name Name of the method to look up for invocation + * @param args Array of {@link LuaValue} containing arguments to supply to the called function after {@code this} + * @return All values returned from {@code this:name(args)} as a {@link Varargs} instance + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #call() + * @see #invoke(Varargs) + * @see #method(String) + * @see #invokemethod(LuaValue,LuaValue[]) + * @see #invokemethod(String,Varargs) + * @see LuaValue#varargsOf(LuaValue[]) + */ + public Varargs invokemethod(String name, LuaValue[] args) { return get(name).invoke(varargsOf(this,varargsOf(args))); } + + /** Call named method on {@link this} with variable arguments, including metatag processing, + * and retain all return values in a {@link Varargs}. + *

+ * Look up {@code this[name]} and if it is a {@link LuaFunction}, + * call it inserting {@link this} as an additional first argument, + * and return all return values as a {@link Varargs} instance. + * Otherwise, look for the {@link CALL} metatag and call that. + *

+ * To get a particular return value, us {@link Varargs#arg(int)} + *

+ * To call {@link this} as a plain call, use {@link #invoke(Varargs)} instead. + * + * @param name Name of the method to look up for invocation + * @param args Array of {@link LuaValue} containing arguments to supply to the called function after {@code this} + * @return All values returned from {@code this:name(args)} as a {@link Varargs} instance + * @throws LuaError if not a function and {@link CALL} is not defined, + * or the invoked function throws a {@link LuaError} + * or the invoked closure throw a lua {@code error} + * @see #call() + * @see #invoke(Varargs) + * @see #method(String) + * @see #invokemethod(String,LuaValue[]) + * @see #invokemethod(LuaValue,Varargs) + * @see LuaValue#varargsOf(LuaValue[]) + */ + public Varargs invokemethod(LuaValue name, LuaValue[] args) { return get(name).invoke(varargsOf(this,varargsOf(args))); } + + /** + * Get the metatag value for the {@link CALL} metatag, if it exists. + * @return {@link LuaValue} value if metatag is defined + * @throws LuaError if {@link CALL} metatag is not defined. + */ + protected LuaValue callmt() { + return checkmetatag(CALL, "attempt to call "); + } + + /** Unary not: return inverse boolean value {@code (~this)} as defined by lua not operator + * @return {@link TRUE} if {@link NIL} or {@link FALSE}, otherwise {@link FALSE} + */ + public LuaValue not() { return FALSE; } + + /** Unary minus: return negative value {@code (-this)} as defined by lua unary minus operator + * @return boolean inverse as {@link LuaBoolean} if boolean or nil, + * numeric inverse as {@LuaNumber} if numeric, + * or metatag processing result if {@link UNM} metatag is defined + * @throws LuaError if {@code this} is not a table or string, and has no {@link UNM} metatag + */ + public LuaValue neg() { return checkmetatag(UNM, "attempt to perform arithmetic on ").call(this); } + + /** Length operator: return lua length of object {@code (#this)} including metatag processing as java int + * @return length as defined by the lua # operator + * or metatag processing result + * @throws LuaError if {@code this} is not a table or string, and has no {@link LEN} metatag + */ + public LuaValue len() { return checkmetatag(LEN, "attempt to get length of ").call(this); } + + /** Length operator: return lua length of object {@code (#this)} including metatag processing as java int + * @return length as defined by the lua # operator + * or metatag processing result converted to java int using {@link #toint()} + * @throws LuaError if {@code this} is not a table or string, and has no {@link LEN} metatag + */ + public int length() { return len().toint(); } + + /** Implementation of lua 5.0 getn() function. + * @return value of getn() as defined in lua 5.0 spec if {@code this} is a {@link LuaTable} + * @throws LuaError if {@code this} is not a {@link LuaTable} + */ + public LuaValue getn() { return typerror("getn"); } + + // object equality, used for key comparison + public boolean equals(Object obj) { return this == obj; } + + /** Equals: Perform equality comparison with another value + * including metatag processing using {@link EQ}. + * @param val The value to compare with. + * @return {@link TRUE} if values are comparable and {@code (this == rhs)}, + * {@link FALSE} if comparable but not equal, + * {@link LuaValue} if metatag processing occurs. + * @see #eq_b(LuaValue) + * @see #raweq(LuaValue) + * @see #neq(LuaValue) + * @see #eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue) + * @see #EQ + */ + public LuaValue eq( LuaValue val ) { return this == val? TRUE: FALSE; } + + /** Equals: Perform equality comparison with another value + * including metatag processing using {@link EQ}, + * and return java boolean + * @param val The value to compare with. + * @return true if values are comparable and {@code (this == rhs)}, + * false if comparable but not equal, + * result converted to java boolean if metatag processing occurs. + * @see #eq(LuaValue) + * @see #raweq(LuaValue) + * @see #neq_b(LuaValue) + * @see #eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue) + * @see #EQ + */ + public boolean eq_b( LuaValue val ) { return this == val; } + + /** Notquals: Perform inequality comparison with another value + * including metatag processing using {@link EQ}. + * @param val The value to compare with. + * @return {@link TRUE} if values are comparable and {@code (this != rhs)}, + * {@link FALSE} if comparable but equal, + * inverse of {@link LuaValue} converted to {@link LuaBoolean} if metatag processing occurs. + * @see #eq(LuaValue) + * @see #raweq(LuaValue) + * @see #eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue) + * @see #EQ + */ + public LuaValue neq( LuaValue val ) { return eq_b(val)? FALSE: TRUE; } + + /** Notquals: Perform inequality comparison with another value + * including metatag processing using {@link EQ}. + * @param val The value to compare with. + * @return true if values are comparable and {@code (this != rhs)}, + * false if comparable but equal, + * inverse of result converted to boolean if metatag processing occurs. + * @see #eq_b(LuaValue) + * @see #raweq(LuaValue) + * @see #eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue) + * @see #EQ + */ + public boolean neq_b( LuaValue val ) { return !eq_b(val); } + + /** Equals: Perform direct equality comparison with another value + * without metatag processing. + * @param val The value to compare with. + * @return true if {@code (this == rhs)}, false otherwise + * @see #eq(LuaValue) + * @see #raweq(LuaUserdata) + * @see #raweq(LuaString) + * @see #raweq(double) + * @see #raweq(int) + * @see #EQ + */ + public boolean raweq( LuaValue val ) { return this == val; } + + /** Equals: Perform direct equality comparison with a {@link LuaUserdata} value + * without metatag processing. + * @param val The {@link LuaUserdata} to compare with. + * @return true if {@code this} is userdata + * and their metatables are the same using == + * and their instances are equal using {@link #equals(Object)}, + * otherwise false + * @see #eq(LuaValue) + * @see #raweq(LuaValue) + */ + public boolean raweq( LuaUserdata val ) { return false; } + + /** Equals: Perform direct equality comparison with a {@link LuaString} value + * without metatag processing. + * @param val The {@link LuaString} to compare with. + * @return true if {@code this} is a {@link LuaString} + * and their byte sequences match, + * otherwise false + */ + public boolean raweq( LuaString val ) { return false; } + + /** Equals: Perform direct equality comparison with a double value + * without metatag processing. + * @param val The double value to compare with. + * @return true if {@code this} is a {@link LuaNumber} + * whose value equals val, + * otherwise false + */ + public boolean raweq( double val ) { return false; } + + /** Equals: Perform direct equality comparison with a int value + * without metatag processing. + * @param val The double value to compare with. + * @return true if {@code this} is a {@link LuaNumber} + * whose value equals val, + * otherwise false + */ + public boolean raweq( int val ) { return false; } + + /** Perform equality testing metatag processing + * @param lhs left-hand-side of equality expression + * @param lhsmt metatag value for left-hand-side + * @param rhs right-hand-side of equality expression + * @param rhsmt metatag value for right-hand-side + * @return true if metatag processing result is not {@link NIL} or {@link FALSE} + * @throws LuaError if metatag was not defined for either operand + * @see #equals(Object) + * @see #eq(LuaValue) + * @see #raweq(LuaValue) + * @see #EQ + */ + public static final boolean eqmtcall(LuaValue lhs, LuaValue lhsmt, LuaValue rhs, LuaValue rhsmt) { + LuaValue h = lhsmt.rawget(EQ); + return h.isnil() || h!=rhsmt.rawget(EQ)? false: h.call(lhs,rhs).toboolean(); + } + + /** Add: Perform numeric add operation with another value + * including metatag processing. + *

+ * Each operand must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + * + * @param rhs The right-hand-side value to perform the add with + * @return value of {@code (this + rhs)} if both are numeric, + * or {@link LuaValue} if metatag processing occurs + * @throws LuaError if either operand is not a number or string convertible to number, + * and neither has the {@link ADD} metatag defined + * @see #arithmt(LuaValue, LuaValue) + */ + public LuaValue add( LuaValue rhs ) { return arithmt(ADD,rhs); } + + /** Add: Perform numeric add operation with another value + * of double type with metatag processing + *

+ * {@code this} must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + * + * @param rhs The right-hand-side value to perform the add with + * @return value of {@code (this + rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to number + * @see #add(LuaValue) + */ + public LuaValue add(double rhs) { return arithmtwith(ADD,rhs); } + + /** Add: Perform numeric add operation with another value + * of int type with metatag processing + *

+ * {@code this} must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + * + * @param rhs The right-hand-side value to perform the add with + * @return value of {@code (this + rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to number + * @see #add(LuaValue) + */ + public LuaValue add(int rhs) { return add((double)rhs); } + + /** Subtract: Perform numeric subtract operation with another value + * of unknown type, + * including metatag processing. + *

+ * Each operand must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + * + * @param rhs The right-hand-side value to perform the subtract with + * @return value of {@code (this - rhs)} if both are numeric, + * or {@link LuaValue} if metatag processing occurs + * @throws LuaError if either operand is not a number or string convertible to number, + * and neither has the {@link SUB} metatag defined + * @see #arithmt(LuaValue, LuaValue) + */ + public LuaValue sub( LuaValue rhs ) { return arithmt(SUB,rhs); } + + /** Subtract: Perform numeric subtract operation with another value + * of double type with metatag processing + *

+ * {@code this} must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + * + * @param rhs The right-hand-side value to perform the subtract with + * @return value of {@code (this - rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to number + * @see #sub(LuaValue) + */ + public LuaValue sub( double rhs ) { return aritherror("sub"); } + + /** Subtract: Perform numeric subtract operation with another value + * of int type with metatag processing + *

+ * {@code this} must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + * + * @param rhs The right-hand-side value to perform the subtract with + * @return value of {@code (this - rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to number + * @see #sub(LuaValue) + */ + public LuaValue sub( int rhs ) { return aritherror("sub"); } + + /** Reverse-subtract: Perform numeric subtract operation from an int value + * with metatag processing + *

+ * {@code this} must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + * + * @param lhs The left-hand-side value from which to perform the subtraction + * @return value of {@code (lhs - this)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to number + * @see #sub(LuaValue) + * @see #sub(double) + * @see #sub(int) + */ + public LuaValue subFrom(double lhs) { return arithmtwith(SUB,lhs); } + + /** Reverse-subtract: Perform numeric subtract operation from a double value + * without metatag processing + *

+ * {@code this} must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + *

+ * For metatag processing {@link #sub(LuaValue)} must be used + * + * @param lhs The left-hand-side value from which to perform the subtraction + * @return value of {@code (lhs - this)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to number + * @see #sub(LuaValue) + * @see #sub(double) + * @see #sub(int) + */ + public LuaValue subFrom(int lhs) { return subFrom((double)lhs); } + + /** Multiply: Perform numeric multiply operation with another value + * of unknown type, + * including metatag processing. + *

+ * Each operand must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + * + * @param rhs The right-hand-side value to perform the multiply with + * @return value of {@code (this * rhs)} if both are numeric, + * or {@link LuaValue} if metatag processing occurs + * @throws LuaError if either operand is not a number or string convertible to number, + * and neither has the {@link MUL} metatag defined + * @see #arithmt(LuaValue, LuaValue) + */ + public LuaValue mul( LuaValue rhs ) { return arithmt(MUL,rhs); } + + /** Multiply: Perform numeric multiply operation with another value + * of double type with metatag processing + *

+ * {@code this} must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + * + * @param rhs The right-hand-side value to perform the multiply with + * @return value of {@code (this * rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to number + * @see #mul(LuaValue) + */ + public LuaValue mul(double rhs) { return arithmtwith(MUL,rhs); } + + /** Multiply: Perform numeric multiply operation with another value + * of int type with metatag processing + *

+ * {@code this} must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + * + * @param rhs The right-hand-side value to perform the multiply with + * @return value of {@code (this * rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to number + * @see #mul(LuaValue) + */ + public LuaValue mul(int rhs) { return mul((double)rhs); } + + /** Raise to power: Raise this value to a power + * including metatag processing. + *

+ * Each operand must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + * + * @param rhs The power to raise this value to + * @return value of {@code (this ^ rhs)} if both are numeric, + * or {@link LuaValue} if metatag processing occurs + * @throws LuaError if either operand is not a number or string convertible to number, + * and neither has the {@link POW} metatag defined + * @see #arithmt(LuaValue, LuaValue) + */ + public LuaValue pow( LuaValue rhs ) { return arithmt(POW,rhs); } + + /** Raise to power: Raise this value to a power + * of double type with metatag processing + *

+ * {@code this} must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + * + * @param rhs The power to raise this value to + * @return value of {@code (this ^ rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to number + * @see #pow(LuaValue) + */ + public LuaValue pow( double rhs ) { return aritherror("pow"); } + + /** Raise to power: Raise this value to a power + * of int type with metatag processing + *

+ * {@code this} must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + * + * @param rhs The power to raise this value to + * @return value of {@code (this ^ rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to number + * @see #pow(LuaValue) + */ + public LuaValue pow( int rhs ) { return aritherror("pow"); } + + /** Reverse-raise to power: Raise another value of double type to this power + * with metatag processing + *

+ * {@code this} must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + * + * @param lhs The left-hand-side value which will be raised to this power + * @return value of {@code (lhs ^ this)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to number + * @see #pow(LuaValue) + * @see #pow(double) + * @see #pow(int) + */ + public LuaValue powWith(double lhs) { return arithmtwith(POW,lhs); } + + /** Reverse-raise to power: Raise another value of double type to this power + * with metatag processing + *

+ * {@code this} must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + * + * @param lhs The left-hand-side value which will be raised to this power + * @return value of {@code (lhs ^ this)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to number + * @see #pow(LuaValue) + * @see #pow(double) + * @see #pow(int) + */ + public LuaValue powWith(int lhs) { return powWith((double)lhs); } + + /** Divide: Perform numeric divide operation by another value + * of unknown type, + * including metatag processing. + *

+ * Each operand must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + * + * @param rhs The right-hand-side value to perform the divulo with + * @return value of {@code (this / rhs)} if both are numeric, + * or {@link LuaValue} if metatag processing occurs + * @throws LuaError if either operand is not a number or string convertible to number, + * and neither has the {@link DIV} metatag defined + * @see #arithmt(LuaValue, LuaValue) + */ + public LuaValue div( LuaValue rhs ) { return arithmt(DIV,rhs); } + + /** Divide: Perform numeric divide operation by another value + * of double type without metatag processing + *

+ * {@code this} must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + *

+ * For metatag processing {@link #div(LuaValue)} must be used + * + * @param rhs The right-hand-side value to perform the divulo with + * @return value of {@code (this / rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to number + * @see #div(LuaValue) + */ + public LuaValue div( double rhs ) { return aritherror("div"); } + + /** Divide: Perform numeric divide operation by another value + * of int type without metatag processing + *

+ * {@code this} must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + *

+ * For metatag processing {@link #div(LuaValue)} must be used + * + * @param rhs The right-hand-side value to perform the divulo with + * @return value of {@code (this / rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to number + * @see #div(LuaValue) + */ + public LuaValue div( int rhs ) { return aritherror("div"); } + + /** Reverse-divide: Perform numeric divide operation into another value + * with metatag processing + *

+ * {@code this} must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + * + * @param lhs The left-hand-side value which will be divided by this + * @return value of {@code (lhs / this)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to number + * @see #div(LuaValue) + * @see #div(double) + * @see #div(int) + */ + public LuaValue divInto(double lhs) { return arithmtwith(DIV,lhs); } + + /** Modulo: Perform numeric modulo operation with another value + * of unknown type, + * including metatag processing. + *

+ * Each operand must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + * + * @param rhs The right-hand-side value to perform the modulo with + * @return value of {@code (this % rhs)} if both are numeric, + * or {@link LuaValue} if metatag processing occurs + * @throws LuaError if either operand is not a number or string convertible to number, + * and neither has the {@link MOD} metatag defined + * @see #arithmt(LuaValue, LuaValue) + */ + public LuaValue mod( LuaValue rhs ) { return arithmt(MOD,rhs); } + + /** Modulo: Perform numeric modulo operation with another value + * of double type without metatag processing + *

+ * {@code this} must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + *

+ * For metatag processing {@link #mod(LuaValue)} must be used + * + * @param rhs The right-hand-side value to perform the modulo with + * @return value of {@code (this % rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to number + * @see #mod(LuaValue) + */ + public LuaValue mod( double rhs ) { return aritherror("mod"); } + + /** Modulo: Perform numeric modulo operation with another value + * of int type without metatag processing + *

+ * {@code this} must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + *

+ * For metatag processing {@link #mod(LuaValue)} must be used + * + * @param rhs The right-hand-side value to perform the modulo with + * @return value of {@code (this % rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to number + * @see #mod(LuaValue) + */ + public LuaValue mod( int rhs ) { return aritherror("mod"); } + + /** Reverse-modulo: Perform numeric modulo operation from another value + * with metatag processing + *

+ * {@code this} must derive from {@link LuaNumber} + * or derive from {@link LuaString} and be convertible to a number + * + * @param lhs The left-hand-side value which will be modulo'ed by this + * @return value of {@code (lhs % this)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to number + * @see #mod(LuaValue) + * @see #mod(double) + * @see #mod(int) + */ + public LuaValue modFrom(double lhs) { return arithmtwith(MOD,lhs); } + + /** Perform metatag processing for arithmetic operations. + *

+ * Finds the supplied metatag value for {@code this} or {@code op2} and invokes it, + * or throws {@link LuaError} if neither is defined. + * @param tag The metatag to look up + * @param op2 The other operand value to perform the operation with + * @return {@link LuaValue} resulting from metatag processing + * @throws LuaError if metatag was not defined for either operand + * @see #add(LuaValue) + * @see #sub(LuaValue) + * @see #mul(LuaValue) + * @see #pow(LuaValue) + * @see #div(LuaValue) + * @see #mod(LuaValue) + * @see #ADD + * @see #SUB + * @see #MUL + * @see #POW + * @see #DIV + * @see #MOD + */ + protected LuaValue arithmt(LuaValue tag, LuaValue op2) { + LuaValue h = this.metatag(tag); + if ( h.isnil() ) { + h = op2.metatag(tag); + if ( h.isnil() ) + error( "attempt to perform arithmetic "+tag+" on "+typename()+" and "+op2.typename() ); + } + return h.call( this, op2 ); + } + + /** Perform metatag processing for arithmetic operations when the left-hand-side is a number. + *

+ * Finds the supplied metatag value for {@code this} and invokes it, + * or throws {@link LuaError} if neither is defined. + * @param tag The metatag to look up + * @param op1 The value of the left-hand-side to perform the operation with + * @return {@link LuaValue} resulting from metatag processing + * @throws LuaError if metatag was not defined for either operand + * @see #add(LuaValue) + * @see #sub(LuaValue) + * @see #mul(LuaValue) + * @see #pow(LuaValue) + * @see #div(LuaValue) + * @see #mod(LuaValue) + * @see #ADD + * @see #SUB + * @see #MUL + * @see #POW + * @see #DIV + * @see #MOD + */ + protected LuaValue arithmtwith(LuaValue tag, double op1) { + LuaValue h = metatag(tag); + if ( h.isnil() ) + error( "attempt to perform arithmetic "+tag+" on number and "+typename() ); + return h.call( LuaValue.valueOf(op1), this ); + } + + /** Less than: Perform numeric or string comparison with another value + * of unknown type, + * including metatag processing, and returning {@link LuaValue}. + *

+ * To be comparable, both operands must derive from {@link LuaString} + * or both must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return {@link TRUE} if {@code (this < rhs)}, {@link FALSE} if not, + * or {@link LuaValue} if metatag processing occurs + * @throws LuaError if either both operands are not a strings or both are not numbers + * and no {@link LT} metatag is defined. + * @see #gteq_b(LuaValue) + * @see #comparemt(LuaValue, LuaValue) + */ + public LuaValue lt( LuaValue rhs ) { return comparemt(LT,rhs); } + + /** Less than: Perform numeric comparison with another value + * of double type, + * including metatag processing, and returning {@link LuaValue}. + *

+ * To be comparable, this must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return {@link TRUE} if {@code (this < rhs)}, {@link FALSE} if not, + * or {@link LuaValue} if metatag processing occurs + * @throws LuaError if this is not a number + * and no {@link LT} metatag is defined. + * @see #gteq_b(double) + * @see #comparemt(LuaValue, LuaValue) + */ + public LuaValue lt( double rhs ) { return compareerror("number"); } + + /** Less than: Perform numeric comparison with another value + * of int type, + * including metatag processing, and returning {@link LuaValue}. + *

+ * To be comparable, this must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return {@link TRUE} if {@code (this < rhs)}, {@link FALSE} if not, + * or {@link LuaValue} if metatag processing occurs + * @throws LuaError if this is not a number + * and no {@link LT} metatag is defined. + * @see #gteq_b(int) + * @see #comparemt(LuaValue, LuaValue) + */ + public LuaValue lt( int rhs ) { return compareerror("number"); } + + /** Less than: Perform numeric or string comparison with another value + * of unknown type, including metatag processing, + * and returning java boolean. + *

+ * To be comparable, both operands must derive from {@link LuaString} + * or both must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return true if {@code (this < rhs)}, false if not, + * and boolean interpreation of result if metatag processing occurs. + * @throws LuaError if either both operands are not a strings or both are not numbers + * and no {@link LT} metatag is defined. + * @see #gteq(LuaValue) + * @see #comparemt(LuaValue, LuaValue) + */ + public boolean lt_b( LuaValue rhs ) { return comparemt(LT,rhs).toboolean(); } + + /** Less than: Perform numeric comparison with another value + * of int type, + * including metatag processing, + * and returning java boolean. + *

+ * To be comparable, this must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return true if {@code (this < rhs)}, false if not, + * and boolean interpreation of result if metatag processing occurs. + * @throws LuaError if this is not a number + * and no {@link LT} metatag is defined. + * @see #gteq(int) + * @see #comparemt(LuaValue, LuaValue) + */ + public boolean lt_b( int rhs ) { compareerror("number"); return false; } + + /** Less than: Perform numeric or string comparison with another value + * of unknown type, including metatag processing, + * and returning java boolean. + *

+ * To be comparable, both operands must derive from {@link LuaString} + * or both must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return true if {@code (this < rhs)}, false if not, + * and boolean interpreation of result if metatag processing occurs. + * @throws LuaError if either both operands are not a strings or both are not numbers + * and no {@link LT} metatag is defined. + * @see #gteq(LuaValue) + * @see #comparemt(LuaValue, LuaValue) + */ + public boolean lt_b( double rhs ) { compareerror("number"); return false; } + + /** Less than or equals: Perform numeric or string comparison with another value + * of unknown type, + * including metatag processing, and returning {@link LuaValue}. + *

+ * To be comparable, both operands must derive from {@link LuaString} + * or both must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return {@link TRUE} if {@code (this <= rhs)}, {@link FALSE} if not, + * or {@link LuaValue} if metatag processing occurs + * @throws LuaError if either both operands are not a strings or both are not numbers + * and no {@link LE} metatag is defined. + * @see #gteq_b(LuaValue) + * @see #comparemt(LuaValue, LuaValue) + */ + public LuaValue lteq( LuaValue rhs ) { return comparemt(LE,rhs); } + + /** Less than or equals: Perform numeric comparison with another value + * of double type, + * including metatag processing, and returning {@link LuaValue}. + *

+ * To be comparable, this must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return {@link TRUE} if {@code (this <= rhs)}, {@link FALSE} if not, + * or {@link LuaValue} if metatag processing occurs + * @throws LuaError if this is not a number + * and no {@link LE} metatag is defined. + * @see #gteq_b(double) + * @see #comparemt(LuaValue, LuaValue) + */ + public LuaValue lteq( double rhs ) { return compareerror("number"); } + + /** Less than or equals: Perform numeric comparison with another value + * of int type, + * including metatag processing, and returning {@link LuaValue}. + *

+ * To be comparable, this must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return {@link TRUE} if {@code (this <= rhs)}, {@link FALSE} if not, + * or {@link LuaValue} if metatag processing occurs + * @throws LuaError if this is not a number + * and no {@link LE} metatag is defined. + * @see #gteq_b(int) + * @see #comparemt(LuaValue, LuaValue) + */ + public LuaValue lteq( int rhs ) { return compareerror("number"); } + + /** Less than or equals: Perform numeric or string comparison with another value + * of unknown type, including metatag processing, + * and returning java boolean. + *

+ * To be comparable, both operands must derive from {@link LuaString} + * or both must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return true if {@code (this <= rhs)}, false if not, + * and boolean interpreation of result if metatag processing occurs. + * @throws LuaError if either both operands are not a strings or both are not numbers + * and no {@link LE} metatag is defined. + * @see #gteq(LuaValue) + * @see #comparemt(LuaValue, LuaValue) + */ + public boolean lteq_b( LuaValue rhs ) { return comparemt(LE,rhs).toboolean(); } + + /** Less than or equals: Perform numeric comparison with another value + * of int type, + * including metatag processing, + * and returning java boolean. + *

+ * To be comparable, this must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return true if {@code (this <= rhs)}, false if not, + * and boolean interpreation of result if metatag processing occurs. + * @throws LuaError if this is not a number + * and no {@link LE} metatag is defined. + * @see #gteq(int) + * @see #comparemt(LuaValue, LuaValue) + */ + public boolean lteq_b( int rhs ) { compareerror("number"); return false; } + + /** Less than or equals: Perform numeric comparison with another value + * of double type, + * including metatag processing, + * and returning java boolean. + *

+ * To be comparable, this must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return true if {@code (this <= rhs)}, false if not, + * and boolean interpreation of result if metatag processing occurs. + * @throws LuaError if this is not a number + * and no {@link LE} metatag is defined. + * @see #gteq(double) + * @see #comparemt(LuaValue, LuaValue) + */ + public boolean lteq_b( double rhs ) { compareerror("number"); return false; } + + /** Greater than: Perform numeric or string comparison with another value + * of unknown type, + * including metatag processing, and returning {@link LuaValue}. + *

+ * To be comparable, both operands must derive from {@link LuaString} + * or both must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return {@link TRUE} if {@code (this > rhs)}, {@link FALSE} if not, + * or {@link LuaValue} if metatag processing occurs + * @throws LuaError if either both operands are not a strings or both are not numbers + * and no {@link LE} metatag is defined. + * @see #gteq_b(LuaValue) + * @see #comparemt(LuaValue, LuaValue) + */ + public LuaValue gt( LuaValue rhs ) { return rhs.comparemt(LE,this); } + + /** Greater than: Perform numeric comparison with another value + * of double type, + * including metatag processing, and returning {@link LuaValue}. + *

+ * To be comparable, this must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return {@link TRUE} if {@code (this > rhs)}, {@link FALSE} if not, + * or {@link LuaValue} if metatag processing occurs + * @throws LuaError if this is not a number + * and no {@link LE} metatag is defined. + * @see #gteq_b(double) + * @see #comparemt(LuaValue, LuaValue) + */ + public LuaValue gt( double rhs ) { return compareerror("number"); } + + /** Greater than: Perform numeric comparison with another value + * of int type, + * including metatag processing, and returning {@link LuaValue}. + *

+ * To be comparable, this must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return {@link TRUE} if {@code (this > rhs)}, {@link FALSE} if not, + * or {@link LuaValue} if metatag processing occurs + * @throws LuaError if this is not a number + * and no {@link LE} metatag is defined. + * @see #gteq_b(int) + * @see #comparemt(LuaValue, LuaValue) + */ + public LuaValue gt( int rhs ) { return compareerror("number"); } + + /** Greater than: Perform numeric or string comparison with another value + * of unknown type, including metatag processing, + * and returning java boolean. + *

+ * To be comparable, both operands must derive from {@link LuaString} + * or both must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return true if {@code (this > rhs)}, false if not, + * and boolean interpreation of result if metatag processing occurs. + * @throws LuaError if either both operands are not a strings or both are not numbers + * and no {@link LE} metatag is defined. + * @see #gteq(LuaValue) + * @see #comparemt(LuaValue, LuaValue) + */ + public boolean gt_b( LuaValue rhs ) { return rhs.comparemt(LE,this).toboolean(); } + + /** Greater than: Perform numeric comparison with another value + * of int type, + * including metatag processing, + * and returning java boolean. + *

+ * To be comparable, this must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return true if {@code (this > rhs)}, false if not, + * and boolean interpreation of result if metatag processing occurs. + * @throws LuaError if this is not a number + * and no {@link LE} metatag is defined. + * @see #gteq(int) + * @see #comparemt(LuaValue, LuaValue) + */ + public boolean gt_b( int rhs ) { compareerror("number"); return false; } + + /** Greater than: Perform numeric or string comparison with another value + * of unknown type, including metatag processing, + * and returning java boolean. + *

+ * To be comparable, both operands must derive from {@link LuaString} + * or both must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return true if {@code (this > rhs)}, false if not, + * and boolean interpreation of result if metatag processing occurs. + * @throws LuaError if either both operands are not a strings or both are not numbers + * and no {@link LE} metatag is defined. + * @see #gteq(LuaValue) + * @see #comparemt(LuaValue, LuaValue) + */ + public boolean gt_b( double rhs ) { compareerror("number"); return false; } + + /** Greater than or equals: Perform numeric or string comparison with another value + * of unknown type, + * including metatag processing, and returning {@link LuaValue}. + *

+ * To be comparable, both operands must derive from {@link LuaString} + * or both must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return {@link TRUE} if {@code (this >= rhs)}, {@link FALSE} if not, + * or {@link LuaValue} if metatag processing occurs + * @throws LuaError if either both operands are not a strings or both are not numbers + * and no {@link LT} metatag is defined. + * @see #gteq_b(LuaValue) + * @see #comparemt(LuaValue, LuaValue) + */ + public LuaValue gteq( LuaValue rhs ) { return rhs.comparemt(LT,this); } + + /** Greater than or equals: Perform numeric comparison with another value + * of double type, + * including metatag processing, and returning {@link LuaValue}. + *

+ * To be comparable, this must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return {@link TRUE} if {@code (this >= rhs)}, {@link FALSE} if not, + * or {@link LuaValue} if metatag processing occurs + * @throws LuaError if this is not a number + * and no {@link LT} metatag is defined. + * @see #gteq_b(double) + * @see #comparemt(LuaValue, LuaValue) + */ + public LuaValue gteq( double rhs ) { return compareerror("number"); } + + /** Greater than or equals: Perform numeric comparison with another value + * of int type, + * including metatag processing, and returning {@link LuaValue}. + *

+ * To be comparable, this must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return {@link TRUE} if {@code (this >= rhs)}, {@link FALSE} if not, + * or {@link LuaValue} if metatag processing occurs + * @throws LuaError if this is not a number + * and no {@link LT} metatag is defined. + * @see #gteq_b(int) + * @see #comparemt(LuaValue, LuaValue) + */ + public LuaValue gteq( int rhs ) { return valueOf(todouble() >= rhs); } + + /** Greater than or equals: Perform numeric or string comparison with another value + * of unknown type, including metatag processing, + * and returning java boolean. + *

+ * To be comparable, both operands must derive from {@link LuaString} + * or both must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return true if {@code (this >= rhs)}, false if not, + * and boolean interpreation of result if metatag processing occurs. + * @throws LuaError if either both operands are not a strings or both are not numbers + * and no {@link LT} metatag is defined. + * @see #gteq(LuaValue) + * @see #comparemt(LuaValue, LuaValue) + */ + public boolean gteq_b( LuaValue rhs ) { return rhs.comparemt(LT,this).toboolean(); } + + /** Greater than or equals: Perform numeric comparison with another value + * of int type, + * including metatag processing, + * and returning java boolean. + *

+ * To be comparable, this must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return true if {@code (this >= rhs)}, false if not, + * and boolean interpreation of result if metatag processing occurs. + * @throws LuaError if this is not a number + * and no {@link LT} metatag is defined. + * @see #gteq(int) + * @see #comparemt(LuaValue, LuaValue) + */ + public boolean gteq_b( int rhs ) { compareerror("number"); return false; } + + /** Greater than or equals: Perform numeric comparison with another value + * of double type, + * including metatag processing, + * and returning java boolean. + *

+ * To be comparable, this must derive from {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @return true if {@code (this >= rhs)}, false if not, + * and boolean interpreation of result if metatag processing occurs. + * @throws LuaError if this is not a number + * and no {@link LT} metatag is defined. + * @see #gteq(double) + * @see #comparemt(LuaValue, LuaValue) + */ + public boolean gteq_b( double rhs ) { compareerror("number"); return false; } + + /** Perform metatag processing for comparison operations. + *

+ * Finds the supplied metatag value and invokes it, + * or throws {@link LuaError} if none applies. + * @param tag The metatag to look up + * @param rhs The right-hand-side value to perform the operation with + * @return {@link LuaValue} resulting from metatag processing + * @throws LuaError if metatag was not defined for either operand, + * or if the operands are not the same type, + * or the metatag values for the two operands are different. + * @see #gt(LuaValue) + * @see #gteq(LuaValue) + * @see #lt(LuaValue) + * @see #lteq(LuaValue) + */ + public LuaValue comparemt( LuaValue tag, LuaValue op1 ) { + if ( type() == op1.type() ) { + LuaValue h = metatag(tag); + if ( !h.isnil() && h == op1.metatag(tag) ) + return h.call(this, op1); + } + return error("attempt to compare "+tag+" on "+typename()+" and "+op1.typename()); + } + + /** Perform string comparison with another value + * of any type + * using string comparison based on byte values. + *

+ * Only strings can be compared, meaning + * each operand must derive from {@link LuaString}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @returns int < 0 for {@code (this < rhs)}, int > 0 for {@code (this > rhs)}, or 0 when same string. + * @throws LuaError if either operand is not a string + */ + public int strcmp( LuaValue rhs ) { error("attempt to compare "+typename()); return 0; } + + /** Perform string comparison with another value + * known to be a {@link LuaString} + * using string comparison based on byte values. + *

+ * Only strings can be compared, meaning + * each operand must derive from {@link LuaString}. + * + * @param rhs The right-hand-side value to perform the comparison with + * @returns int < 0 for {@code (this < rhs)}, int > 0 for {@code (this > rhs)}, or 0 when same string. + * @throws LuaError if this is not a string + */ + public int strcmp( LuaString rhs ) { error("attempt to compare "+typename()); return 0; } + + /** Concatenate another value onto this value and return the result + * using rules of lua string concatenation including metatag processing. + *

+ * Only strings and numbers as represented can be concatenated, meaning + * each operand must derive from {@link LuaString} or {@link LuaNumber}. + * + * @param rhs The right-hand-side value to perform the operation with + * @returns {@link LuaValue} resulting from concatenation of {@code (this .. rhs)} + * @throws LuaError if either operand is not of an appropriate type, + * such as nil or a table + */ + public LuaValue concat(LuaValue rhs) { return this.concatmt(rhs); } + + /** Reverse-concatenation: concatenate this value onto another value + * whose type is unknwon + * and return the result using rules of lua string concatenation including + * metatag processing. + *

+ * Only strings and numbers as represented can be concatenated, meaning + * each operand must derive from {@link LuaString} or {@link LuaNumber}. + * + * @param lhs The left-hand-side value onto which this will be concatenated + * @returns {@link LuaValue} resulting from concatenation of {@code (lhs .. this)} + * @throws LuaError if either operand is not of an appropriate type, + * such as nil or a table + * @see #concat(LuaValue) + */ + public LuaValue concatTo(LuaValue lhs) { return lhs.concatmt(this); } + + /** Reverse-concatenation: concatenate this value onto another value + * known to be a {@link LuaNumber} + * and return the result using rules of lua string concatenation including + * metatag processing. + *

+ * Only strings and numbers as represented can be concatenated, meaning + * each operand must derive from {@link LuaString} or {@link LuaNumber}. + * + * @param lhs The left-hand-side value onto which this will be concatenated + * @returns {@link LuaValue} resulting from concatenation of {@code (lhs .. this)} + * @throws LuaError if either operand is not of an appropriate type, + * such as nil or a table + * @see #concat(LuaValue) + */ + public LuaValue concatTo(LuaNumber lhs) { return lhs.concatmt(this); } + + /** Reverse-concatenation: concatenate this value onto another value + * known to be a {@link LuaString} + * and return the result using rules of lua string concatenation including + * metatag processing. + *

+ * Only strings and numbers as represented can be concatenated, meaning + * each operand must derive from {@link LuaString} or {@link LuaNumber}. + * + * @param lhs The left-hand-side value onto which this will be concatenated + * @returns {@link LuaValue} resulting from concatenation of {@code (lhs .. this)} + * @throws LuaError if either operand is not of an appropriate type, + * such as nil or a table + * @see #concat(LuaValue) + */ + public LuaValue concatTo(LuaString lhs) { return lhs.concatmt(this); } + + /** Convert the value to a {@link Buffer} for more efficient concatenation of + * multiple strings. + * @return Buffer instance containing the string or number + */ + public Buffer buffer() { return new Buffer(this); } + + /** Concatenate a {@link Buffer} onto this value and return the result + * using rules of lua string concatenation including metatag processing. + *

+ * Only strings and numbers as represented can be concatenated, meaning + * each operand must derive from {@link LuaString} or {@link LuaNumber}. + * + * @param rhs The right-hand-side {@link Buffer} to perform the operation with + * @return LuaString resulting from concatenation of {@code (this .. rhs)} + * @throws LuaError if either operand is not of an appropriate type, + * such as nil or a table + */ + public Buffer concat(Buffer rhs) { return rhs.concatTo(this); } + + /** Perform metatag processing for concatenation operations. + *

+ * Finds the {@link CONCAT} metatag value and invokes it, + * or throws {@link LuaError} if it doesn't exist. + * @param rhs The right-hand-side value to perform the operation with + * @return {@link LuaValue} resulting from metatag processing for {@link CONCAT} metatag. + * @throws LuaError if metatag was not defined for either operand + */ + public LuaValue concatmt(LuaValue rhs) { + LuaValue h=metatag(CONCAT); + if ( h.isnil() && (h=rhs.metatag(CONCAT)).isnil()) + error("attempt to concatenate "+typename()+" and "+rhs.typename()); + return h.call(this,rhs); + } + + /** Perform boolean {@code and} with another operand, based on lua rules for boolean evaluation. + * This returns either {@code this} or {@code rhs} depending on the boolean value for {@code this}. + * + * @param rhs The right-hand-side value to perform the operation with + * @return {@code this} if {@code this.toboolean()} is false, {@code rhs} otherwise. + */ + public LuaValue and( LuaValue rhs ) { return this.toboolean()? rhs: this; } + + /** Perform boolean {@code or} with another operand, based on lua rules for boolean evaluation. + * This returns either {@code this} or {@code rhs} depending on the boolean value for {@code this}. + * + * @param rhs The right-hand-side value to perform the operation with + * @return {@code this} if {@code this.toboolean()} is true, {@code rhs} otherwise. + */ + public LuaValue or( LuaValue rhs ) { return this.toboolean()? this: rhs; } + + /** Perform end-condition test in for-loop processing. + *

+ * Used in lua-bytecode to Java-bytecode conversion. + * + * @param limit the numerical limit to complete the for loop + * @param step the numberical step size to use. + * @return true if limit has not been reached, false otherwise. + */ + public boolean testfor_b(LuaValue limit, LuaValue step) { return step.gt_b(0)? lteq_b(limit): gteq_b(limit); } + + /** + * Convert this value to a string if it is a {@link LuaString} or {@link LuaNumber}, + * or throw a {@link LuaError} if it is not + * @return {@link LuaString} corresponding to the value if a string or number + * @throws LuaError if not a string or number + */ + public LuaString strvalue() { typerror("strValue"); return null; } + + /** Return the key part of this value if it is a weak table entry, or {@link NIL} if it was weak and is no longer referenced. + * @return {@link LuaValue} key, or {@link NIL} if it was weak and is no longer referenced. + * @see WeakTable + */ + public LuaValue strongkey() { return strongvalue(); } + + /** Return this value as a strong reference, or {@link NIL} if it was weak and is no longer referenced. + * @return {@link LuaValue} referred to, or {@link NIL} if it was weak and is no longer referenced. + * @see WeakTable + */ + public LuaValue strongvalue() { return this; } + + /** Test if this is a weak reference and its value no longer is referenced. + * @return true if this is a weak reference whose value no longer is referenced + * @see WeakTable + */ + public boolean isweaknil() { return false; } + + /** Convert java boolean to a {@link LuaValue}. + * + * @param b boolean value to convert + * @return {@link TRUE} if not or {@link FALSE} if false + */ + public static LuaBoolean valueOf(boolean b) { return b? LuaValue.TRUE: FALSE; }; + + /** Convert java int to a {@link LuaValue}. + * + * @param i int value to convert + * @return {@link LuaInteger} instance, possibly pooled, whose value is i + */ + public static LuaInteger valueOf(int i) { return LuaInteger.valueOf(i); } + + /** Convert java double to a {@link LuaValue}. + * This may return a {@link LuaInteger} or {@link LuaDouble} depending + * on the value supplied. + * + * @param d double value to convert + * @return {@link LuaNumber} instance, possibly pooled, whose value is d + */ + public static LuaNumber valueOf(double d) { return LuaDouble.valueOf(d); }; + + /** Convert java string to a {@link LuaValue}. + * + * @param s String value to convert + * @return {@link LuaString} instance, possibly pooled, whose value is s + */ + public static LuaString valueOf(String s) { return LuaString.valueOf(s); } + + /** Convert bytes in an array to a {@link LuaValue}. + * + * @param bytes byte array to convert + * @return {@link LuaString} instance, possibly pooled, whose bytes are those in the supplied array + */ + public static LuaString valueOf(byte[] bytes) { return LuaString.valueOf(bytes); } + + /** Convert bytes in an array to a {@link LuaValue}. + * + * @param bytes byte array to convert + * @param off offset into the byte array, starting at 0 + * @param len number of bytes to include in the {@link LuaString} + * @return {@link LuaString} instance, possibly pooled, whose bytes are those in the supplied array + */ + public static LuaString valueOf(byte[] bytes, int off, int len) { + return LuaString.valueOf(bytes,off,len); + } + + /** Construct an empty {@link LuaTable}. + * @return new {@link LuaTable} instance with no values and no metatable. + */ + public static LuaTable tableOf() { return new LuaTable(); } + + /** Construct a {@link LuaTable} initialized with supplied array values. + * @param varargs {@link Varargs} containing the values to use in initialization + * @param firstarg the index of the first argument to use from the varargs, 1 being the first. + * @return new {@link LuaTable} instance with sequential elements coming from the varargs. + */ + public static LuaTable tableOf(Varargs varargs, int firstarg) { return new LuaTable(varargs,firstarg); } + + /** Construct an empty {@link LuaTable} preallocated to hold array and hashed elements + * @param narray Number of array elements to preallocate + * @param nhash Number of hash elements to preallocate + * @return new {@link LuaTable} instance with no values and no metatable, but preallocated for array and hashed elements. + */ + public static LuaTable tableOf(int narray, int nhash) { return new LuaTable(narray, nhash); } + + /** Construct a {@link LuaTable} initialized with supplied array values. + * @param unnamedValues array of {@link LuaValue} containing the values to use in initialization + * @return new {@link LuaTable} instance with sequential elements coming from the array. + */ + public static LuaTable listOf(LuaValue[] unnamedValues) { return new LuaTable(null,unnamedValues,null); } + + /** Construct a {@link LuaTable} initialized with supplied array values. + * @param unnamedValues array of {@link LuaValue} containing the first values to use in initialization + * @param lastarg {@link Varargs} containing additional values to use in initialization + * to be put after the last unnamedValues element + * @return new {@link LuaTable} instance with sequential elements coming from the array and varargs. + */ + public static LuaTable listOf(LuaValue[] unnamedValues,Varargs lastarg) { return new LuaTable(null,unnamedValues,lastarg); } + + /** Construct a {@link LuaTable} initialized with supplied named values. + * @param namedValues array of {@link LuaValue} containing the keys and values to use in initialization + * in order {@code {key-a, value-a, key-b, value-b, ...} } + * @return new {@link LuaTable} instance with non-sequential keys coming from the supplied array. + */ + public static LuaTable tableOf(LuaValue[] namedValues) { return new LuaTable(namedValues,null,null); } + + /** Construct a {@link LuaTable} initialized with supplied named values and sequential elements. + * The named values will be assigned first, and the sequential elements will be assigned later, + * possibly overwriting named values at the same slot if there are conflicts. + * @param namedValues array of {@link LuaValue} containing the keys and values to use in initialization + * in order {@code {key-a, value-a, key-b, value-b, ...} } + * @param unnamedValues array of {@link LuaValue} containing the sequenctial elements to use in initialization + * in order {@code {value-1, value-2, ...} }, or null if there are none + * @return new {@link LuaTable} instance with named and sequential values supplied. + */ + public static LuaTable tableOf(LuaValue[] namedValues, LuaValue[] unnamedValues) {return new LuaTable(namedValues,unnamedValues,null); } + + /** Construct a {@link LuaTable} initialized with supplied named values and sequential elements in an array part and as varargs. + * The named values will be assigned first, and the sequential elements will be assigned later, + * possibly overwriting named values at the same slot if there are conflicts. + * @param namedValues array of {@link LuaValue} containing the keys and values to use in initialization + * in order {@code {key-a, value-a, key-b, value-b, ...} } + * @param unnamedValues array of {@link LuaValue} containing the first sequenctial elements to use in initialization + * in order {@code {value-1, value-2, ...} }, or null if there are none + * @param lastarg {@link Varargs} containing additional values to use in the sequential part of the initialization, + * to be put after the last unnamedValues element + * @return new {@link LuaTable} instance with named and sequential values supplied. + */ + public static LuaTable tableOf(LuaValue[] namedValues, LuaValue[] unnamedValues, Varargs lastarg) {return new LuaTable(namedValues,unnamedValues,lastarg); } + + /** Construct a LuaUserdata for an object. + * + * @param o The java instance to be wrapped as userdata + * @return {@link LuaUserdata} value wrapping the java instance. + */ + public static LuaUserdata userdataOf(Object o) { return new LuaUserdata(o); } + + /** Construct a LuaUserdata for an object with a user supplied metatable. + * + * @param o The java instance to be wrapped as userdata + * @param metatable The metatble to associate with the userdata instance. + * @return {@link LuaUserdata} value wrapping the java instance. + */ + public static LuaUserdata userdataOf(Object o,LuaValue metatable) { return new LuaUserdata(o,metatable); } + + /** Constant limiting metatag loop processing */ + private static final int MAXTAGLOOP = 100; + + /** + * Return value for field reference including metatag processing, or {@link LuaValue#NIL} if it doesn't exist. + * @param t {@link LuaValue} on which field is being referenced, typically a table or something with the metatag {@link LuaValue#INDEX} defined + * @param key {@link LuaValue} naming the field to reference + * @return {@link LuaValue} for the {@code key} if it exists, or {@link LuaValue#NIL} + * @throws LuaError if there is a loop in metatag processing + */ + /** get value from metatable operations, or NIL if not defined by metatables */ + protected static LuaValue gettable(LuaValue t, LuaValue key) { + LuaValue tm; + int loop = 0; + do { + if (t.istable()) { + LuaValue res = t.rawget(key); + if ((!res.isnil()) || (tm = t.metatag(INDEX)).isnil()) + return res; + } else if ((tm = t.metatag(INDEX)).isnil()) + t.indexerror(); + if (tm.isfunction()) + return tm.call(t, key); + t = tm; + } + while ( ++loop < MAXTAGLOOP ); + error("loop in gettable"); + return NIL; + } + + /** + * Perform field assignment including metatag processing. + * @param t {@link LuaValue} on which value is being set, typically a table or something with the metatag {@link LuaValue#NEWINDEX} defined + * @param key {@link LuaValue} naming the field to assign + * @param value {@link LuaValue} the new value to assign to {@code key} + * @throws LuaError if there is a loop in metatag processing + * @return true if assignment or metatag processing succeeded, false otherwise + */ + protected static boolean settable(LuaValue t, LuaValue key, LuaValue value) { + LuaValue tm; + int loop = 0; + do { + if (t.istable()) { + if ((!t.rawget(key).isnil()) || (tm = t.metatag(NEWINDEX)).isnil()) { + t.rawset(key, value); + return true; + } + } else if ((tm = t.metatag(NEWINDEX)).isnil()) + t.typerror("index"); + if (tm.isfunction()) { + tm.call(t, key, value); + return true; + } + t = tm; + } + while ( ++loop < MAXTAGLOOP ); + error("loop in settable"); + return false; + } + + /** + * Get particular metatag, or return {@link LuaValue#NIL} if it doesn't exist + * @param tag Metatag name to look up, typically a string such as + * {@link LuaValue#INDEX} or {@link LuaValue#NEWINDEX} + * @param reason Description of error when tag lookup fails. + * @return {@link LuaValue} for tag {@code reason}, or {@link LuaValue#NIL} + */ + public LuaValue metatag(LuaValue tag) { + LuaValue mt = getmetatable(); + if ( mt == null ) + return NIL; + return mt.rawget(tag); + } + + /** + * Get particular metatag, or throw {@link LuaError} if it doesn't exist + * @param tag Metatag name to look up, typically a string such as + * {@link LuaValue#INDEX} or {@link LuaValue#NEWINDEX} + * @param reason Description of error when tag lookup fails. + * @return {@link LuaValue} that can be called + * @throws LuaError when the lookup fails. + */ + protected LuaValue checkmetatag(LuaValue tag, String reason) { + LuaValue h = this.metatag(tag); + if ( h.isnil() ) + throw new LuaError(reason+typename()); + return h; + } + + /** Throw {@link LuaError} indicating index was attempted on illegal type + * @throws LuaError when called. + */ + private void indexerror() { + error( "attempt to index ? (a "+typename()+" value)" ); + } + + /** Construct a {@link Varargs} around an array of {@link LuaValue}s. + * + * @param v The array of {@link LuaValue}s + * @param more {@link Varargs} contain values to include at the end + * @return {@link Varargs} wrapping the supplied values. + * @see LuaValue#varargsOf(LuaValue, Varargs) + * @see LuaValue#varargsOf(LuaValue[], int, int) + */ + public static Varargs varargsOf(final LuaValue[] v) { + switch ( v.length ) { + case 0: return NONE; + case 1: return v[0]; + case 2: return new PairVarargs(v[0],v[1]); + default: return new ArrayVarargs(v,NONE); + } + } + + /** Construct a {@link Varargs} around an array of {@link LuaValue}s. + * + * @param v The array of {@link LuaValue}s + * @param more {@link Varargs} contain values to include at the end + * @return {@link Varargs} wrapping the supplied values. + * @see LuaValue#varargsOf(LuaValue[]) + * @see LuaValue#varargsOf(LuaValue[], int, int, Varargs) + */ + public static Varargs varargsOf(final LuaValue[] v,Varargs r) { + switch ( v.length ) { + case 0: return r; + case 1: return new PairVarargs(v[0],r); + default: return new ArrayVarargs(v,r); + } + } + + /** Construct a {@link Varargs} around an array of {@link LuaValue}s. + * + * @param v The array of {@link LuaValue}s + * @param offset number of initial values to skip in the array + * @param length number of values to include from the array + * @return {@link Varargs} wrapping the supplied values. + * @see LuaValue#varargsOf(LuaValue[]) + * @see LuaValue#varargsOf(LuaValue[], int, int, Varargs) + */ + public static Varargs varargsOf(final LuaValue[] v, final int offset, final int length) { + switch ( length ) { + case 0: return NONE; + case 1: return v[offset]; + case 2: return new PairVarargs(v[offset+0],v[offset+1]); + default: return new ArrayPartVarargs(v,offset,length); + } + } + + /** Construct a {@link Varargs} around an array of {@link LuaValue}s. + * + * @param v The array of {@link LuaValue}s + * @param offset number of initial values to skip in the array + * @param length number of values to include from the array + * @param more {@link Varargs} contain values to include at the end + * @return {@link Varargs} wrapping the supplied values. + * @see LuaValue#varargsOf(LuaValue[], Varargs) + * @see LuaValue#varargsOf(LuaValue[], int, int) + */ + public static Varargs varargsOf(final LuaValue[] v, final int offset, final int length,Varargs more) { + switch ( length ) { + case 0: return more; + case 1: return new PairVarargs(v[offset],more); + default: return new ArrayPartVarargs(v,offset,length,more); + } + } + + /** Construct a {@link Varargs} around a set of 2 or more {@link LuaValue}s. + *

+ * This can be used to wrap exactly 2 values, or a list consisting of 1 initial value + * followed by another variable list of remaining values. + * + * @param v1 First {@link LuaValue} in the {@link Varargs} + * @param v2 {@link LuaValue} supplying the 2rd value, + * or {@link Varargs}s supplying all values beyond the first + * @return {@link Varargs} wrapping the supplied values. + */ + public static Varargs varargsOf(LuaValue v, Varargs r) { + switch ( r.narg() ) { + case 0: return v; + default: return new PairVarargs(v,r); + } + } + + /** Construct a {@link Varargs} around a set of 3 or more {@link LuaValue}s. + *

+ * This can be used to wrap exactly 3 values, or a list consisting of 2 initial values + * followed by another variable list of remaining values. + * + * @param v1 First {@link LuaValue} in the {@link Varargs} + * @param v2 Second {@link LuaValue} in the {@link Varargs} + * @param v3 {@link LuaValue} supplying the 3rd value, + * or {@link Varargs}s supplying all values beyond the second + * @return {@link Varargs} wrapping the supplied values. + */ + public static Varargs varargsOf(LuaValue v1,LuaValue v2,Varargs v3) { + switch ( v3.narg() ) { + case 0: return new PairVarargs(v1,v2); + default: return new ArrayVarargs(new LuaValue[] {v1,v2},v3); + } + } + + /** Construct a {@link TailcallVarargs} around a function and arguments. + *

+ * The tail call is not yet called or processing until the client invokes + * {@link TailcallVarargs#eval()} which performs the tail call processing. + *

+ * This method is typically not used directly by client code. + * Instead use one of the function invocation methods. + * + * @param func {@link LuaValue} to be called as a tail call + * @param args {@link Varargs} containing the arguments to the call + * @return {@link TailcallVarargs} to be used in tailcall oprocessing. + * @see LuaValue#call() + * @see LuaValue#invoke() + * @see LuaValue#method(LuaValue) + * @see LuaValue#invokemethod(LuaValue) + */ + public static Varargs tailcallOf(LuaValue func, Varargs args) { + return new TailcallVarargs(func, args); + } + + /** + * Callback used during tail call processing to invoke the function once. + *

+ * This may return a {@link TailcallVarargs} to be evaluated by the client. + *

+ * This should not be called directly, instead use on of the call invocation functions. + * + * @param args the arguments to the call invocation. + * @return Varargs the return values, possible a TailcallVarargs. + * @see LuaValue#call() + * @see LuaValue#invoke() + * @see LuaValue#method(LuaValue) + * @see LuaValue#invokemethod(LuaValue) + */ + public Varargs onInvoke(Varargs args) { + return invoke(args); + } + + /** Varargs implemenation with no values. + *

+ * This is an internal class not intended to be used directly. + * Instead use the predefined constant {@link LuaValue#NONE} + * + * @see LuaValue#NONE + */ + private static final class None extends LuaNil { + static None _NONE = new None(); + public LuaValue arg(int i) { return NIL; } + public int narg() { return 0; } + public LuaValue arg1() { return NIL; } + public String tojstring() { return "none"; } + } + + /** Varargs implemenation backed by an array of LuaValues + *

+ * This is an internal class not intended to be used directly. + * Instead use the corresponding static methods on LuaValue. + * + * @see LuaValue#varargsOf(LuaValue[]) + * @see LuaValue#varargsOf(LuaValue[], Varargs) + */ + static final class ArrayVarargs extends Varargs { + private final LuaValue[] v; + private final Varargs r; + /** Construct a Varargs from an array of LuaValue. + *

+ * This is an internal class not intended to be used directly. + * Instead use the corresponding static methods on LuaValue. + * + * @see LuaValue#varargsOf(LuaValue[]) + * @see LuaValue#varargsOf(LuaValue[], Varargs) + */ + ArrayVarargs(LuaValue[] v, Varargs r) { + this.v = v; + this.r = r ; + } + public LuaValue arg(int i) { + return i >=1 && i<=v.length? v[i - 1]: r.arg(i-v.length); + } + public int narg() { + return v.length+r.narg(); + } + public LuaValue arg1() { return v.length>0? v[0]: r.arg1(); } + } + + /** Varargs implemenation backed by an array of LuaValues + *

+ * This is an internal class not intended to be used directly. + * Instead use the corresponding static methods on LuaValue. + * + * @see LuaValue#varargsOf(LuaValue[], int, int) + * @see LuaValue#varargsOf(LuaValue[], int, int, Varargs) + */ + static final class ArrayPartVarargs extends Varargs { + private final int offset; + private final LuaValue[] v; + private final int length; + private final Varargs more; + /** Construct a Varargs from an array of LuaValue. + *

+ * This is an internal class not intended to be used directly. + * Instead use the corresponding static methods on LuaValue. + * + * @see LuaValue#varargsOf(LuaValue[], int, int) + */ + ArrayPartVarargs(LuaValue[] v, int offset, int length) { + this.v = v; + this.offset = offset; + this.length = length; + this.more = NONE; + } + /** Construct a Varargs from an array of LuaValue and additional arguments. + *

+ * This is an internal class not intended to be used directly. + * Instead use the corresponding static method on LuaValue. + * + * @see LuaValue#varargsOf(LuaValue[], int, int, Varargs) + */ + public ArrayPartVarargs(LuaValue[] v, int offset, int length, Varargs more) { + this.v = v; + this.offset = offset; + this.length = length; + this.more = more; + } + public LuaValue arg(int i) { + return i>=1&&i<=length? v[i+offset-1]: more.arg(i-length); + } + public int narg() { + return length + more.narg(); + } + public LuaValue arg1() { + return length>0? v[offset]: more.arg1(); + } + } + + /** Varargs implemenation backed by two values. + *

+ * This is an internal class not intended to be used directly. + * Instead use the corresponding static method on LuaValue. + * + * @see LuaValue#varargsOf(LuaValue, Varargs) + */ + static final class PairVarargs extends Varargs { + private final LuaValue v1; + private final Varargs v2; + /** Construct a Varargs from an two LuaValue. + *

+ * This is an internal class not intended to be used directly. + * Instead use the corresponding static method on LuaValue. + * + * @see LuaValue#varargsOf(LuaValue, Varargs) + */ + PairVarargs(LuaValue v1, Varargs v2) { + this.v1 = v1; + this.v2 = v2; + } + public LuaValue arg(int i) { + return i==1? v1: v2.arg(i-1); + } + public int narg() { + return 1+v2.narg(); + } + public LuaValue arg1() { + return v1; + } + } + +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/OrphanedThread.java b/luaj-2.0.3/src/core/org/luaj/vm2/OrphanedThread.java new file mode 100644 index 0000000000..668217be3e --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/OrphanedThread.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2012 Luaj.org. 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. + ******************************************************************************/ +package org.luaj.vm2; + +/** + * {@link java.lang.Error} sublcass that indicates a lua thread that is no + * longer referenced has been detected. + *

+ * The java thread in which this is thrown should correspond to a + * {@link LuaThread} being used as a coroutine that could not possibly be + * resumed again because there are no more references to the LuaThread with + * which it is associated. Rather than locking up resources forever, this error + * is thrown, and should fall through all the way to the thread's {@link Thread.run}() method. + *

+ * Java code mixed with the luaj vm should not catch this error because it may + * occur when the coroutine is not running, so any processing done during error + * handling could break the thread-safety of the application because other lua + * processing could be going on in a different thread. + */ +public class OrphanedThread extends Error { + + public OrphanedThread() { + super("orphaned thread"); + } +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/Print.java b/luaj-2.0.3/src/core/org/luaj/vm2/Print.java new file mode 100644 index 0000000000..72c2f8f92b --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/Print.java @@ -0,0 +1,417 @@ +/******************************************************************************* +* Copyright (c) 2009 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +/** + * Debug helper class to pretty-print lua bytecodes. + * @see Prototype + * @see LuaClosure + */ +public class Print extends Lua { + + /** opcode names */ + private static final String STRING_FOR_NULL = "null"; + public static PrintStream ps = System.out; + + public static final String[] OPNAMES = { + "MOVE", + "LOADK", + "LOADBOOL", + "LOADNIL", + "GETUPVAL", + "GETGLOBAL", + "GETTABLE", + "SETGLOBAL", + "SETUPVAL", + "SETTABLE", + "NEWTABLE", + "SELF", + "ADD", + "SUB", + "MUL", + "DIV", + "MOD", + "POW", + "UNM", + "NOT", + "LEN", + "CONCAT", + "JMP", + "EQ", + "LT", + "LE", + "TEST", + "TESTSET", + "CALL", + "TAILCALL", + "RETURN", + "FORLOOP", + "FORPREP", + "TFORLOOP", + "SETLIST", + "CLOSE", + "CLOSURE", + "VARARG", + null, + }; + + + static void printString(PrintStream ps, final LuaString s) { + + ps.print('"'); + for (int i = 0, n = s.m_length; i < n; i++) { + int c = s.m_bytes[s.m_offset+i]; + if ( c >= ' ' && c <= '~' && c != '\"' && c != '\\' ) + ps.print((char) c); + else { + switch (c) { + case '"': + ps.print("\\\""); + break; + case '\\': + ps.print("\\\\"); + break; + case 0x0007: /* bell */ + ps.print("\\a"); + break; + case '\b': /* backspace */ + ps.print("\\b"); + break; + case '\f': /* form feed */ + ps.print("\\f"); + break; + case '\t': /* tab */ + ps.print("\\t"); + break; + case '\r': /* carriage return */ + ps.print("\\r"); + break; + case '\n': /* newline */ + ps.print("\\n"); + break; + case 0x000B: /* vertical tab */ + ps.print("\\v"); + break; + default: + ps.print('\\'); + ps.print(Integer.toString(1000 + 0xff&c).substring(1)); + break; + } + } + } + ps.print('"'); + } + + static void printValue( PrintStream ps, LuaValue v ) { + switch ( v.type() ) { + case LuaValue.TSTRING: printString( ps, (LuaString) v ); break; + default: ps.print( v.tojstring() ); + + } + } + + static void printConstant(PrintStream ps, Prototype f, int i) { + printValue( ps, f.k[i] ); + } + + /** + * Print the code in a prototype + * @param f the {@link Prototype} + */ + public static void printCode(Prototype f) { + int[] code = f.code; + int pc, n = code.length; + for (pc = 0; pc < n; pc++) { + printOpCode(f, pc); + ps.println(); + } + } + + /** + * Print an opcode in a prototype + * @param f the {@link Prototype} + * @param pc the program counter to look up and print + */ + public static void printOpCode(Prototype f, int pc) { + printOpCode(ps,f,pc); + } + + /** + * Print an opcode in a prototype + * @param ps the {@link PrintStream} to print to + * @param f the {@link Prototype} + * @param pc the program counter to look up and print + */ + public static void printOpCode(PrintStream ps, Prototype f, int pc) { + int[] code = f.code; + int i = code[pc]; + int o = GET_OPCODE(i); + int a = GETARG_A(i); + int b = GETARG_B(i); + int c = GETARG_C(i); + int bx = GETARG_Bx(i); + int sbx = GETARG_sBx(i); + int line = getline(f, pc); + ps.print(" " + (pc + 1) + " "); + if (line > 0) + ps.print("[" + line + "] "); + else + ps.print("[-] "); + ps.print(OPNAMES[o] + " "); + switch (getOpMode(o)) { + case iABC: + ps.print( a ); + if (getBMode(o) != OpArgN) + ps.print(" "+(ISK(b) ? (-1 - INDEXK(b)) : b)); + if (getCMode(o) != OpArgN) + ps.print(" "+(ISK(c) ? (-1 - INDEXK(c)) : c)); + break; + case iABx: + if (getBMode(o) == OpArgK) { + ps.print(a + " " + (-1 - bx)); + } else { + ps.print(a + " " + (bx)); + } + break; + case iAsBx: + if (o == OP_JMP) + ps.print( sbx ); + else + ps.print(a + " " + sbx); + break; + } + switch (o) { + case OP_LOADK: + ps.print(" ; "); + printConstant(ps, f, bx); + break; + case OP_GETUPVAL: + case OP_SETUPVAL: + ps.print(" ; "); + if ( f.upvalues.length > b ) + printValue(ps, f.upvalues[b]); + else + ps.print( "-" ); + break; + case OP_GETGLOBAL: + case OP_SETGLOBAL: + ps.print(" ; "); + printConstant( ps, f, bx ); + break; + case OP_GETTABLE: + case OP_SELF: + if (ISK(c)) { + ps.print(" ; "); + printConstant(ps, f, INDEXK(c)); + } + break; + case OP_SETTABLE: + case OP_ADD: + case OP_SUB: + case OP_MUL: + case OP_DIV: + case OP_POW: + case OP_EQ: + case OP_LT: + case OP_LE: + if (ISK(b) || ISK(c)) { + ps.print(" ; "); + if (ISK(b)) + printConstant(ps, f, INDEXK(b)); + else + ps.print("-"); + ps.print(" "); + if (ISK(c)) + printConstant(ps, f, INDEXK(c)); + else + ps.print("-"); + } + break; + case OP_JMP: + case OP_FORLOOP: + case OP_FORPREP: + ps.print(" ; to " + (sbx + pc + 2)); + break; + case OP_CLOSURE: + ps.print(" ; " + f.p[bx].getClass().getName()); + break; + case OP_SETLIST: + if (c == 0) + ps.print(" ; " + ((int) code[++pc])); + else + ps.print(" ; " + ((int) c)); + break; + case OP_VARARG: + ps.print( " ; is_vararg="+ f.is_vararg ); + break; + default: + break; + } + } + + private static int getline(Prototype f, int pc) { + return pc>0 && f.lineinfo!=null && pc (" + f.code.length + " instructions, " + + f.code.length * 4 + " bytes at " + id(f) + ")\n"); + ps.print(f.numparams + " param, " + f.maxstacksize + " slot, " + + f.upvalues.length + " upvalue, "); + ps.print(f.locvars.length + " local, " + f.k.length + + " constant, " + f.p.length + " function\n"); + } + + static void printConstants(Prototype f) { + int i, n = f.k.length; + ps.print("constants (" + n + ") for " + id(f) + ":\n"); + for (i = 0; i < n; i++) { + ps.print(" " + (i + 1) + " "); + printValue( ps, f.k[i] ); + ps.print( "\n"); + } + } + + static void printLocals(Prototype f) { + int i, n = f.locvars.length; + ps.print("locals (" + n + ") for " + id(f) + ":\n"); + for (i = 0; i < n; i++) { + ps.println(" "+i+" "+f.locvars[i].varname+" "+(f.locvars[i].startpc+1)+" "+(f.locvars[i].endpc+1)); + } + } + + static void printUpValues(Prototype f) { + int i, n = f.upvalues.length; + ps.print("upvalues (" + n + ") for " + id(f) + ":\n"); + for (i = 0; i < n; i++) { + ps.print(" " + i + " " + f.upvalues[i] + "\n"); + } + } + + public static void print(Prototype p) { + printFunction(p, true); + } + + public static void printFunction(Prototype f, boolean full) { + int i, n = f.p.length; + printHeader(f); + printCode(f); + if (full) { + printConstants(f); + printLocals(f); + printUpValues(f); + } + for (i = 0; i < n; i++) + printFunction(f.p[i], full); + } + + private static void format( String s, int maxcols ) { + int n = s.length(); + if ( n > maxcols ) + ps.print( s.substring(0,maxcols) ); + else { + ps.print( s ); + for ( int i=maxcols-n; --i>=0; ) + ps.print( ' ' ); + } + } + + private static String id(Prototype f) { + return "Proto"; + } + private void _assert(boolean b) { + if ( !b ) + throw new NullPointerException("_assert failed"); + } + + /** + * Print the state of a {@link LuaClosure} that is being executed + * @param cl the {@link LuaClosure} + * @param pc the program counter + * @param stack the stack of {@link LuaValue} + * @param top the top of the stack + * @param varargs any {@link Varargs} value that may apply + */ + public static void printState(LuaClosure cl, int pc, LuaValue[] stack, int top, Varargs varargs) { + // print opcode into buffer + PrintStream previous = ps; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ps = new PrintStream( baos ); + printOpCode( cl.p, pc ); + ps.flush(); + ps.close(); + ps = previous; + format( baos.toString(), 50 ); + + // print stack + ps.print('['); + for ( int i=0; i + * This is both a straight translation of the corresponding C type, + * and the main data structure for execution of compiled lua bytecode. + *

+ * See documentatation on {@link LuaClosure} for information on how to load + * and execute a {@link Prototype}. + * @see LuaClosure + */ + +public class Prototype { + /* constants used by the function */ + public LuaValue[] k; + public int[] code; + /* functions defined inside the function */ + public Prototype[] p; + /* map from opcodes to source lines */ + public int[] lineinfo; + /* information about local variables */ + public LocVars[] locvars; + /* upvalue names */ + public LuaString[] upvalues; + public LuaString source; + public int nups; + public int linedefined; + public int lastlinedefined; + public int numparams; + public int is_vararg; + public int maxstacksize; + + + public String toString() { + return source + ":" + linedefined+"-"+lastlinedefined; + } + + /** Get the name of a local variable. + * + * @param number the local variable number to look up + * @param pc the program counter + * @return the name, or null if not found + */ + public LuaString getlocalname(int number, int pc) { + int i; + for (i = 0; i + * Since Java doesn't have direct support for tail calls, + * any lua function whose {@link Prototype} contains the + * {@link Lua#OP_TAILCALL} bytecode needs a mechanism + * for tail calls when converting lua-bytecode to java-bytecode. + *

+ * The tail call holds the next function and arguments, + * and the client a call to {@link #eval()} executes the function + * repeatedly until the tail calls are completed. + *

+ * Normally, users of luaj need not concern themselves with the + * details of this mechanism, as it is built into the core + * execution framework. + * @see Prototype + * @see LuaJC + */ +public class TailcallVarargs extends Varargs { + + private LuaValue func; + private Varargs args; + private Varargs result; + + public TailcallVarargs(LuaValue f, Varargs args) { + this.func = f; + this.args = args; + } + + public TailcallVarargs(LuaValue object, LuaValue methodname, Varargs args) { + this.func = object.get(methodname); + this.args = LuaValue.varargsOf(object, args); + } + + public boolean isTailcall() { + return true; + } + + public Varargs eval() { + while ( result == null ) { + Varargs r = func.onInvoke(args); + if (r.isTailcall()) { + TailcallVarargs t = (TailcallVarargs) r; + func = t.func; + args = t.args; + } + else { + result = r; + func = null; + args = null; + } + } + return result; + } + + public LuaValue arg( int i ) { + if ( result == null ) + eval(); + return result.arg(i); + } + + public LuaValue arg1() { + if (result == null) + eval(); + return result.arg1(); + } + + public int narg() { + if (result == null) + eval(); + return result.narg(); + } +} \ No newline at end of file diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/UpValue.java b/luaj-2.0.3/src/core/org/luaj/vm2/UpValue.java new file mode 100644 index 0000000000..072dd34841 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/UpValue.java @@ -0,0 +1,77 @@ +/******************************************************************************* +* Copyright (c) 2009-2011 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2; + + +/** Upvalue used with Closure formulation + *

+ * @see LuaClosure + * @see Prototype + */ +public final class UpValue { + + LuaValue[] array; // initially the stack, becomes a holder + int index; + + /** + * Create an upvalue relative to a stack + * @param stack the stack + * @param index the index on the stack for the upvalue + */ + public UpValue( LuaValue[] stack, int index) { + this.array = stack; + this.index = index; + } + + /** + * Convert this upvalue to a Java String + * @return the Java String for this upvalue. + * @see LuaValue#tojstring() + */ + public String tojstring() { + return array[index].tojstring(); + } + + /** + * Get the value of the upvalue + * @return the {@link LuaValue} for this upvalue + */ + public final LuaValue getValue() { + return array[index]; + } + + /** + * Set the value of the upvalue + * @param the {@link LuaValue} to set it to + */ + public final void setValue( LuaValue value ) { + array[index] = value; + } + + /** + * Close this upvalue so it is no longer on the stack + */ + public final void close() { + array = new LuaValue[] { array[index] }; + index = 0; + } +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/Varargs.java b/luaj-2.0.3/src/core/org/luaj/vm2/Varargs.java new file mode 100644 index 0000000000..340bdd20ca --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/Varargs.java @@ -0,0 +1,537 @@ +/******************************************************************************* +* Copyright (c) 2009 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2; + +/** + * Class to encapsulate varargs values, either as part of a variable argument list, or multiple return values. + *

+ * To construct varargs, use one of the static methods such as + * {@code LuaValue.varargsOf(LuaValue,LuaValue)} + *

+ *

+ * Any LuaValue can be used as a stand-in for Varargs, for both calls and return values. + * When doing so, nargs() will return 1 and arg1() or arg(1) will return this. + * This simplifies the case when calling or implementing varargs functions with only + * 1 argument or 1 return value. + *

+ * Varargs can also be derived from other varargs by appending to the front with a call + * such as {@code LuaValue.varargsOf(LuaValue,Varargs)} + * or by taking a portion of the args using {@code Varargs.subargs(int start)} + *

+ * @see LuaValue#varargsOf(LuaValue[]) + * @see LuaValue#varargsOf(LuaValue, Varargs) + * @see LuaValue#varargsOf(LuaValue[], Varargs) + * @see LuaValue#varargsOf(LuaValue, LuaValue, Varargs) + * @see LuaValue#varargsOf(LuaValue[], int, int) + * @see LuaValue#varargsOf(LuaValue[], int, int, Varargs) + * @see LuaValue#subargs(int) + */ +public abstract class Varargs { + + /** + * Get the n-th argument value (1-based). + * @param i the index of the argument to get, 1 is the first argument + * @return Value at position i, or LuaValue.NIL if there is none. + * @see Varargs#arg1() + * @see LuaValue#NIL + */ + abstract public LuaValue arg( int i ); + + /** + * Get the number of arguments, or 0 if there are none. + * @return number of arguments. + */ + abstract public int narg(); + + /** + * Get the first argument in the list. + * @return LuaValue which is first in the list, or LuaValue.NIL if there are no values. + * @see Varargs#arg(int) + * @see LuaValue#NIL + */ + abstract public LuaValue arg1(); + + /** + * Evaluate any pending tail call and return result. + * @return the evaluated tail call result + */ + public Varargs eval() { return this; } + + /** + * Return true if this is a TailcallVarargs + * @return true if a tail call, false otherwise + */ + public boolean isTailcall() { + return false; + } + + // ----------------------------------------------------------------------- + // utilities to get specific arguments and type-check them. + // ----------------------------------------------------------------------- + + /** Gets the type of argument {@code i} + * @param i the index of the argument to convert, 1 is the first argument + * @return int value corresponding to one of the LuaValue integer type values + * @see LuaValue.TNIL + * @see LuaValue.TBOOLEAN + * @see LuaValue.TNUMBER + * @see LuaValue.TSTRING + * @see LuaValue.TTABLE + * @see LuaValue.TFUNCTION + * @see LuaValue.TUSERDATA + * @see LuaValue.TTHREAD + * */ + public int type(int i) { return arg(i).type(); } + + /** Tests if argument i is nil. + * @param i the index of the argument to test, 1 is the first argument + * @return true if the argument is nil or does not exist, false otherwise + * @see LuaValue.TNIL + * */ + public boolean isnil(int i) { return arg(i).isnil(); } + + /** Tests if argument i is a function. + * @param i the index of the argument to test, 1 is the first argument + * @return true if the argument exists and is a function or closure, false otherwise + * @see LuaValue.TFUNCTION + * */ + public boolean isfunction(int i) { return arg(i).isfunction(); } + + /** Tests if argument i is a number. + * Since anywhere a number is required, a string can be used that + * is a number, this will return true for both numbers and + * strings that can be interpreted as numbers. + * @param i the index of the argument to test, 1 is the first argument + * @return true if the argument exists and is a number or + * string that can be interpreted as a number, false otherwise + * @see LuaValue.TNUMBER + * @see LuaValue.TSTRING + * */ + public boolean isnumber(int i) { return arg(i).isnumber(); } + + /** Tests if argument i is a string. + * Since all lua numbers can be used where strings are used, + * this will return true for both strings and numbers. + * @param i the index of the argument to test, 1 is the first argument + * @return true if the argument exists and is a string or number, false otherwise + * @see LuaValue.TNUMBER + * @see LuaValue.TSTRING + * */ + public boolean isstring(int i) { return arg(i).isstring(); } + + /** Tests if argument i is a table. + * @param i the index of the argument to test, 1 is the first argument + * @return true if the argument exists and is a lua table, false otherwise + * @see LuaValue.TTABLE + * */ + public boolean istable(int i) { return arg(i).istable(); } + + /** Tests if argument i is a thread. + * @param i the index of the argument to test, 1 is the first argument + * @return true if the argument exists and is a lua thread, false otherwise + * @see LuaValue.TTHREAD + * */ + public boolean isthread(int i) { return arg(i).isthread(); } + + /** Tests if argument i is a userdata. + * @param i the index of the argument to test, 1 is the first argument + * @return true if the argument exists and is a userdata, false otherwise + * @see LuaValue.TUSERDATA + * */ + public boolean isuserdata(int i) { return arg(i).isuserdata(); } + + /** Tests if a value exists at argument i. + * @param i the index of the argument to test, 1 is the first argument + * @return true if the argument exists, false otherwise + * */ + public boolean isvalue(int i) { return i>0 && i<=narg(); } + + /** Return argument i as a boolean value, {@code defval} if nil, or throw a LuaError if any other type. + * @param i the index of the argument to test, 1 is the first argument + * @return true if argument i is boolean true, false if it is false, or defval if not supplied or nil + * @exception LuaError if the argument is not a lua boolean + * */ + public boolean optboolean(int i, boolean defval) { return arg(i).optboolean(defval); } + + /** Return argument i as a closure, {@code defval} if nil, or throw a LuaError if any other type. + * @param i the index of the argument to test, 1 is the first argument + * @return LuaClosure if argument i is a closure, or defval if not supplied or nil + * @exception LuaError if the argument is not a lua closure + * */ + public LuaClosure optclosure(int i, LuaClosure defval) { return arg(i).optclosure(defval); } + + /** Return argument i as a double, {@code defval} if nil, or throw a LuaError if it cannot be converted to one. + * @param i the index of the argument to test, 1 is the first argument + * @return java double value if argument i is a number or string that converts to a number, or defval if not supplied or nil + * @exception LuaError if the argument is not a number + * */ + public double optdouble(int i, double defval) { return arg(i).optdouble(defval); } + + /** Return argument i as a function, {@code defval} if nil, or throw a LuaError if an incompatible type. + * @param i the index of the argument to test, 1 is the first argument + * @return LuaValue that can be called if argument i is lua function or closure, or defval if not supplied or nil + * @exception LuaError if the argument is not a lua function or closure + * */ + public LuaFunction optfunction(int i, LuaFunction defval) { return arg(i).optfunction(defval); } + + /** Return argument i as a java int value, discarding any fractional part, {@code defval} if nil, or throw a LuaError if not a number. + * @param i the index of the argument to test, 1 is the first argument + * @return int value with fraction discarded and truncated if necessary if argument i is number, or defval if not supplied or nil + * @exception LuaError if the argument is not a number + * */ + public int optint(int i, int defval) { return arg(i).optint(defval); } + + /** Return argument i as a java int value, {@code defval} if nil, or throw a LuaError if not a number or is not representable by a java int. + * @param i the index of the argument to test, 1 is the first argument + * @return LuaInteger value that fits in a java int without rounding, or defval if not supplied or nil + * @exception LuaError if the argument cannot be represented by a java int value + * */ + public LuaInteger optinteger(int i, LuaInteger defval) { return arg(i).optinteger(defval); } + + /** Return argument i as a java long value, discarding any fractional part, {@code defval} if nil, or throw a LuaError if not a number. + * @param i the index of the argument to test, 1 is the first argument + * @return long value with fraction discarded and truncated if necessary if argument i is number, or defval if not supplied or nil + * @exception LuaError if the argument is not a number + * */ + public long optlong(int i, long defval) { return arg(i).optlong(defval); } + + /** Return argument i as a LuaNumber, {@code defval} if nil, or throw a LuaError if not a number or string that can be converted to a number. + * @param i the index of the argument to test, 1 is the first argument, or defval if not supplied or nil + * @return LuaNumber if argument i is number or can be converted to a number + * @exception LuaError if the argument is not a number + * */ + public LuaNumber optnumber(int i, LuaNumber defval) { return arg(i).optnumber(defval); } + + /** Return argument i as a java String if a string or number, {@code defval} if nil, or throw a LuaError if any other type + * @param i the index of the argument to test, 1 is the first argument + * @return String value if argument i is a string or number, or defval if not supplied or nil + * @exception LuaError if the argument is not a string or number + * */ + public String optjstring(int i, String defval) { return arg(i).optjstring(defval); } + + /** Return argument i as a LuaString if a string or number, {@code defval} if nil, or throw a LuaError if any other type + * @param i the index of the argument to test, 1 is the first argument + * @return LuaString value if argument i is a string or number, or defval if not supplied or nil + * @exception LuaError if the argument is not a string or number + * */ + public LuaString optstring(int i, LuaString defval) { return arg(i).optstring(defval); } + + /** Return argument i as a LuaTable if a lua table, {@code defval} if nil, or throw a LuaError if any other type. + * @param i the index of the argument to test, 1 is the first argument + * @return LuaTable value if a table, or defval if not supplied or nil + * @exception LuaError if the argument is not a lua table + * */ + public LuaTable opttable(int i, LuaTable defval) { return arg(i).opttable(defval); } + + /** Return argument i as a LuaThread if a lua thread, {@code defval} if nil, or throw a LuaError if any other type. + * @param i the index of the argument to test, 1 is the first argument + * @return LuaThread value if a thread, or defval if not supplied or nil + * @exception LuaError if the argument is not a lua thread + * */ + public LuaThread optthread(int i, LuaThread defval) { return arg(i).optthread(defval); } + + /** Return argument i as a java Object if a userdata, {@code defval} if nil, or throw a LuaError if any other type. + * @param i the index of the argument to test, 1 is the first argument + * @return java Object value if argument i is a userdata, or defval if not supplied or nil + * @exception LuaError if the argument is not a userdata + * */ + public Object optuserdata(int i, Object defval) { return arg(i).optuserdata(defval); } + + /** Return argument i as a java Object if it is a userdata whose instance Class c or a subclass, + * {@code defval} if nil, or throw a LuaError if any other type. + * @param i the index of the argument to test, 1 is the first argument + * @param c the class to which the userdata instance must be assignable + * @return java Object value if argument i is a userdata whose instance Class c or a subclass, or defval if not supplied or nil + * @exception LuaError if the argument is not a userdata or from whose instance c is not assignable + * */ + public Object optuserdata(int i, Class c, Object defval) { return arg(i).optuserdata(c,defval); } + + /** Return argument i as a LuaValue if it exists, or {@code defval}. + * @param i the index of the argument to test, 1 is the first argument + * @return LuaValue value if the argument exists, defval if not + * @exception LuaError if the argument does not exist. + * */ + public LuaValue optvalue(int i, LuaValue defval) { return i>0 && i<=narg()? arg(i): defval; } + + /** Return argument i as a boolean value, or throw an error if any other type. + * @param i the index of the argument to test, 1 is the first argument + * @return true if argument i is boolean true, false if it is false + * @exception LuaError if the argument is not a lua boolean + * */ + public boolean checkboolean(int i) { return arg(i).checkboolean(); } + + /** Return argument i as a closure, or throw an error if any other type. + * @param i the index of the argument to test, 1 is the first argument + * @return LuaClosure if argument i is a closure. + * @exception LuaError if the argument is not a lua closure + * */ + public LuaClosure checkclosure(int i) { return arg(i).checkclosure(); } + + /** Return argument i as a double, or throw an error if it cannot be converted to one. + * @param i the index of the argument to test, 1 is the first argument + * @return java double value if argument i is a number or string that converts to a number + * @exception LuaError if the argument is not a number + * */ + public double checkdouble(int i) { return arg(i).checknumber().todouble(); } + + /** Return argument i as a function, or throw an error if an incompatible type. + * @param i the index of the argument to test, 1 is the first argument + * @return LuaValue that can be called if argument i is lua function or closure + * @exception LuaError if the argument is not a lua function or closure + * */ + public LuaValue checkfunction(int i) { return arg(i).checkfunction(); } + + /** Return argument i as a java int value, discarding any fractional part, or throw an error if not a number. + * @param i the index of the argument to test, 1 is the first argument + * @return int value with fraction discarded and truncated if necessary if argument i is number + * @exception LuaError if the argument is not a number + * */ + public int checkint(int i) { return arg(i).checknumber().toint(); } + + /** Return argument i as a java int value, or throw an error if not a number or is not representable by a java int. + * @param i the index of the argument to test, 1 is the first argument + * @return LuaInteger value that fits in a java int without rounding + * @exception LuaError if the argument cannot be represented by a java int value + * */ + public LuaInteger checkinteger(int i) { return arg(i).checkinteger(); } + + /** Return argument i as a java long value, discarding any fractional part, or throw an error if not a number. + * @param i the index of the argument to test, 1 is the first argument + * @return long value with fraction discarded and truncated if necessary if argument i is number + * @exception LuaError if the argument is not a number + * */ + public long checklong(int i) { return arg(i).checknumber().tolong(); } + + /** Return argument i as a LuaNumber, or throw an error if not a number or string that can be converted to a number. + * @param i the index of the argument to test, 1 is the first argument + * @return LuaNumber if argument i is number or can be converted to a number + * @exception LuaError if the argument is not a number + * */ + public LuaNumber checknumber(int i) { return arg(i).checknumber(); } + + /** Return argument i as a java String if a string or number, or throw an error if any other type + * @param i the index of the argument to test, 1 is the first argument + * @return String value if argument i is a string or number + * @exception LuaError if the argument is not a string or number + * */ + public String checkjstring(int i) { return arg(i).checkjstring(); } + + /** Return argument i as a LuaString if a string or number, or throw an error if any other type + * @param i the index of the argument to test, 1 is the first argument + * @return LuaString value if argument i is a string or number + * @exception LuaError if the argument is not a string or number + * */ + public LuaString checkstring(int i) { return arg(i).checkstring(); } + + /** Return argument i as a LuaTable if a lua table, or throw an error if any other type. + * @param i the index of the argument to test, 1 is the first argument + * @return LuaTable value if a table + * @exception LuaError if the argument is not a lua table + * */ + public LuaTable checktable(int i) { return arg(i).checktable(); } + + /** Return argument i as a LuaThread if a lua thread, or throw an error if any other type. + * @param i the index of the argument to test, 1 is the first argument + * @return LuaThread value if a thread + * @exception LuaError if the argument is not a lua thread + * */ + public LuaThread checkthread(int i) { return arg(i).checkthread(); } + + /** Return argument i as a java Object if a userdata, or throw an error if any other type. + * @param i the index of the argument to test, 1 is the first argument + * @return java Object value if argument i is a userdata + * @exception LuaError if the argument is not a userdata + * */ + public Object checkuserdata(int i) { return arg(i).checkuserdata(); } + + /** Return argument i as a java Object if it is a userdata whose instance Class c or a subclass, + * or throw an error if any other type. + * @param i the index of the argument to test, 1 is the first argument + * @param c the class to which the userdata instance must be assignable + * @return java Object value if argument i is a userdata whose instance Class c or a subclass + * @exception LuaError if the argument is not a userdata or from whose instance c is not assignable + * */ + public Object checkuserdata(int i,Class c) { return arg(i).checkuserdata(c); } + + /** Return argument i as a LuaValue if it exists, or throw an error. + * @param i the index of the argument to test, 1 is the first argument + * @return LuaValue value if the argument exists + * @exception LuaError if the argument does not exist. + * */ + public LuaValue checkvalue(int i) { return i<=narg()? arg(i): LuaValue.argerror(i,"value expected"); } + + /** Return argument i as a LuaValue if it is not nil, or throw an error if it is nil. + * @param i the index of the argument to test, 1 is the first argument + * @return LuaValue value if the argument is not nil + * @exception LuaError if the argument doesn't exist or evaluates to nil. + * */ + public LuaValue checknotnil(int i) { return arg(i).checknotnil(); } + + /** Return argument i as a LuaValue when a user-supplied assertion passes, or throw an error. + * @param test user supplied assertion to test against + * @param i the index to report in any error message + * @param msg the error message to use when the test fails + * @return LuaValue value if the value of {@code test} is {@code true} + * @exception LuaError if the the value of {@code test} is {@code false} + * */ + public void argcheck(boolean test, int i, String msg) { if (!test) LuaValue.argerror(i,msg); } + + /** Return true if there is no argument or nil at argument i. + * @param i the index of the argument to test, 1 is the first argument + * @return true if argument i contains either no argument or nil + * */ + public boolean isnoneornil(int i) { + return i>narg() || arg(i).isnil(); + } + + /** Convert argument {@code i} to java boolean based on lua rules for boolean evaluation. + * @param i the index of the argument to convert, 1 is the first argument + * @return {@code false} if argument i is nil or false, otherwise {@code true} + * */ + public boolean toboolean(int i) { return arg(i).toboolean(); } + + /** Return argument i as a java byte value, discarding any fractional part and truncating, + * or 0 if not a number. + * @param i the index of the argument to convert, 1 is the first argument + * @return byte value with fraction discarded and truncated if necessary if argument i is number, otherwise 0 + * */ + public byte tobyte(int i) { return arg(i).tobyte(); } + + /** Return argument i as a java char value, discarding any fractional part and truncating, + * or 0 if not a number. + * @param i the index of the argument to convert, 1 is the first argument + * @return char value with fraction discarded and truncated if necessary if argument i is number, otherwise 0 + * */ + public char tochar(int i) { return arg(i).tochar(); } + + /** Return argument i as a java double value or 0 if not a number. + * @param i the index of the argument to convert, 1 is the first argument + * @return double value if argument i is number, otherwise 0 + * */ + public double todouble(int i) { return arg(i).todouble(); } + + /** Return argument i as a java float value, discarding excess fractional part and truncating, + * or 0 if not a number. + * @param i the index of the argument to convert, 1 is the first argument + * @return float value with excess fraction discarded and truncated if necessary if argument i is number, otherwise 0 + * */ + public float tofloat(int i) { return arg(i).tofloat(); } + + /** Return argument i as a java int value, discarding any fractional part and truncating, + * or 0 if not a number. + * @param i the index of the argument to convert, 1 is the first argument + * @return int value with fraction discarded and truncated if necessary if argument i is number, otherwise 0 + * */ + public int toint(int i) { return arg(i).toint(); } + + /** Return argument i as a java long value, discarding any fractional part and truncating, + * or 0 if not a number. + * @param i the index of the argument to convert, 1 is the first argument + * @return long value with fraction discarded and truncated if necessary if argument i is number, otherwise 0 + * */ + public long tolong(int i) { return arg(i).tolong(); } + + /** Return argument i as a java String based on the type of the argument. + * @param i the index of the argument to convert, 1 is the first argument + * @return String value representing the type + * */ + public String tojstring(int i) { return arg(i).tojstring(); } + + /** Return argument i as a java short value, discarding any fractional part and truncating, + * or 0 if not a number. + * @param i the index of the argument to convert, 1 is the first argument + * @return short value with fraction discarded and truncated if necessary if argument i is number, otherwise 0 + * */ + public short toshort(int i) { return arg(i).toshort(); } + + /** Return argument i as a java Object if a userdata, or null. + * @param i the index of the argument to convert, 1 is the first argument + * @return java Object value if argument i is a userdata, otherwise null + * */ + public Object touserdata(int i) { return arg(i).touserdata(); } + + /** Return argument i as a java Object if it is a userdata whose instance Class c or a subclass, or null. + * @param i the index of the argument to convert, 1 is the first argument + * @param c the class to which the userdata instance must be assignable + * @return java Object value if argument i is a userdata whose instance Class c or a subclass, otherwise null + * */ + public Object touserdata(int i,Class c) { return arg(i).touserdata(c); } + + /** Convert the list of varargs values to a human readable java String. + * @return String value in human readable form such as {1,2}. + */ + public String tojstring() { + Buffer sb = new Buffer(); + sb.append( "(" ); + for ( int i=1,n=narg(); i<=n; i++ ) { + if (i>1) sb.append( "," ); + sb.append( arg(i).tojstring() ); + } + sb.append( ")" ); + return sb.tojstring(); + } + + /** Convert the value or values to a java String using Varargs.tojstring() + * @return String value in human readable form. + * @see Varargs#tojstring() + */ + public String toString() { return tojstring(); } + + /** + * Create a {@code Varargs} instance containing arguments starting at index {@code start} + * @param start the index from which to include arguments, where 1 is the first argument. + * @return Varargs containing argument { start, start+1, ... , narg-start-1 } + */ + public Varargs subargs(final int start) { + int end = narg(); + switch ( end-start ) { + case 0: return arg(start); + case 1: return new LuaValue.PairVarargs(arg(start),arg(end)); + } + return end=start && i<=end? v.arg(i): LuaValue.NIL; + } + public LuaValue arg1() { + return v.arg(start); + } + public int narg() { + return end+1-start; + } + } +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/WeakTable.java b/luaj-2.0.3/src/core/org/luaj/vm2/WeakTable.java new file mode 100644 index 0000000000..32a6334fdb --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/WeakTable.java @@ -0,0 +1,349 @@ +/******************************************************************************* + * Copyright (c) 2009-2011 Luaj.org. 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. + ******************************************************************************/ +package org.luaj.vm2; + +import java.lang.ref.WeakReference; + +import org.luaj.vm2.lib.TwoArgFunction; + +/** + * Subclass of {@link LuaTable} that provides weak key and weak value semantics. + *

+ * Normally these are not created directly, but indirectly when changing the mode + * of a {@link LuaTable} as lua script executes. + *

+ * However, calling the constructors directly when weak tables are required from + * Java will reduce overhead. + */ +public class WeakTable extends LuaTable { + private boolean weakkeys,weakvalues; + + /** + * Construct a table with weak keys, weak values, or both + * @param weakkeys true to let the table have weak keys + * @param weakvalues true to let the table have weak values + */ + public WeakTable(boolean weakkeys, boolean weakvalues) { + this(weakkeys, weakvalues, 0, 0); + } + + /** + * Construct a table with weak keys, weak values, or both, and an initial capacity + * @param weakkeys true to let the table have weak keys + * @param weakvalues true to let the table have weak values + * @param narray capacity of array part + * @param nhash capacity of hash part + */ + protected WeakTable(boolean weakkeys, boolean weakvalues, int narray, int nhash) { + super(narray, nhash); + this.weakkeys = weakkeys; + this.weakvalues = weakvalues; + } + + /** + * Construct a table with weak keys, weak values, or both, and a source of initial data + * @param weakkeys true to let the table have weak keys + * @param weakvalues true to let the table have weak values + * @param source {@link LuaTable} containing the initial elements + */ + protected WeakTable(boolean weakkeys, boolean weakvalues, LuaTable source) { + this(weakkeys, weakvalues, source.getArrayLength(), source.getHashLength()); + Varargs n; + LuaValue k = NIL; + while ( !(k = ((n = source.next(k)).arg1())).isnil() ) + rawset(k, n.arg(2)); + m_metatable = source.m_metatable; + } + + public void presize( int narray ) { + super.presize(narray); + } + + /** + * Presize capacity of both array and hash parts. + * @param narray capacity of array part + * @param nhash capacity of hash part + */ + public void presize(int narray, int nhash) { + super.presize(narray, nhash); + } + + protected int getArrayLength() { + return super.getArrayLength(); + } + + protected int getHashLength() { + return super.getHashLength(); + } + + protected LuaTable changemode(boolean weakkeys, boolean weakvalues) { + this.weakkeys = weakkeys; + this.weakvalues = weakvalues; + return this; + } + + /** + * Self-sent message to convert a value to its weak counterpart + * @param value value to convert + * @return {@link LuaValue} that is a strong or weak reference, depending on type of {@code value} + */ + LuaValue weaken( LuaValue value ) { + switch ( value.type() ) { + case LuaValue.TFUNCTION: + case LuaValue.TTHREAD: + case LuaValue.TTABLE: + return new WeakValue(value); + case LuaValue.TUSERDATA: + return new WeakUserdata(value); + default: + return value; + } + } + + public void rawset( int key, LuaValue value ) { + if ( weakvalues ) + value = weaken( value ); + super.rawset(key, value); + } + + public void rawset( LuaValue key, LuaValue value ) { + if ( weakvalues ) + value = weaken( value ); + if ( weakkeys ) { + switch ( key.type() ) { + case LuaValue.TFUNCTION: + case LuaValue.TTHREAD: + case LuaValue.TTABLE: + case LuaValue.TUSERDATA: + key = value = new WeakEntry(this, key, value); + break; + default: + break; + } + } + super.rawset(key, value); + } + + + public LuaValue rawget( int key ) { + return super.rawget(key).strongvalue(); + } + + public LuaValue rawget( LuaValue key ) { + return super.rawget(key).strongvalue(); + } + + /** Get the hash value for a key + * key the key to look up + * */ + protected LuaValue hashget(LuaValue key) { + if ( hashEntries > 0 ) { + int i = hashFindSlot(key); + if ( hashEntries == 0 ) + return NIL; + LuaValue v = hashValues[i]; + return v!=null? v: NIL; + } + return NIL; + } + + + // override to remove values for weak keys as we search + public int hashFindSlot(LuaValue key) { + int i = ( key.hashCode() & 0x7FFFFFFF ) % hashKeys.length; + LuaValue k; + while ( ( k = hashKeys[i] ) != null ) { + if ( k.isweaknil() ) { + hashClearSlot(i); + if ( hashEntries == 0 ) + return 0; + } + else { + if ( k.raweq(key.strongkey()) ) + return i; + i = ( i + 1 ) % hashKeys.length; + } + } + return i; + } + + public int maxn() { + return super.maxn(); + } + + + /** + * Get the next element after a particular key in the table + * @return key,value or nil + */ + public Varargs next( LuaValue key ) { + while ( true ) { + Varargs n = super.next(key); + LuaValue k = n.arg1(); + if ( k.isnil() ) + return NIL; + LuaValue ks = k.strongkey(); + LuaValue vs = n.arg(2).strongvalue(); + if ( ks.isnil() || vs.isnil() ) { + super.rawset(k, NIL); + } else { + return varargsOf(ks,vs); + } + } + } + + // ----------------- sort support ----------------------------- + public void sort(final LuaValue comparator) { + super.sort( new TwoArgFunction() { + public LuaValue call(LuaValue arg1, LuaValue arg2) { + return comparator.call( arg1.strongvalue(), arg2.strongvalue() ); + } + } ); + } + + /** Internal class to implement weak values. + * @see WeakTable + */ + static class WeakValue extends LuaValue { + final WeakReference ref; + + protected WeakValue(LuaValue value) { + ref = new WeakReference(value); + } + + public int type() { + illegal("type","weak value"); + return 0; + } + + public String typename() { + illegal("typename","weak value"); + return null; + } + + public String toString() { + return "weak<"+ref.get()+">"; + } + + public LuaValue strongvalue() { + Object o = ref.get(); + return o!=null? (LuaValue)o: NIL; + } + + public boolean raweq(LuaValue rhs) { + Object o = ref.get(); + return o!=null && rhs.raweq((LuaValue)o); + } + + public boolean isweaknil() { + return ref.get() == null; + } + } + + /** Internal class to implement weak userdata values. + * @see WeakTable + */ + static final class WeakUserdata extends WeakValue { + private final WeakReference ob; + private final LuaValue mt; + + private WeakUserdata(LuaValue value) { + super(value); + ob = new WeakReference(value.touserdata()); + mt = value.getmetatable(); + } + + public LuaValue strongvalue() { + Object u = ref.get(); + if ( u != null ) + return (LuaValue) u; + Object o = ob.get(); + return o!=null? userdataOf(o,mt): NIL; + } + + public boolean raweq(LuaValue rhs) { + if ( ! rhs.isuserdata() ) + return false; + LuaValue v = (LuaValue) ref.get(); + if ( v != null && v.raweq(rhs) ) + return true; + return rhs.touserdata() == ob.get(); + } + + public boolean isweaknil() { + return ob.get() == null || ref.get() == null; + } + } + + /** Internal class to implement weak table entries. + * @see WeakTable + */ + static final class WeakEntry extends LuaValue { + final LuaValue weakkey; + LuaValue weakvalue; + final int keyhash; + + private WeakEntry(WeakTable table, LuaValue key, LuaValue weakvalue) { + this.weakkey = table.weaken(key); + this.keyhash = key.hashCode(); + this.weakvalue = weakvalue; + } + + public LuaValue strongkey() { + return weakkey.strongvalue(); + } + + // when looking up the value, look in the keys metatable + public LuaValue strongvalue() { + LuaValue key = weakkey.strongvalue(); + if ( key.isnil() ) + return weakvalue = NIL; + return weakvalue.strongvalue(); + } + + public int type() { + return TNONE; + } + + public String typename() { + illegal("typename","weak entry"); + return null; + } + + public String toString() { + return "weak<"+weakkey.strongvalue()+","+strongvalue()+">"; + } + + public int hashCode() { + return keyhash; + } + + public boolean raweq(LuaValue rhs) { + //return rhs.raweq(weakkey.strongvalue()); + return weakkey.raweq(rhs); + } + + public boolean isweaknil() { + return weakkey.isweaknil() || weakvalue.isweaknil(); + } + } +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/compiler/DumpState.java b/luaj-2.0.3/src/core/org/luaj/vm2/compiler/DumpState.java new file mode 100644 index 0000000000..f02a944c38 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/compiler/DumpState.java @@ -0,0 +1,267 @@ +/******************************************************************************* +* Copyright (c) 2009 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.compiler; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import org.luaj.vm2.LocVars; +import org.luaj.vm2.Prototype; +import org.luaj.vm2.LuaString; +import org.luaj.vm2.LuaValue; + + +public class DumpState { + + /** mark for precompiled code (`Lua') */ + public static final String LUA_SIGNATURE = "\033Lua"; + + /** for header of binary files -- this is Lua 5.1 */ + public static final int LUAC_VERSION = 0x51; + + /** for header of binary files -- this is the official format */ + public static final int LUAC_FORMAT = 0; + + /** size of header of binary files */ + public static final int LUAC_HEADERSIZE = 12; + + /** expected lua header bytes */ + private static final byte[] LUAC_HEADER_SIGNATURE = { '\033', 'L', 'u', 'a' }; + + /** set true to allow integer compilation */ + public static boolean ALLOW_INTEGER_CASTING = false; + + /** format corresponding to non-number-patched lua, all numbers are floats or doubles */ + public static final int NUMBER_FORMAT_FLOATS_OR_DOUBLES = 0; + + /** format corresponding to non-number-patched lua, all numbers are ints */ + public static final int NUMBER_FORMAT_INTS_ONLY = 1; + + /** format corresponding to number-patched lua, all numbers are 32-bit (4 byte) ints */ + public static final int NUMBER_FORMAT_NUM_PATCH_INT32 = 4; + + /** default number format */ + public static final int NUMBER_FORMAT_DEFAULT = NUMBER_FORMAT_FLOATS_OR_DOUBLES; + + // header fields + private boolean IS_LITTLE_ENDIAN = false; + private int NUMBER_FORMAT = NUMBER_FORMAT_DEFAULT; + private int SIZEOF_LUA_NUMBER = 8; + private static final int SIZEOF_INT = 4; + private static final int SIZEOF_SIZET = 4; + private static final int SIZEOF_INSTRUCTION = 4; + + DataOutputStream writer; + boolean strip; + int status; + + public DumpState(OutputStream w, boolean strip) { + this.writer = new DataOutputStream( w ); + this.strip = strip; + this.status = 0; + } + + void dumpBlock(final byte[] b, int size) throws IOException { + writer.write(b, 0, size); + } + + void dumpChar(int b) throws IOException { + writer.write( b ); + } + + void dumpInt(int x) throws IOException { + if ( IS_LITTLE_ENDIAN ) { + writer.writeByte(x&0xff); + writer.writeByte((x>>8)&0xff); + writer.writeByte((x>>16)&0xff); + writer.writeByte((x>>24)&0xff); + } else { + writer.writeInt(x); + } + } + + void dumpString(LuaString s) throws IOException { + final int len = s.len().toint(); + dumpInt( len+1 ); + s.write( writer, 0, len ); + writer.write( 0 ); + } + + void dumpDouble(double d) throws IOException { + long l = Double.doubleToLongBits(d); + if ( IS_LITTLE_ENDIAN ) { + dumpInt( (int) l ); + dumpInt( (int) (l>>32) ); + } else { + writer.writeLong(l); + } + } + + void dumpCode( final Prototype f ) throws IOException { + final int[] code = f.code; + int n = code.length; + dumpInt( n ); + for ( int i=0; i l ) + errorlimit( l, msg ); + } + + void errorlimit (int limit, String what) { + String msg = (f.linedefined == 0) ? + L.pushfstring("main function has more than "+limit+" "+what) : + L.pushfstring("function at line "+f.linedefined+" has more than "+limit+" "+what); + ls.lexerror(msg, 0); + } + + + int indexupvalue(LuaString name, expdesc v) { + int i; + for (i = 0; i < f.nups; i++) { + if (upvalues[i].k == v.k && upvalues[i].info == v.u.s.info) { + _assert(f.upvalues[i] == name); + return i; + } + } + /* new one */ + checklimit(f.nups + 1, LUAI_MAXUPVALUES, "upvalues"); + if ( f.upvalues == null || f.nups + 1 > f.upvalues.length) + f.upvalues = realloc( f.upvalues, f.nups*2+1 ); + f.upvalues[f.nups] = name; + _assert (v.k == LexState.VLOCAL || v.k == LexState.VUPVAL); + upvalues[f.nups] = new upvaldesc(); + upvalues[f.nups].k = (short) (v.k); + upvalues[f.nups].info = (short) (v.u.s.info); + return f.nups++; + } + + int searchvar(LuaString n) { + int i; + for (i = nactvar - 1; i >= 0; i--) { + if (n == getlocvar(i).varname) + return i; + } + return -1; /* not found */ + } + + void markupval(int level) { + BlockCnt bl = this.bl; + while (bl != null && bl.nactvar > level) + bl = bl.previous; + if (bl != null) + bl.upval = true; + } + + int singlevaraux(LuaString n, expdesc var, int base) { + int v = searchvar(n); /* look up at current level */ + if (v >= 0) { + var.init(LexState.VLOCAL, v); + if (base == 0) + markupval(v); /* local will be used as an upval */ + return LexState.VLOCAL; + } else { /* not found at current level; try upper one */ + if (prev == null) { /* no more levels? */ + /* default is global variable */ + var.init(LexState.VGLOBAL, NO_REG); + return LexState.VGLOBAL; + } + if (prev.singlevaraux(n, var, 0) == LexState.VGLOBAL) + return LexState.VGLOBAL; + var.u.s.info = indexupvalue(n, var); /* else was LOCAL or UPVAL */ + var.k = LexState.VUPVAL; /* upvalue in this level */ + return LexState.VUPVAL; + } + } + + void enterblock (BlockCnt bl, boolean isbreakable) { + bl.breaklist.i = LexState.NO_JUMP; + bl.isbreakable = isbreakable; + bl.nactvar = this.nactvar; + bl.upval = false; + bl.previous = this.bl; + this.bl = bl; + _assert(this.freereg == this.nactvar); + } + + // +// void leaveblock (FuncState *fs) { +// BlockCnt *bl = this.bl; +// this.bl = bl.previous; +// removevars(this.ls, bl.nactvar); +// if (bl.upval) +// this.codeABC(OP_CLOSE, bl.nactvar, 0, 0); +// /* a block either controls scope or breaks (never both) */ +// assert(!bl.isbreakable || !bl.upval); +// assert(bl.nactvar == this.nactvar); +// this.freereg = this.nactvar; /* free registers */ +// this.patchtohere(bl.breaklist); +// } + + void leaveblock() { + BlockCnt bl = this.bl; + this.bl = bl.previous; + ls.removevars(bl.nactvar); + if (bl.upval) + this.codeABC(OP_CLOSE, bl.nactvar, 0, 0); + /* a block either controls scope or breaks (never both) */ + _assert (!bl.isbreakable || !bl.upval); + _assert (bl.nactvar == this.nactvar); + this.freereg = this.nactvar; /* free registers */ + this.patchtohere(bl.breaklist.i); + } + + void closelistfield(ConsControl cc) { + if (cc.v.k == LexState.VVOID) + return; /* there is no list item */ + this.exp2nextreg(cc.v); + cc.v.k = LexState.VVOID; + if (cc.tostore == LFIELDS_PER_FLUSH) { + this.setlist(cc.t.u.s.info, cc.na, cc.tostore); /* flush */ + cc.tostore = 0; /* no more items pending */ + } + } + + boolean hasmultret(int k) { + return ((k) == LexState.VCALL || (k) == LexState.VVARARG); + } + + void lastlistfield (ConsControl cc) { + if (cc.tostore == 0) return; + if (hasmultret(cc.v.k)) { + this.setmultret(cc.v); + this.setlist(cc.t.u.s.info, cc.na, LUA_MULTRET); + cc.na--; /** do not count last expression (unknown number of elements) */ + } + else { + if (cc.v.k != LexState.VVOID) + this.exp2nextreg(cc.v); + this.setlist(cc.t.u.s.info, cc.na, cc.tostore); + } + } + + + + // ============================================================= + // from lcode.c + // ============================================================= + + void nil(int from, int n) { + InstructionPtr previous; + if (this.pc > this.lasttarget) { /* no jumps to current position? */ + if (this.pc == 0) { /* function start? */ + if (from >= this.nactvar) + return; /* positions are already clean */ + } else { + previous = new InstructionPtr(this.f.code, this.pc - 1); + if (GET_OPCODE(previous.get()) == OP_LOADNIL) { + int pfrom = GETARG_A(previous.get()); + int pto = GETARG_B(previous.get()); + if (pfrom <= from && from <= pto + 1) { /* can connect both? */ + if (from + n - 1 > pto) + SETARG_B(previous, from + n - 1); + return; + } + } + } + } + /* else no optimization */ + this.codeABC(OP_LOADNIL, from, from + n - 1, 0); + } + + + int jump() { + int jpc = this.jpc.i; /* save list of jumps to here */ + this.jpc.i = LexState.NO_JUMP; + IntPtr j = new IntPtr(this.codeAsBx(OP_JMP, 0, LexState.NO_JUMP)); + this.concat(j, jpc); /* keep them on hold */ + return j.i; + } + + void ret(int first, int nret) { + this.codeABC(OP_RETURN, first, nret + 1, 0); + } + + int condjump(int /* OpCode */op, int A, int B, int C) { + this.codeABC(op, A, B, C); + return this.jump(); + } + + void fixjump(int pc, int dest) { + InstructionPtr jmp = new InstructionPtr(this.f.code, pc); + int offset = dest - (pc + 1); + _assert (dest != LexState.NO_JUMP); + if (Math.abs(offset) > MAXARG_sBx) + ls.syntaxerror("control structure too long"); + SETARG_sBx(jmp, offset); + } + + + /* + * * returns current `pc' and marks it as a jump target (to avoid wrong * + * optimizations with consecutive instructions not in the same basic block). + */ + int getlabel() { + this.lasttarget = this.pc; + return this.pc; + } + + + int getjump(int pc) { + int offset = GETARG_sBx(this.f.code[pc]); + /* point to itself represents end of list */ + if (offset == LexState.NO_JUMP) + /* end of list */ + return LexState.NO_JUMP; + else + /* turn offset into absolute position */ + return (pc + 1) + offset; + } + + + InstructionPtr getjumpcontrol(int pc) { + InstructionPtr pi = new InstructionPtr(this.f.code, pc); + if (pc >= 1 && testTMode(GET_OPCODE(pi.code[pi.idx - 1]))) + return new InstructionPtr(pi.code, pi.idx - 1); + else + return pi; + } + + + /* + * * check whether list has any jump that do not produce a value * (or + * produce an inverted value) + */ + boolean need_value(int list) { + for (; list != LexState.NO_JUMP; list = this.getjump(list)) { + int i = this.getjumpcontrol(list).get(); + if (GET_OPCODE(i) != OP_TESTSET) + return true; + } + return false; /* not found */ + } + + + boolean patchtestreg(int node, int reg) { + InstructionPtr i = this.getjumpcontrol(node); + if (GET_OPCODE(i.get()) != OP_TESTSET) + /* cannot patch other instructions */ + return false; + if (reg != NO_REG && reg != GETARG_B(i.get())) + SETARG_A(i, reg); + else + /* no register to put value or register already has the value */ + i.set(CREATE_ABC(OP_TEST, GETARG_B(i.get()), 0, Lua.GETARG_C(i.get()))); + + return true; + } + + + void removevalues(int list) { + for (; list != LexState.NO_JUMP; list = this.getjump(list)) + this.patchtestreg(list, NO_REG); + } + + void patchlistaux(int list, int vtarget, int reg, int dtarget) { + while (list != LexState.NO_JUMP) { + int next = this.getjump(list); + if (this.patchtestreg(list, reg)) + this.fixjump(list, vtarget); + else + this.fixjump(list, dtarget); /* jump to default target */ + list = next; + } + } + + void dischargejpc() { + this.patchlistaux(this.jpc.i, this.pc, NO_REG, this.pc); + this.jpc.i = LexState.NO_JUMP; + } + + void patchlist(int list, int target) { + if (target == this.pc) + this.patchtohere(list); + else { + _assert (target < this.pc); + this.patchlistaux(list, target, NO_REG, target); + } + } + + void patchtohere(int list) { + this.getlabel(); + this.concat(this.jpc, list); + } + + void concat(IntPtr l1, int l2) { + if (l2 == LexState.NO_JUMP) + return; + if (l1.i == LexState.NO_JUMP) + l1.i = l2; + else { + int list = l1.i; + int next; + while ((next = this.getjump(list)) != LexState.NO_JUMP) + /* find last element */ + list = next; + this.fixjump(list, l2); + } + } + + void checkstack(int n) { + int newstack = this.freereg + n; + if (newstack > this.f.maxstacksize) { + if (newstack >= MAXSTACK) + ls.syntaxerror("function or expression too complex"); + this.f.maxstacksize = newstack; + } + } + + void reserveregs(int n) { + this.checkstack(n); + this.freereg += n; + } + + void freereg(int reg) { + if (!ISK(reg) && reg >= this.nactvar) { + this.freereg--; + _assert (reg == this.freereg); + } + } + + void freeexp(expdesc e) { + if (e.k == LexState.VNONRELOC) + this.freereg(e.u.s.info); + } + + int addk(LuaValue v) { + int idx; + if (this.htable.containsKey(v)) { + idx = ((Integer) htable.get(v)).intValue(); + } else { + idx = this.nk; + this.htable.put(v, new Integer(idx)); + final Prototype f = this.f; + if (f.k == null || nk + 1 >= f.k.length) + f.k = realloc( f.k, nk*2 + 1 ); + f.k[this.nk++] = v; + } + return idx; + } + + int stringK(LuaString s) { + return this.addk(s); + } + + int numberK(LuaValue r) { + if ( r instanceof LuaDouble ) { + double d = r.todouble(); + int i = (int) d; + if ( d == (double) i ) + r = LuaInteger.valueOf(i); + } + return this.addk(r); + } + + int boolK(boolean b) { + return this.addk((b ? LuaValue.TRUE : LuaValue.FALSE)); + } + + int nilK() { + return this.addk(LuaValue.NIL); + } + + void setreturns(expdesc e, int nresults) { + if (e.k == LexState.VCALL) { /* expression is an open function call? */ + SETARG_C(this.getcodePtr(e), nresults + 1); + } else if (e.k == LexState.VVARARG) { + SETARG_B(this.getcodePtr(e), nresults + 1); + SETARG_A(this.getcodePtr(e), this.freereg); + this.reserveregs(1); + } + } + + void setoneret(expdesc e) { + if (e.k == LexState.VCALL) { /* expression is an open function call? */ + e.k = LexState.VNONRELOC; + e.u.s.info = GETARG_A(this.getcode(e)); + } else if (e.k == LexState.VVARARG) { + SETARG_B(this.getcodePtr(e), 2); + e.k = LexState.VRELOCABLE; /* can relocate its simple result */ + } + } + + void dischargevars(expdesc e) { + switch (e.k) { + case LexState.VLOCAL: { + e.k = LexState.VNONRELOC; + break; + } + case LexState.VUPVAL: { + e.u.s.info = this.codeABC(OP_GETUPVAL, 0, e.u.s.info, 0); + e.k = LexState.VRELOCABLE; + break; + } + case LexState.VGLOBAL: { + e.u.s.info = this.codeABx(OP_GETGLOBAL, 0, e.u.s.info); + e.k = LexState.VRELOCABLE; + break; + } + case LexState.VINDEXED: { + this.freereg(e.u.s.aux); + this.freereg(e.u.s.info); + e.u.s.info = this + .codeABC(OP_GETTABLE, 0, e.u.s.info, e.u.s.aux); + e.k = LexState.VRELOCABLE; + break; + } + case LexState.VVARARG: + case LexState.VCALL: { + this.setoneret(e); + break; + } + default: + break; /* there is one value available (somewhere) */ + } + } + + int code_label(int A, int b, int jump) { + this.getlabel(); /* those instructions may be jump targets */ + return this.codeABC(OP_LOADBOOL, A, b, jump); + } + + void discharge2reg(expdesc e, int reg) { + this.dischargevars(e); + switch (e.k) { + case LexState.VNIL: { + this.nil(reg, 1); + break; + } + case LexState.VFALSE: + case LexState.VTRUE: { + this.codeABC(OP_LOADBOOL, reg, (e.k == LexState.VTRUE ? 1 : 0), + 0); + break; + } + case LexState.VK: { + this.codeABx(OP_LOADK, reg, e.u.s.info); + break; + } + case LexState.VKNUM: { + this.codeABx(OP_LOADK, reg, this.numberK(e.u.nval())); + break; + } + case LexState.VRELOCABLE: { + InstructionPtr pc = this.getcodePtr(e); + SETARG_A(pc, reg); + break; + } + case LexState.VNONRELOC: { + if (reg != e.u.s.info) + this.codeABC(OP_MOVE, reg, e.u.s.info, 0); + break; + } + default: { + _assert (e.k == LexState.VVOID || e.k == LexState.VJMP); + return; /* nothing to do... */ + } + } + e.u.s.info = reg; + e.k = LexState.VNONRELOC; + } + + void discharge2anyreg(expdesc e) { + if (e.k != LexState.VNONRELOC) { + this.reserveregs(1); + this.discharge2reg(e, this.freereg - 1); + } + } + + void exp2reg(expdesc e, int reg) { + this.discharge2reg(e, reg); + if (e.k == LexState.VJMP) + this.concat(e.t, e.u.s.info); /* put this jump in `t' list */ + if (e.hasjumps()) { + int _final; /* position after whole expression */ + int p_f = LexState.NO_JUMP; /* position of an eventual LOAD false */ + int p_t = LexState.NO_JUMP; /* position of an eventual LOAD true */ + if (this.need_value(e.t.i) || this.need_value(e.f.i)) { + int fj = (e.k == LexState.VJMP) ? LexState.NO_JUMP : this + .jump(); + p_f = this.code_label(reg, 0, 1); + p_t = this.code_label(reg, 1, 0); + this.patchtohere(fj); + } + _final = this.getlabel(); + this.patchlistaux(e.f.i, _final, reg, p_f); + this.patchlistaux(e.t.i, _final, reg, p_t); + } + e.f.i = e.t.i = LexState.NO_JUMP; + e.u.s.info = reg; + e.k = LexState.VNONRELOC; + } + + void exp2nextreg(expdesc e) { + this.dischargevars(e); + this.freeexp(e); + this.reserveregs(1); + this.exp2reg(e, this.freereg - 1); + } + + int exp2anyreg(expdesc e) { + this.dischargevars(e); + if (e.k == LexState.VNONRELOC) { + if (!e.hasjumps()) + return e.u.s.info; /* exp is already in a register */ + if (e.u.s.info >= this.nactvar) { /* reg. is not a local? */ + this.exp2reg(e, e.u.s.info); /* put value on it */ + return e.u.s.info; + } + } + this.exp2nextreg(e); /* default */ + return e.u.s.info; + } + + void exp2val(expdesc e) { + if (e.hasjumps()) + this.exp2anyreg(e); + else + this.dischargevars(e); + } + + int exp2RK(expdesc e) { + this.exp2val(e); + switch (e.k) { + case LexState.VKNUM: + case LexState.VTRUE: + case LexState.VFALSE: + case LexState.VNIL: { + if (this.nk <= MAXINDEXRK) { /* constant fit in RK operand? */ + e.u.s.info = (e.k == LexState.VNIL) ? this.nilK() + : (e.k == LexState.VKNUM) ? this.numberK(e.u.nval()) + : this.boolK((e.k == LexState.VTRUE)); + e.k = LexState.VK; + return RKASK(e.u.s.info); + } else + break; + } + case LexState.VK: { + if (e.u.s.info <= MAXINDEXRK) /* constant fit in argC? */ + return RKASK(e.u.s.info); + else + break; + } + default: + break; + } + /* not a constant in the right range: put it in a register */ + return this.exp2anyreg(e); + } + + void storevar(expdesc var, expdesc ex) { + switch (var.k) { + case LexState.VLOCAL: { + this.freeexp(ex); + this.exp2reg(ex, var.u.s.info); + return; + } + case LexState.VUPVAL: { + int e = this.exp2anyreg(ex); + this.codeABC(OP_SETUPVAL, e, var.u.s.info, 0); + break; + } + case LexState.VGLOBAL: { + int e = this.exp2anyreg(ex); + this.codeABx(OP_SETGLOBAL, e, var.u.s.info); + break; + } + case LexState.VINDEXED: { + int e = this.exp2RK(ex); + this.codeABC(OP_SETTABLE, var.u.s.info, var.u.s.aux, e); + break; + } + default: { + _assert (false); /* invalid var kind to store */ + break; + } + } + this.freeexp(ex); + } + + void self(expdesc e, expdesc key) { + int func; + this.exp2anyreg(e); + this.freeexp(e); + func = this.freereg; + this.reserveregs(2); + this.codeABC(OP_SELF, func, e.u.s.info, this.exp2RK(key)); + this.freeexp(key); + e.u.s.info = func; + e.k = LexState.VNONRELOC; + } + + void invertjump(expdesc e) { + InstructionPtr pc = this.getjumpcontrol(e.u.s.info); + _assert (testTMode(GET_OPCODE(pc.get())) + && GET_OPCODE(pc.get()) != OP_TESTSET && Lua + .GET_OPCODE(pc.get()) != OP_TEST); + // SETARG_A(pc, !(GETARG_A(pc.get()))); + int a = GETARG_A(pc.get()); + int nota = (a!=0? 0: 1); + SETARG_A(pc, nota); + } + + int jumponcond(expdesc e, int cond) { + if (e.k == LexState.VRELOCABLE) { + int ie = this.getcode(e); + if (GET_OPCODE(ie) == OP_NOT) { + this.pc--; /* remove previous OP_NOT */ + return this.condjump(OP_TEST, GETARG_B(ie), 0, (cond!=0? 0: 1)); + } + /* else go through */ + } + this.discharge2anyreg(e); + this.freeexp(e); + return this.condjump(OP_TESTSET, NO_REG, e.u.s.info, cond); + } + + void goiftrue(expdesc e) { + int pc; /* pc of last jump */ + this.dischargevars(e); + switch (e.k) { + case LexState.VK: + case LexState.VKNUM: + case LexState.VTRUE: { + pc = LexState.NO_JUMP; /* always true; do nothing */ + break; + } + case LexState.VFALSE: { + pc = this.jump(); /* always jump */ + break; + } + case LexState.VJMP: { + this.invertjump(e); + pc = e.u.s.info; + break; + } + default: { + pc = this.jumponcond(e, 0); + break; + } + } + this.concat(e.f, pc); /* insert last jump in `f' list */ + this.patchtohere(e.t.i); + e.t.i = LexState.NO_JUMP; + } + + void goiffalse(expdesc e) { + int pc; /* pc of last jump */ + this.dischargevars(e); + switch (e.k) { + case LexState.VNIL: + case LexState.VFALSE: { + pc = LexState.NO_JUMP; /* always false; do nothing */ + break; + } + case LexState.VTRUE: { + pc = this.jump(); /* always jump */ + break; + } + case LexState.VJMP: { + pc = e.u.s.info; + break; + } + default: { + pc = this.jumponcond(e, 1); + break; + } + } + this.concat(e.t, pc); /* insert last jump in `t' list */ + this.patchtohere(e.f.i); + e.f.i = LexState.NO_JUMP; + } + + void codenot(expdesc e) { + this.dischargevars(e); + switch (e.k) { + case LexState.VNIL: + case LexState.VFALSE: { + e.k = LexState.VTRUE; + break; + } + case LexState.VK: + case LexState.VKNUM: + case LexState.VTRUE: { + e.k = LexState.VFALSE; + break; + } + case LexState.VJMP: { + this.invertjump(e); + break; + } + case LexState.VRELOCABLE: + case LexState.VNONRELOC: { + this.discharge2anyreg(e); + this.freeexp(e); + e.u.s.info = this.codeABC(OP_NOT, 0, e.u.s.info, 0); + e.k = LexState.VRELOCABLE; + break; + } + default: { + _assert (false); /* cannot happen */ + break; + } + } + /* interchange true and false lists */ + { + int temp = e.f.i; + e.f.i = e.t.i; + e.t.i = temp; + } + this.removevalues(e.f.i); + this.removevalues(e.t.i); + } + + void indexed(expdesc t, expdesc k) { + t.u.s.aux = this.exp2RK(k); + t.k = LexState.VINDEXED; + } + + boolean constfolding(int op, expdesc e1, expdesc e2) { + LuaValue v1, v2, r; + if (!e1.isnumeral() || !e2.isnumeral()) + return false; + v1 = e1.u.nval(); + v2 = e2.u.nval(); + switch (op) { + case OP_ADD: + r = v1.add(v2); + break; + case OP_SUB: + r = v1.sub(v2); + break; + case OP_MUL: + r = v1.mul(v2); + break; + case OP_DIV: + r = v1.div(v2); + break; + case OP_MOD: + r = v1.mod(v2); + break; + case OP_POW: + r = v1.pow(v2); + break; + case OP_UNM: + r = v1.neg(); + break; + case OP_LEN: + // r = v1.len(); + // break; + return false; /* no constant folding for 'len' */ + default: + _assert (false); + r = null; + break; + } + if ( Double.isNaN(r.todouble()) ) + return false; /* do not attempt to produce NaN */ + e1.u.setNval( r ); + return true; + } + + void codearith(int op, expdesc e1, expdesc e2) { + if (constfolding(op, e1, e2)) + return; + else { + int o2 = (op != OP_UNM && op != OP_LEN) ? this.exp2RK(e2) + : 0; + int o1 = this.exp2RK(e1); + if (o1 > o2) { + this.freeexp(e1); + this.freeexp(e2); + } else { + this.freeexp(e2); + this.freeexp(e1); + } + e1.u.s.info = this.codeABC(op, 0, o1, o2); + e1.k = LexState.VRELOCABLE; + } + } + + void codecomp(int /* OpCode */op, int cond, expdesc e1, expdesc e2) { + int o1 = this.exp2RK(e1); + int o2 = this.exp2RK(e2); + this.freeexp(e2); + this.freeexp(e1); + if (cond == 0 && op != OP_EQ) { + int temp; /* exchange args to replace by `<' or `<=' */ + temp = o1; + o1 = o2; + o2 = temp; /* o1 <==> o2 */ + cond = 1; + } + e1.u.s.info = this.condjump(op, cond, o1, o2); + e1.k = LexState.VJMP; + } + + void prefix(int /* UnOpr */op, expdesc e) { + expdesc e2 = new expdesc(); + e2.init(LexState.VKNUM, 0); + switch (op) { + case LexState.OPR_MINUS: { + if (e.k == LexState.VK) + this.exp2anyreg(e); /* cannot operate on non-numeric constants */ + this.codearith(OP_UNM, e, e2); + break; + } + case LexState.OPR_NOT: + this.codenot(e); + break; + case LexState.OPR_LEN: { + this.exp2anyreg(e); /* cannot operate on constants */ + this.codearith(OP_LEN, e, e2); + break; + } + default: + _assert (false); + } + } + + void infix(int /* BinOpr */op, expdesc v) { + switch (op) { + case LexState.OPR_AND: { + this.goiftrue(v); + break; + } + case LexState.OPR_OR: { + this.goiffalse(v); + break; + } + case LexState.OPR_CONCAT: { + this.exp2nextreg(v); /* operand must be on the `stack' */ + break; + } + case LexState.OPR_ADD: + case LexState.OPR_SUB: + case LexState.OPR_MUL: + case LexState.OPR_DIV: + case LexState.OPR_MOD: + case LexState.OPR_POW: { + if (!v.isnumeral()) + this.exp2RK(v); + break; + } + default: { + this.exp2RK(v); + break; + } + } + } + + + void posfix(int op, expdesc e1, expdesc e2) { + switch (op) { + case LexState.OPR_AND: { + _assert (e1.t.i == LexState.NO_JUMP); /* list must be closed */ + this.dischargevars(e2); + this.concat(e2.f, e1.f.i); + // *e1 = *e2; + e1.setvalue(e2); + break; + } + case LexState.OPR_OR: { + _assert (e1.f.i == LexState.NO_JUMP); /* list must be closed */ + this.dischargevars(e2); + this.concat(e2.t, e1.t.i); + // *e1 = *e2; + e1.setvalue(e2); + break; + } + case LexState.OPR_CONCAT: { + this.exp2val(e2); + if (e2.k == LexState.VRELOCABLE + && GET_OPCODE(this.getcode(e2)) == OP_CONCAT) { + _assert (e1.u.s.info == GETARG_B(this.getcode(e2)) - 1); + this.freeexp(e1); + SETARG_B(this.getcodePtr(e2), e1.u.s.info); + e1.k = LexState.VRELOCABLE; + e1.u.s.info = e2.u.s.info; + } else { + this.exp2nextreg(e2); /* operand must be on the 'stack' */ + this.codearith(OP_CONCAT, e1, e2); + } + break; + } + case LexState.OPR_ADD: + this.codearith(OP_ADD, e1, e2); + break; + case LexState.OPR_SUB: + this.codearith(OP_SUB, e1, e2); + break; + case LexState.OPR_MUL: + this.codearith(OP_MUL, e1, e2); + break; + case LexState.OPR_DIV: + this.codearith(OP_DIV, e1, e2); + break; + case LexState.OPR_MOD: + this.codearith(OP_MOD, e1, e2); + break; + case LexState.OPR_POW: + this.codearith(OP_POW, e1, e2); + break; + case LexState.OPR_EQ: + this.codecomp(OP_EQ, 1, e1, e2); + break; + case LexState.OPR_NE: + this.codecomp(OP_EQ, 0, e1, e2); + break; + case LexState.OPR_LT: + this.codecomp(OP_LT, 1, e1, e2); + break; + case LexState.OPR_LE: + this.codecomp(OP_LE, 1, e1, e2); + break; + case LexState.OPR_GT: + this.codecomp(OP_LT, 0, e1, e2); + break; + case LexState.OPR_GE: + this.codecomp(OP_LE, 0, e1, e2); + break; + default: + _assert (false); + } + } + + + void fixline(int line) { + this.f.lineinfo[this.pc - 1] = line; + } + + + int code(int instruction, int line) { + Prototype f = this.f; + this.dischargejpc(); /* `pc' will change */ + /* put new instruction in code array */ + if (f.code == null || this.pc + 1 > f.code.length) + f.code = LuaC.realloc(f.code, this.pc * 2 + 1); + f.code[this.pc] = instruction; + /* save corresponding line information */ + if (f.lineinfo == null || this.pc + 1 > f.lineinfo.length) + f.lineinfo = LuaC.realloc(f.lineinfo, + this.pc * 2 + 1); + f.lineinfo[this.pc] = line; + return this.pc++; + } + + + int codeABC(int o, int a, int b, int c) { + _assert (getOpMode(o) == iABC); + _assert (getBMode(o) != OpArgN || b == 0); + _assert (getCMode(o) != OpArgN || c == 0); + return this.code(CREATE_ABC(o, a, b, c), this.ls.lastline); + } + + + int codeABx(int o, int a, int bc) { + _assert (getOpMode(o) == iABx || getOpMode(o) == iAsBx); + _assert (getCMode(o) == OpArgN); + return this.code(CREATE_ABx(o, a, bc), this.ls.lastline); + } + + + void setlist(int base, int nelems, int tostore) { + int c = (nelems - 1) / LFIELDS_PER_FLUSH + 1; + int b = (tostore == LUA_MULTRET) ? 0 : tostore; + _assert (tostore != 0); + if (c <= MAXARG_C) + this.codeABC(OP_SETLIST, base, b, c); + else { + this.codeABC(OP_SETLIST, base, b, 0); + this.code(c, this.ls.lastline); + } + this.freereg = base + 1; /* free registers with list values */ + } + +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/compiler/InstructionPtr.java b/luaj-2.0.3/src/core/org/luaj/vm2/compiler/InstructionPtr.java new file mode 100644 index 0000000000..fbdf061a5e --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/compiler/InstructionPtr.java @@ -0,0 +1,37 @@ +/******************************************************************************* +* Copyright (c) 2009 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.compiler; + +class InstructionPtr { + final int[] code; + final int idx; + InstructionPtr(int[] code, int idx ) { + this.code = code; + this.idx = idx; + } + int get() { + return code[idx]; + } + void set(int value) { + code[idx] = value; + } +} \ No newline at end of file diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/compiler/IntPtr.java b/luaj-2.0.3/src/core/org/luaj/vm2/compiler/IntPtr.java new file mode 100644 index 0000000000..0f42cb0e65 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/compiler/IntPtr.java @@ -0,0 +1,31 @@ +/******************************************************************************* +* Copyright (c) 2009 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.compiler; + +public class IntPtr { + int i; + IntPtr() { + } + IntPtr(int value) { + this.i = value; + } +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/compiler/LexState.java b/luaj-2.0.3/src/core/org/luaj/vm2/compiler/LexState.java new file mode 100644 index 0000000000..40247431b5 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/compiler/LexState.java @@ -0,0 +1,1905 @@ +/******************************************************************************* +* Copyright (c) 2009 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.compiler; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Hashtable; + +import org.luaj.vm2.LuaInteger; +import org.luaj.vm2.LocVars; +import org.luaj.vm2.Lua; +import org.luaj.vm2.LuaError; +import org.luaj.vm2.Prototype; +import org.luaj.vm2.LuaString; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.compiler.FuncState.BlockCnt; + + +public class LexState { + + protected static final String RESERVED_LOCAL_VAR_FOR_CONTROL = "(for control)"; + protected static final String RESERVED_LOCAL_VAR_FOR_STATE = "(for state)"; + protected static final String RESERVED_LOCAL_VAR_FOR_GENERATOR = "(for generator)"; + protected static final String RESERVED_LOCAL_VAR_FOR_STEP = "(for step)"; + protected static final String RESERVED_LOCAL_VAR_FOR_LIMIT = "(for limit)"; + protected static final String RESERVED_LOCAL_VAR_FOR_INDEX = "(for index)"; + + // keywords array + protected static final String[] RESERVED_LOCAL_VAR_KEYWORDS = new String[] { + RESERVED_LOCAL_VAR_FOR_CONTROL, + RESERVED_LOCAL_VAR_FOR_GENERATOR, + RESERVED_LOCAL_VAR_FOR_INDEX, + RESERVED_LOCAL_VAR_FOR_LIMIT, + RESERVED_LOCAL_VAR_FOR_STATE, + RESERVED_LOCAL_VAR_FOR_STEP + }; + private static final Hashtable RESERVED_LOCAL_VAR_KEYWORDS_TABLE = new Hashtable(); + static { + for ( int i=0; i=", "<=", "~=", + "", "", "", "", + }; + + final static int + /* terminal symbols denoted by reserved words */ + TK_AND=257, TK_BREAK=258, TK_DO=259, TK_ELSE=260, TK_ELSEIF=261, + TK_END=262, TK_FALSE=263, TK_FOR=264, TK_FUNCTION=265, TK_IF=266, + TK_IN=267, TK_LOCAL=268, TK_NIL=269, TK_NOT=270, TK_OR=271, TK_REPEAT=272, + TK_RETURN=273, TK_THEN=274, TK_TRUE=275, TK_UNTIL=276, TK_WHILE=277, + /* other terminal symbols */ + TK_CONCAT=278, TK_DOTS=279, TK_EQ=280, TK_GE=281, TK_LE=282, TK_NE=283, + TK_NUMBER=284, TK_NAME=285, TK_STRING=286, TK_EOS=287; + + final static int FIRST_RESERVED = TK_AND; + final static int NUM_RESERVED = TK_WHILE+1-FIRST_RESERVED; + + final static Hashtable RESERVED = new Hashtable(); + static { + for ( int i=0; i= '0' && c <= '9') + || (c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z') + || (c == '_'); + // return Character.isLetterOrDigit(c); + } + + private boolean isalpha(int c) { + return (c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z'); + } + + private boolean isdigit(int c) { + return (c >= '0' && c <= '9'); + } + + private boolean isspace(int c) { + return (c <= ' '); + } + + + public LexState(LuaC state, InputStream stream) { + this.z = stream; + this.buff = new byte[32]; + this.L = state; + } + + void nextChar() { + try { + current = z.read(); + } catch ( IOException e ) { + e.printStackTrace(); + current = EOZ; + } + } + + boolean currIsNewline() { + return current == '\n' || current == '\r'; + } + + void save_and_next() { + save( current ); + nextChar(); + } + + void save(int c) { + if ( buff == null || nbuff + 1 > buff.length ) + buff = LuaC.realloc( buff, nbuff*2+1 ); + buff[nbuff++] = (byte) c; + } + + + String token2str( int token ) { + if ( token < FIRST_RESERVED ) { + return iscntrl(token)? + L.pushfstring( "char("+((int)token)+")" ): + L.pushfstring( String.valueOf( (char) token ) ); + } else { + return luaX_tokens[token-FIRST_RESERVED]; + } + } + + private static boolean iscntrl(int token) { + return token < ' '; + } + + String txtToken(int token) { + switch ( token ) { + case TK_NAME: + case TK_STRING: + case TK_NUMBER: + return new String( buff, 0, nbuff ); + default: + return token2str( token ); + } + } + + void lexerror( String msg, int token ) { + String cid = chunkid( source.tojstring() ); // TODO: get source name from source + L.pushfstring( cid+":"+linenumber+": "+msg ); + if ( token != 0 ) + L.pushfstring( "syntax error: "+msg+" near "+txtToken(token) ); + throw new LuaError(cid+":"+linenumber+": "+msg); + } + + String chunkid( String source ) { + if ( source.startsWith("=") ) + return source.substring(1); + String end = ""; + if ( source.startsWith("@") ) { + source = source.substring(1); + } else { + source = "[string \""+source; + end = "\"]"; + } + int n = source.length() + end.length(); + if ( n > MAXSRC ) + source = source.substring(0,MAXSRC-end.length()-3) + "..."; + return source + end; + } + + void syntaxerror( String msg ) { + lexerror( msg, t.token ); + } + + // only called by new_localvarliteral() for var names. + LuaString newstring( String s ) { + byte[] b = s.getBytes(); + return L.newTString(b, 0, b.length); + } + + LuaString newstring( byte[] bytes, int offset, int len ) { + return L.newTString( bytes, offset, len ); + } + + void inclinenumber() { + int old = current; + LuaC._assert( currIsNewline() ); + nextChar(); /* skip '\n' or '\r' */ + if ( currIsNewline() && current != old ) + nextChar(); /* skip '\n\r' or '\r\n' */ + if ( ++linenumber >= MAX_INT ) + syntaxerror("chunk has too many lines"); + } + + void setinput( LuaC L, int firstByte, InputStream z, LuaString source ) { + this.decpoint = '.'; + this.L = L; + this.lookahead.token = TK_EOS; /* no look-ahead token */ + this.z = z; + this.fs = null; + this.linenumber = 1; + this.lastline = 1; + this.source = source; + this.nbuff = 0; /* initialize buffer */ + this.current = firstByte; /* read first char */ + this.skipShebang(); + } + + private void skipShebang() { + if ( current == '#' ) + while (!currIsNewline() && current != EOZ) + nextChar(); + } + + + + /* + ** ======================================================= + ** LEXICAL ANALYZER + ** ======================================================= + */ + + + boolean check_next(String set) { + if (set.indexOf(current) < 0) + return false; + save_and_next(); + return true; + } + + void buffreplace(byte from, byte to) { + int n = nbuff; + byte[] p = buff; + while ((--n) >= 0) + if (p[n] == from) + p[n] = to; + } + + boolean str2d(String str, SemInfo seminfo) { + double d; + str = str.trim(); // TODO: get rid of this + if ( str.startsWith("0x") ) { + d = Long.parseLong(str.substring(2), 16); + } + else + d = Double.parseDouble(str); + seminfo.r = LuaValue.valueOf(d); + return true; + } + + // + // TODO: reexamine this source and see if it should be ported differently + // + // static void trydecpoint (LexState *ls, SemInfo *seminfo) { + // /* format error: try to update decimal point separator */ + // struct lconv *cv = localeconv(); + // char old = this.decpoint; + // this.decpoint = (cv ? cv->decimal_point[0] : '.'); + // buffreplace(ls, old, this.decpoint); /* try updated decimal separator */ + // if (!luaO_str2d(luaZ_buffer(this.buff), &seminfo->r)) { + // /* format error with correct decimal point: no more options */ + // buffreplace(ls, this.decpoint, '.'); /* undo change (for error message) */ + // luaX_lexerror(ls, "malformed number", TK_NUMBER); + // } + // } + // + /* + void trydecpoint(String str, SemInfo seminfo) { + NumberFormat nf = NumberFormat.getInstance(); + try { + Number n = nf.parse(str); + double d = n.doubleValue(); + seminfo.r = new LDouble(d); + } catch (ParseException e) { + lexerror("malformed number", TK_NUMBER); + } + } + */ + + void read_numeral(SemInfo seminfo) { + LuaC._assert (isdigit(current)); + do { + save_and_next(); + } while (isdigit(current) || current == '.'); + if (check_next("Ee")) /* `E'? */ + check_next("+-"); /* optional exponent sign */ + while (isalnum(current) || current == '_') + save_and_next(); + save('\0'); + buffreplace((byte)'.', decpoint); /* follow locale for decimal point */ + String str = new String(buff, 0, nbuff); +// if (!str2d(str, seminfo)) /* format error? */ +// trydecpoint(str, seminfo); /* try to update decimal point separator */ + str2d(str, seminfo); + } + + int skip_sep() { + int count = 0; + int s = current; + LuaC._assert (s == '[' || s == ']'); + save_and_next(); + while (current == '=') { + save_and_next(); + count++; + } + return (current == s) ? count : (-count) - 1; + } + + void read_long_string(SemInfo seminfo, int sep) { + int cont = 0; + save_and_next(); /* skip 2nd `[' */ + if (currIsNewline()) /* string starts with a newline? */ + inclinenumber(); /* skip it */ + for (boolean endloop = false; !endloop;) { + switch (current) { + case EOZ: + lexerror((seminfo != null) ? "unfinished long string" + : "unfinished long comment", TK_EOS); + break; /* to avoid warnings */ + case '[': { + if (skip_sep() == sep) { + save_and_next(); /* skip 2nd `[' */ + cont++; + if (LUA_COMPAT_LSTR == 1) { + if (sep == 0) + lexerror("nesting of [[...]] is deprecated", '['); + } + } + break; + } + case ']': { + if (skip_sep() == sep) { + save_and_next(); /* skip 2nd `]' */ + if (LUA_COMPAT_LSTR == 2) { + cont--; + if (sep == 0 && cont >= 0) + break; + } + endloop = true; + } + break; + } + case '\n': + case '\r': { + save('\n'); + inclinenumber(); + if (seminfo == null) + nbuff = 0; /* avoid wasting space */ + break; + } + default: { + if (seminfo != null) + save_and_next(); + else + nextChar(); + } + } + } + if (seminfo != null) + seminfo.ts = newstring(buff, 2 + sep, nbuff - 2 * (2 + sep)); + } + + void read_string(int del, SemInfo seminfo) { + save_and_next(); + while (current != del) { + switch (current) { + case EOZ: + lexerror("unfinished string", TK_EOS); + continue; /* to avoid warnings */ + case '\n': + case '\r': + lexerror("unfinished string", TK_STRING); + continue; /* to avoid warnings */ + case '\\': { + int c; + nextChar(); /* do not save the `\' */ + switch (current) { + case 'a': /* bell */ + c = '\u0007'; + break; + case 'b': /* backspace */ + c = '\b'; + break; + case 'f': /* form feed */ + c = '\f'; + break; + case 'n': /* newline */ + c = '\n'; + break; + case 'r': /* carriage return */ + c = '\r'; + break; + case 't': /* tab */ + c = '\t'; + break; + case 'v': /* vertical tab */ + c = '\u000B'; + break; + case '\n': /* go through */ + case '\r': + save('\n'); + inclinenumber(); + continue; + case EOZ: + continue; /* will raise an error next loop */ + default: { + if (!isdigit(current)) + save_and_next(); /* handles \\, \", \', and \? */ + else { /* \xxx */ + int i = 0; + c = 0; + do { + c = 10 * c + (current - '0'); + nextChar(); + } while (++i < 3 && isdigit(current)); + if (c > UCHAR_MAX) + lexerror("escape sequence too large", TK_STRING); + save(c); + } + continue; + } + } + save(c); + nextChar(); + continue; + } + default: + save_and_next(); + } + } + save_and_next(); /* skip delimiter */ + seminfo.ts = newstring(buff, 1, nbuff - 2); + } + + int llex(SemInfo seminfo) { + nbuff = 0; + while (true) { + switch (current) { + case '\n': + case '\r': { + inclinenumber(); + continue; + } + case '-': { + nextChar(); + if (current != '-') + return '-'; + /* else is a comment */ + nextChar(); + if (current == '[') { + int sep = skip_sep(); + nbuff = 0; /* `skip_sep' may dirty the buffer */ + if (sep >= 0) { + read_long_string(null, sep); /* long comment */ + nbuff = 0; + continue; + } + } + /* else short comment */ + while (!currIsNewline() && current != EOZ) + nextChar(); + continue; + } + case '[': { + int sep = skip_sep(); + if (sep >= 0) { + read_long_string(seminfo, sep); + return TK_STRING; + } else if (sep == -1) + return '['; + else + lexerror("invalid long string delimiter", TK_STRING); + } + case '=': { + nextChar(); + if (current != '=') + return '='; + else { + nextChar(); + return TK_EQ; + } + } + case '<': { + nextChar(); + if (current != '=') + return '<'; + else { + nextChar(); + return TK_LE; + } + } + case '>': { + nextChar(); + if (current != '=') + return '>'; + else { + nextChar(); + return TK_GE; + } + } + case '~': { + nextChar(); + if (current != '=') + return '~'; + else { + nextChar(); + return TK_NE; + } + } + case '"': + case '\'': { + read_string(current, seminfo); + return TK_STRING; + } + case '.': { + save_and_next(); + if (check_next(".")) { + if (check_next(".")) + return TK_DOTS; /* ... */ + else + return TK_CONCAT; /* .. */ + } else if (!isdigit(current)) + return '.'; + else { + read_numeral(seminfo); + return TK_NUMBER; + } + } + case EOZ: { + return TK_EOS; + } + default: { + if (isspace(current)) { + LuaC._assert (!currIsNewline()); + nextChar(); + continue; + } else if (isdigit(current)) { + read_numeral(seminfo); + return TK_NUMBER; + } else if (isalpha(current) || current == '_') { + /* identifier or reserved word */ + LuaString ts; + do { + save_and_next(); + } while (isalnum(current) || current == '_'); + ts = newstring(buff, 0, nbuff); + if ( RESERVED.containsKey(ts) ) + return ((Integer)RESERVED.get(ts)).intValue(); + else { + seminfo.ts = ts; + return TK_NAME; + } + } else { + int c = current; + nextChar(); + return c; /* single-char tokens (+ - / ...) */ + } + } + } + } + } + + void next() { + lastline = linenumber; + if (lookahead.token != TK_EOS) { /* is there a look-ahead token? */ + t.set( lookahead ); /* use this one */ + lookahead.token = TK_EOS; /* and discharge it */ + } else + t.token = llex(t.seminfo); /* read next token */ + } + + void lookahead() { + LuaC._assert (lookahead.token == TK_EOS); + lookahead.token = llex(lookahead.seminfo); + } + + // ============================================================= + // from lcode.h + // ============================================================= + + + // ============================================================= + // from lparser.c + // ============================================================= + + static class expdesc { + int k; // expkind, from enumerated list, above + static class U { // originally a union + static class S { + int info, aux; + } + final S s = new S(); + private LuaValue _nval; + public void setNval(LuaValue r) { + _nval = r; + } + public LuaValue nval() { + return (_nval == null? LuaInteger.valueOf(s.info): _nval); + } + }; + final U u = new U(); + final IntPtr t = new IntPtr(); /* patch list of `exit when true' */ + final IntPtr f = new IntPtr(); /* patch list of `exit when false' */ + void init( int k, int i ) { + this.f.i = NO_JUMP; + this.t.i = NO_JUMP; + this.k = k; + this.u.s.info = i; + } + + boolean hasjumps() { + return (t.i != f.i); + } + + boolean isnumeral() { + return (k == VKNUM && t.i == NO_JUMP && f.i == NO_JUMP); + } + + public void setvalue(expdesc other) { + this.k = other.k; + this.u._nval = other.u._nval; + this.u.s.info = other.u.s.info; + this.u.s.aux = other.u.s.aux; + this.t.i = other.t.i; + this.f.i = other.f.i; + } + } + + boolean hasmultret(int k) { + return ((k) == VCALL || (k) == VVARARG); + } + + /*---------------------------------------------------------------------- + name args description + ------------------------------------------------------------------------*/ + + /* + * * prototypes for recursive non-terminal functions + */ + + void error_expected(int token) { + syntaxerror(L.pushfstring(LUA_QS(token2str(token)) + " expected")); + } + + boolean testnext(int c) { + if (t.token == c) { + next(); + return true; + } else + return false; + } + + void check(int c) { + if (t.token != c) + error_expected(c); + } + + void checknext (int c) { + check(c); + next(); + } + + void check_condition(boolean c, String msg) { + if (!(c)) + syntaxerror(msg); + } + + + void check_match(int what, int who, int where) { + if (!testnext(what)) { + if (where == linenumber) + error_expected(what); + else { + syntaxerror(L.pushfstring(LUA_QS(token2str(what)) + + " expected " + "(to close " + LUA_QS(token2str(who)) + + " at line " + where + ")")); + } + } + } + + LuaString str_checkname() { + LuaString ts; + check(TK_NAME); + ts = t.seminfo.ts; + next(); + return ts; + } + + void codestring(expdesc e, LuaString s) { + e.init(VK, fs.stringK(s)); + } + + void checkname(expdesc e) { + codestring(e, str_checkname()); + } + + + int registerlocalvar(LuaString varname) { + FuncState fs = this.fs; + Prototype f = fs.f; + if (f.locvars == null || fs.nlocvars + 1 > f.locvars.length) + f.locvars = LuaC.realloc( f.locvars, fs.nlocvars*2+1 ); + f.locvars[fs.nlocvars] = new LocVars(varname,0,0); + return fs.nlocvars++; + } + + +// +// #define new_localvarliteral(ls,v,n) \ +// this.new_localvar(luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n) +// + void new_localvarliteral(String v, int n) { + LuaString ts = newstring(v); + new_localvar(ts, n); + } + + void new_localvar(LuaString name, int n) { + FuncState fs = this.fs; + fs.checklimit(fs.nactvar + n + 1, FuncState.LUAI_MAXVARS, "local variables"); + fs.actvar[fs.nactvar + n] = (short) registerlocalvar(name); + } + + void adjustlocalvars(int nvars) { + FuncState fs = this.fs; + fs.nactvar = (short) (fs.nactvar + nvars); + for (; nvars > 0; nvars--) { + fs.getlocvar(fs.nactvar - nvars).startpc = fs.pc; + } + } + + void removevars(int tolevel) { + FuncState fs = this.fs; + while (fs.nactvar > tolevel) + fs.getlocvar(--fs.nactvar).endpc = fs.pc; + } + + void singlevar(expdesc var) { + LuaString varname = this.str_checkname(); + FuncState fs = this.fs; + if (fs.singlevaraux(varname, var, 1) == VGLOBAL) + var.u.s.info = fs.stringK(varname); /* info points to global name */ + } + + void adjust_assign(int nvars, int nexps, expdesc e) { + FuncState fs = this.fs; + int extra = nvars - nexps; + if (hasmultret(e.k)) { + /* includes call itself */ + extra++; + if (extra < 0) + extra = 0; + /* last exp. provides the difference */ + fs.setreturns(e, extra); + if (extra > 1) + fs.reserveregs(extra - 1); + } else { + /* close last expression */ + if (e.k != VVOID) + fs.exp2nextreg(e); + if (extra > 0) { + int reg = fs.freereg; + fs.reserveregs(extra); + fs.nil(reg, extra); + } + } + } + + void enterlevel() { + if (++L.nCcalls > LUAI_MAXCCALLS) + lexerror("chunk has too many syntax levels", 0); + } + + void leavelevel() { + L.nCcalls--; + } + + void pushclosure(FuncState func, expdesc v) { + FuncState fs = this.fs; + Prototype f = fs.f; + if (f.p == null || fs.np + 1 > f.p.length) + f.p = LuaC.realloc( f.p, fs.np*2 + 1 ); + f.p[fs.np++] = func.f; + v.init(VRELOCABLE, fs.codeABx(Lua.OP_CLOSURE, 0, fs.np - 1)); + for (int i = 0; i < func.f.nups; i++) { + int o = (func.upvalues[i].k == VLOCAL) ? Lua.OP_MOVE + : Lua.OP_GETUPVAL; + fs.codeABC(o, 0, func.upvalues[i].info, 0); + } + } + + void open_func (FuncState fs) { + LuaC L = this.L; + Prototype f = new Prototype(); + if ( this.fs!=null ) + f.source = this.fs.f.source; + fs.f = f; + fs.prev = this.fs; /* linked list of funcstates */ + fs.ls = this; + fs.L = L; + this.fs = fs; + fs.pc = 0; + fs.lasttarget = -1; + fs.jpc = new IntPtr( NO_JUMP ); + fs.freereg = 0; + fs.nk = 0; + fs.np = 0; + fs.nlocvars = 0; + fs.nactvar = 0; + fs.bl = null; + f.maxstacksize = 2; /* registers 0/1 are always valid */ + //fs.h = new LTable(); + fs.htable = new Hashtable(); + } + + void close_func() { + FuncState fs = this.fs; + Prototype f = fs.f; + this.removevars(0); + fs.ret(0, 0); /* final return */ + f.code = LuaC.realloc(f.code, fs.pc); + f.lineinfo = LuaC.realloc(f.lineinfo, fs.pc); + // f.sizelineinfo = fs.pc; + f.k = LuaC.realloc(f.k, fs.nk); + f.p = LuaC.realloc(f.p, fs.np); + f.locvars = LuaC.realloc(f.locvars, fs.nlocvars); + // f.sizelocvars = fs.nlocvars; + f.upvalues = LuaC.realloc(f.upvalues, f.nups); + // LuaC._assert (CheckCode.checkcode(f)); + LuaC._assert (fs.bl == null); + this.fs = fs.prev; +// L.top -= 2; /* remove table and prototype from the stack */ + // /* last token read was anchored in defunct function; must reanchor it + // */ + // if (fs!=null) ls.anchor_token(); + } + + /*============================================================*/ + /* GRAMMAR RULES */ + /*============================================================*/ + + void field(expdesc v) { + /* field -> ['.' | ':'] NAME */ + FuncState fs = this.fs; + expdesc key = new expdesc(); + fs.exp2anyreg(v); + this.next(); /* skip the dot or colon */ + this.checkname(key); + fs.indexed(v, key); + } + + void yindex(expdesc v) { + /* index -> '[' expr ']' */ + this.next(); /* skip the '[' */ + this.expr(v); + this.fs.exp2val(v); + this.checknext(']'); + } + + + /* + ** {====================================================================== + ** Rules for Constructors + ** ======================================================================= + */ + + + static class ConsControl { + expdesc v = new expdesc(); /* last list item read */ + expdesc t; /* table descriptor */ + int nh; /* total number of `record' elements */ + int na; /* total number of array elements */ + int tostore; /* number of array elements pending to be stored */ + }; + + + void recfield(ConsControl cc) { + /* recfield -> (NAME | `['exp1`]') = exp1 */ + FuncState fs = this.fs; + int reg = this.fs.freereg; + expdesc key = new expdesc(); + expdesc val = new expdesc(); + int rkkey; + if (this.t.token == TK_NAME) { + fs.checklimit(cc.nh, MAX_INT, "items in a constructor"); + this.checkname(key); + } else + /* this.t.token == '[' */ + this.yindex(key); + cc.nh++; + this.checknext('='); + rkkey = fs.exp2RK(key); + this.expr(val); + fs.codeABC(Lua.OP_SETTABLE, cc.t.u.s.info, rkkey, fs.exp2RK(val)); + fs.freereg = reg; /* free registers */ + } + + void listfield (ConsControl cc) { + this.expr(cc.v); + fs.checklimit(cc.na, MAX_INT, "items in a constructor"); + cc.na++; + cc.tostore++; + } + + + void constructor(expdesc t) { + /* constructor -> ?? */ + FuncState fs = this.fs; + int line = this.linenumber; + int pc = fs.codeABC(Lua.OP_NEWTABLE, 0, 0, 0); + ConsControl cc = new ConsControl(); + cc.na = cc.nh = cc.tostore = 0; + cc.t = t; + t.init(VRELOCABLE, pc); + cc.v.init(VVOID, 0); /* no value (yet) */ + fs.exp2nextreg(t); /* fix it at stack top (for gc) */ + this.checknext('{'); + do { + LuaC._assert (cc.v.k == VVOID || cc.tostore > 0); + if (this.t.token == '}') + break; + fs.closelistfield(cc); + switch (this.t.token) { + case TK_NAME: { /* may be listfields or recfields */ + this.lookahead(); + if (this.lookahead.token != '=') /* expression? */ + this.listfield(cc); + else + this.recfield(cc); + break; + } + case '[': { /* constructor_item -> recfield */ + this.recfield(cc); + break; + } + default: { /* constructor_part -> listfield */ + this.listfield(cc); + break; + } + } + } while (this.testnext(',') || this.testnext(';')); + this.check_match('}', '{', line); + fs.lastlistfield(cc); + InstructionPtr i = new InstructionPtr(fs.f.code, pc); + LuaC.SETARG_B(i, luaO_int2fb(cc.na)); /* set initial array size */ + LuaC.SETARG_C(i, luaO_int2fb(cc.nh)); /* set initial table size */ + } + + /* + ** converts an integer to a "floating point byte", represented as + ** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if + ** eeeee != 0 and (xxx) otherwise. + */ + static int luaO_int2fb (int x) { + int e = 0; /* expoent */ + while (x >= 16) { + x = (x+1) >> 1; + e++; + } + if (x < 8) return x; + else return ((e+1) << 3) | (((int)x) - 8); + } + + + /* }====================================================================== */ + + void parlist () { + /* parlist -> [ param { `,' param } ] */ + FuncState fs = this.fs; + Prototype f = fs.f; + int nparams = 0; + f.is_vararg = 0; + if (this.t.token != ')') { /* is `parlist' not empty? */ + do { + switch (this.t.token) { + case TK_NAME: { /* param . NAME */ + this.new_localvar(this.str_checkname(), nparams++); + break; + } + case TK_DOTS: { /* param . `...' */ + this.next(); + if (LUA_COMPAT_VARARG) { + /* use `arg' as default name */ + this.new_localvarliteral("arg", nparams++); + f.is_vararg = LuaC.VARARG_HASARG | LuaC.VARARG_NEEDSARG; + } + f.is_vararg |= LuaC.VARARG_ISVARARG; + break; + } + default: this.syntaxerror(" or " + LUA_QL("...") + " expected"); + } + } while ((f.is_vararg==0) && this.testnext(',')); + } + this.adjustlocalvars(nparams); + f.numparams = (fs.nactvar - (f.is_vararg & LuaC.VARARG_HASARG)); + fs.reserveregs(fs.nactvar); /* reserve register for parameters */ + } + + + void body(expdesc e, boolean needself, int line) { + /* body -> `(' parlist `)' chunk END */ + FuncState new_fs = new FuncState(); + open_func(new_fs); + new_fs.f.linedefined = line; + this.checknext('('); + if (needself) { + new_localvarliteral("self", 0); + adjustlocalvars(1); + } + this.parlist(); + this.checknext(')'); + this.chunk(); + new_fs.f.lastlinedefined = this.linenumber; + this.check_match(TK_END, TK_FUNCTION, line); + this.close_func(); + this.pushclosure(new_fs, e); + } + + int explist1(expdesc v) { + /* explist1 -> expr { `,' expr } */ + int n = 1; /* at least one expression */ + this.expr(v); + while (this.testnext(',')) { + fs.exp2nextreg(v); + this.expr(v); + n++; + } + return n; + } + + + void funcargs(expdesc f) { + FuncState fs = this.fs; + expdesc args = new expdesc(); + int base, nparams; + int line = this.linenumber; + switch (this.t.token) { + case '(': { /* funcargs -> `(' [ explist1 ] `)' */ + if (line != this.lastline) + this.syntaxerror("ambiguous syntax (function call x new statement)"); + this.next(); + if (this.t.token == ')') /* arg list is empty? */ + args.k = VVOID; + else { + this.explist1(args); + fs.setmultret(args); + } + this.check_match(')', '(', line); + break; + } + case '{': { /* funcargs -> constructor */ + this.constructor(args); + break; + } + case TK_STRING: { /* funcargs -> STRING */ + this.codestring(args, this.t.seminfo.ts); + this.next(); /* must use `seminfo' before `next' */ + break; + } + default: { + this.syntaxerror("function arguments expected"); + return; + } + } + LuaC._assert (f.k == VNONRELOC); + base = f.u.s.info; /* base register for call */ + if (hasmultret(args.k)) + nparams = Lua.LUA_MULTRET; /* open call */ + else { + if (args.k != VVOID) + fs.exp2nextreg(args); /* close last argument */ + nparams = fs.freereg - (base + 1); + } + f.init(VCALL, fs.codeABC(Lua.OP_CALL, base, nparams + 1, 2)); + fs.fixline(line); + fs.freereg = base+1; /* call remove function and arguments and leaves + * (unless changed) one result */ + } + + + /* + ** {====================================================================== + ** Expression parsing + ** ======================================================================= + */ + + void prefixexp(expdesc v) { + /* prefixexp -> NAME | '(' expr ')' */ + switch (this.t.token) { + case '(': { + int line = this.linenumber; + this.next(); + this.expr(v); + this.check_match(')', '(', line); + fs.dischargevars(v); + return; + } + case TK_NAME: { + this.singlevar(v); + return; + } + default: { + this.syntaxerror("unexpected symbol"); + return; + } + } + } + + + void primaryexp(expdesc v) { + /* + * primaryexp -> prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | + * funcargs } + */ + FuncState fs = this.fs; + this.prefixexp(v); + for (;;) { + switch (this.t.token) { + case '.': { /* field */ + this.field(v); + break; + } + case '[': { /* `[' exp1 `]' */ + expdesc key = new expdesc(); + fs.exp2anyreg(v); + this.yindex(key); + fs.indexed(v, key); + break; + } + case ':': { /* `:' NAME funcargs */ + expdesc key = new expdesc(); + this.next(); + this.checkname(key); + fs.self(v, key); + this.funcargs(v); + break; + } + case '(': + case TK_STRING: + case '{': { /* funcargs */ + fs.exp2nextreg(v); + this.funcargs(v); + break; + } + default: + return; + } + } + } + + + void simpleexp(expdesc v) { + /* + * simpleexp -> NUMBER | STRING | NIL | true | false | ... | constructor | + * FUNCTION body | primaryexp + */ + switch (this.t.token) { + case TK_NUMBER: { + v.init(VKNUM, 0); + v.u.setNval(this.t.seminfo.r); + break; + } + case TK_STRING: { + this.codestring(v, this.t.seminfo.ts); + break; + } + case TK_NIL: { + v.init(VNIL, 0); + break; + } + case TK_TRUE: { + v.init(VTRUE, 0); + break; + } + case TK_FALSE: { + v.init(VFALSE, 0); + break; + } + case TK_DOTS: { /* vararg */ + FuncState fs = this.fs; + this.check_condition(fs.f.is_vararg!=0, "cannot use " + LUA_QL("...") + + " outside a vararg function"); + fs.f.is_vararg &= ~LuaC.VARARG_NEEDSARG; /* don't need 'arg' */ + v.init(VVARARG, fs.codeABC(Lua.OP_VARARG, 0, 1, 0)); + break; + } + case '{': { /* constructor */ + this.constructor(v); + return; + } + case TK_FUNCTION: { + this.next(); + this.body(v, false, this.linenumber); + return; + } + default: { + this.primaryexp(v); + return; + } + } + this.next(); + } + + + int getunopr(int op) { + switch (op) { + case TK_NOT: + return OPR_NOT; + case '-': + return OPR_MINUS; + case '#': + return OPR_LEN; + default: + return OPR_NOUNOPR; + } + } + + + int getbinopr(int op) { + switch (op) { + case '+': + return OPR_ADD; + case '-': + return OPR_SUB; + case '*': + return OPR_MUL; + case '/': + return OPR_DIV; + case '%': + return OPR_MOD; + case '^': + return OPR_POW; + case TK_CONCAT: + return OPR_CONCAT; + case TK_NE: + return OPR_NE; + case TK_EQ: + return OPR_EQ; + case '<': + return OPR_LT; + case TK_LE: + return OPR_LE; + case '>': + return OPR_GT; + case TK_GE: + return OPR_GE; + case TK_AND: + return OPR_AND; + case TK_OR: + return OPR_OR; + default: + return OPR_NOBINOPR; + } + } + + static class Priority { + final byte left; /* left priority for each binary operator */ + + final byte right; /* right priority */ + + public Priority(int i, int j) { + left = (byte) i; + right = (byte) j; + } + }; + + static Priority[] priority = { /* ORDER OPR */ + new Priority(6, 6), new Priority(6, 6), new Priority(7, 7), new Priority(7, 7), new Priority(7, 7), /* `+' `-' `/' `%' */ + new Priority(10, 9), new Priority(5, 4), /* power and concat (right associative) */ + new Priority(3, 3), new Priority(3, 3), /* equality and inequality */ + new Priority(3, 3), new Priority(3, 3), new Priority(3, 3), new Priority(3, 3), /* order */ + new Priority(2, 2), new Priority(1, 1) /* logical (and/or) */ + }; + + static final int UNARY_PRIORITY = 8; /* priority for unary operators */ + + + /* + ** subexpr -> (simpleexp | unop subexpr) { binop subexpr } + ** where `binop' is any binary operator with a priority higher than `limit' + */ + int subexpr(expdesc v, int limit) { + int op; + int uop; + this.enterlevel(); + uop = getunopr(this.t.token); + if (uop != OPR_NOUNOPR) { + this.next(); + this.subexpr(v, UNARY_PRIORITY); + fs.prefix(uop, v); + } else + this.simpleexp(v); + /* expand while operators have priorities higher than `limit' */ + op = getbinopr(this.t.token); + while (op != OPR_NOBINOPR && priority[op].left > limit) { + expdesc v2 = new expdesc(); + int nextop; + this.next(); + fs.infix(op, v); + /* read sub-expression with higher priority */ + nextop = this.subexpr(v2, priority[op].right); + fs.posfix(op, v, v2); + op = nextop; + } + this.leavelevel(); + return op; /* return first untreated operator */ + } + + void expr(expdesc v) { + this.subexpr(v, 0); + } + + /* }==================================================================== */ + + + + /* + ** {====================================================================== + ** Rules for Statements + ** ======================================================================= + */ + + + boolean block_follow (int token) { + switch (token) { + case TK_ELSE: case TK_ELSEIF: case TK_END: + case TK_UNTIL: case TK_EOS: + return true; + default: return false; + } + } + + + void block () { + /* block -> chunk */ + FuncState fs = this.fs; + BlockCnt bl = new BlockCnt(); + fs.enterblock(bl, false); + this.chunk(); + LuaC._assert(bl.breaklist.i == NO_JUMP); + fs.leaveblock(); + } + + + /* + ** structure to chain all variables in the left-hand side of an + ** assignment + */ + static class LHS_assign { + LHS_assign prev; + /* variable (global, local, upvalue, or indexed) */ + expdesc v = new expdesc(); + }; + + + /* + ** check whether, in an assignment to a local variable, the local variable + ** is needed in a previous assignment (to a table). If so, save original + ** local value in a safe place and use this safe copy in the previous + ** assignment. + */ + void check_conflict (LHS_assign lh, expdesc v) { + FuncState fs = this.fs; + int extra = fs.freereg; /* eventual position to save local variable */ + boolean conflict = false; + for (; lh!=null; lh = lh.prev) { + if (lh.v.k == VINDEXED) { + if (lh.v.u.s.info == v.u.s.info) { /* conflict? */ + conflict = true; + lh.v.u.s.info = extra; /* previous assignment will use safe copy */ + } + if (lh.v.u.s.aux == v.u.s.info) { /* conflict? */ + conflict = true; + lh.v.u.s.aux = extra; /* previous assignment will use safe copy */ + } + } + } + if (conflict) { + fs.codeABC(Lua.OP_MOVE, fs.freereg, v.u.s.info, 0); /* make copy */ + fs.reserveregs(1); + } + } + + + void assignment (LHS_assign lh, int nvars) { + expdesc e = new expdesc(); + this.check_condition(VLOCAL <= lh.v.k && lh.v.k <= VINDEXED, + "syntax error"); + if (this.testnext(',')) { /* assignment -> `,' primaryexp assignment */ + LHS_assign nv = new LHS_assign(); + nv.prev = lh; + this.primaryexp(nv.v); + if (nv.v.k == VLOCAL) + this.check_conflict(lh, nv.v); + this.assignment(nv, nvars+1); + } + else { /* assignment . `=' explist1 */ + int nexps; + this.checknext('='); + nexps = this.explist1(e); + if (nexps != nvars) { + this.adjust_assign(nvars, nexps, e); + if (nexps > nvars) + this.fs.freereg -= nexps - nvars; /* remove extra values */ + } + else { + fs.setoneret(e); /* close last expression */ + fs.storevar(lh.v, e); + return; /* avoid default */ + } + } + e.init(VNONRELOC, this.fs.freereg-1); /* default assignment */ + fs.storevar(lh.v, e); + } + + + int cond() { + /* cond -> exp */ + expdesc v = new expdesc(); + /* read condition */ + this.expr(v); + /* `falses' are all equal here */ + if (v.k == VNIL) + v.k = VFALSE; + fs.goiftrue(v); + return v.f.i; + } + + + void breakstat() { + FuncState fs = this.fs; + BlockCnt bl = fs.bl; + boolean upval = false; + while (bl != null && !bl.isbreakable) { + upval |= bl.upval; + bl = bl.previous; + } + if (bl == null) + this.syntaxerror("no loop to break"); + if (upval) + fs.codeABC(Lua.OP_CLOSE, bl.nactvar, 0, 0); + fs.concat(bl.breaklist, fs.jump()); + } + + + void whilestat (int line) { + /* whilestat -> WHILE cond DO block END */ + FuncState fs = this.fs; + int whileinit; + int condexit; + BlockCnt bl = new BlockCnt(); + this.next(); /* skip WHILE */ + whileinit = fs.getlabel(); + condexit = this.cond(); + fs.enterblock(bl, true); + this.checknext(TK_DO); + this.block(); + fs.patchlist(fs.jump(), whileinit); + this.check_match(TK_END, TK_WHILE, line); + fs.leaveblock(); + fs.patchtohere(condexit); /* false conditions finish the loop */ + } + + void repeatstat(int line) { + /* repeatstat -> REPEAT block UNTIL cond */ + int condexit; + FuncState fs = this.fs; + int repeat_init = fs.getlabel(); + BlockCnt bl1 = new BlockCnt(); + BlockCnt bl2 = new BlockCnt(); + fs.enterblock(bl1, true); /* loop block */ + fs.enterblock(bl2, false); /* scope block */ + this.next(); /* skip REPEAT */ + this.chunk(); + this.check_match(TK_UNTIL, TK_REPEAT, line); + condexit = this.cond(); /* read condition (inside scope block) */ + if (!bl2.upval) { /* no upvalues? */ + fs.leaveblock(); /* finish scope */ + fs.patchlist(condexit, repeat_init); /* close the loop */ + } else { /* complete semantics when there are upvalues */ + this.breakstat(); /* if condition then break */ + fs.patchtohere(condexit); /* else... */ + fs.leaveblock(); /* finish scope... */ + fs.patchlist(fs.jump(), repeat_init); /* and repeat */ + } + fs.leaveblock(); /* finish loop */ + } + + + int exp1() { + expdesc e = new expdesc(); + int k; + this.expr(e); + k = e.k; + fs.exp2nextreg(e); + return k; + } + + + void forbody(int base, int line, int nvars, boolean isnum) { + /* forbody -> DO block */ + BlockCnt bl = new BlockCnt(); + FuncState fs = this.fs; + int prep, endfor; + this.adjustlocalvars(3); /* control variables */ + this.checknext(TK_DO); + prep = isnum ? fs.codeAsBx(Lua.OP_FORPREP, base, NO_JUMP) : fs.jump(); + fs.enterblock(bl, false); /* scope for declared variables */ + this.adjustlocalvars(nvars); + fs.reserveregs(nvars); + this.block(); + fs.leaveblock(); /* end of scope for declared variables */ + fs.patchtohere(prep); + endfor = (isnum) ? fs.codeAsBx(Lua.OP_FORLOOP, base, NO_JUMP) : fs + .codeABC(Lua.OP_TFORLOOP, base, 0, nvars); + fs.fixline(line); /* pretend that `Lua.OP_FOR' starts the loop */ + fs.patchlist((isnum ? endfor : fs.jump()), prep + 1); + } + + + void fornum(LuaString varname, int line) { + /* fornum -> NAME = exp1,exp1[,exp1] forbody */ + FuncState fs = this.fs; + int base = fs.freereg; + this.new_localvarliteral(RESERVED_LOCAL_VAR_FOR_INDEX, 0); + this.new_localvarliteral(RESERVED_LOCAL_VAR_FOR_LIMIT, 1); + this.new_localvarliteral(RESERVED_LOCAL_VAR_FOR_STEP, 2); + this.new_localvar(varname, 3); + this.checknext('='); + this.exp1(); /* initial value */ + this.checknext(','); + this.exp1(); /* limit */ + if (this.testnext(',')) + this.exp1(); /* optional step */ + else { /* default step = 1 */ + fs.codeABx(Lua.OP_LOADK, fs.freereg, fs.numberK(LuaInteger.valueOf(1))); + fs.reserveregs(1); + } + this.forbody(base, line, 1, true); + } + + + void forlist(LuaString indexname) { + /* forlist -> NAME {,NAME} IN explist1 forbody */ + FuncState fs = this.fs; + expdesc e = new expdesc(); + int nvars = 0; + int line; + int base = fs.freereg; + /* create control variables */ + this.new_localvarliteral(RESERVED_LOCAL_VAR_FOR_GENERATOR, nvars++); + this.new_localvarliteral(RESERVED_LOCAL_VAR_FOR_STATE, nvars++); + this.new_localvarliteral(RESERVED_LOCAL_VAR_FOR_CONTROL, nvars++); + /* create declared variables */ + this.new_localvar(indexname, nvars++); + while (this.testnext(',')) + this.new_localvar(this.str_checkname(), nvars++); + this.checknext(TK_IN); + line = this.linenumber; + this.adjust_assign(3, this.explist1(e), e); + fs.checkstack(3); /* extra space to call generator */ + this.forbody(base, line, nvars - 3, false); + } + + + void forstat(int line) { + /* forstat -> FOR (fornum | forlist) END */ + FuncState fs = this.fs; + LuaString varname; + BlockCnt bl = new BlockCnt(); + fs.enterblock(bl, true); /* scope for loop and control variables */ + this.next(); /* skip `for' */ + varname = this.str_checkname(); /* first variable name */ + switch (this.t.token) { + case '=': + this.fornum(varname, line); + break; + case ',': + case TK_IN: + this.forlist(varname); + break; + default: + this.syntaxerror(LUA_QL("=") + " or " + LUA_QL("in") + " expected"); + } + this.check_match(TK_END, TK_FOR, line); + fs.leaveblock(); /* loop scope (`break' jumps to this point) */ + } + + + int test_then_block() { + /* test_then_block -> [IF | ELSEIF] cond THEN block */ + int condexit; + this.next(); /* skip IF or ELSEIF */ + condexit = this.cond(); + this.checknext(TK_THEN); + this.block(); /* `then' part */ + return condexit; + } + + + void ifstat(int line) { + /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] + * END */ + FuncState fs = this.fs; + int flist; + IntPtr escapelist = new IntPtr(NO_JUMP); + flist = test_then_block(); /* IF cond THEN block */ + while (this.t.token == TK_ELSEIF) { + fs.concat(escapelist, fs.jump()); + fs.patchtohere(flist); + flist = test_then_block(); /* ELSEIF cond THEN block */ + } + if (this.t.token == TK_ELSE) { + fs.concat(escapelist, fs.jump()); + fs.patchtohere(flist); + this.next(); /* skip ELSE (after patch, for correct line info) */ + this.block(); /* `else' part */ + } else + fs.concat(escapelist, flist); + fs.patchtohere(escapelist.i); + this.check_match(TK_END, TK_IF, line); + } + + void localfunc() { + expdesc v = new expdesc(); + expdesc b = new expdesc(); + FuncState fs = this.fs; + this.new_localvar(this.str_checkname(), 0); + v.init(VLOCAL, fs.freereg); + fs.reserveregs(1); + this.adjustlocalvars(1); + this.body(b, false, this.linenumber); + fs.storevar(v, b); + /* debug information will only see the variable after this point! */ + fs.getlocvar(fs.nactvar - 1).startpc = fs.pc; + } + + + void localstat() { + /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ + int nvars = 0; + int nexps; + expdesc e = new expdesc(); + do { + this.new_localvar(this.str_checkname(), nvars++); + } while (this.testnext(',')); + if (this.testnext('=')) + nexps = this.explist1(e); + else { + e.k = VVOID; + nexps = 0; + } + this.adjust_assign(nvars, nexps, e); + this.adjustlocalvars(nvars); + } + + + boolean funcname(expdesc v) { + /* funcname -> NAME {field} [`:' NAME] */ + boolean needself = false; + this.singlevar(v); + while (this.t.token == '.') + this.field(v); + if (this.t.token == ':') { + needself = true; + this.field(v); + } + return needself; + } + + + void funcstat(int line) { + /* funcstat -> FUNCTION funcname body */ + boolean needself; + expdesc v = new expdesc(); + expdesc b = new expdesc(); + this.next(); /* skip FUNCTION */ + needself = this.funcname(v); + this.body(b, needself, line); + fs.storevar(v, b); + fs.fixline(line); /* definition `happens' in the first line */ + } + + + void exprstat() { + /* stat -> func | assignment */ + FuncState fs = this.fs; + LHS_assign v = new LHS_assign(); + this.primaryexp(v.v); + if (v.v.k == VCALL) /* stat -> func */ + LuaC.SETARG_C(fs.getcodePtr(v.v), 1); /* call statement uses no results */ + else { /* stat -> assignment */ + v.prev = null; + this.assignment(v, 1); + } + } + + void retstat() { + /* stat -> RETURN explist */ + FuncState fs = this.fs; + expdesc e = new expdesc(); + int first, nret; /* registers with returned values */ + this.next(); /* skip RETURN */ + if (block_follow(this.t.token) || this.t.token == ';') + first = nret = 0; /* return no values */ + else { + nret = this.explist1(e); /* optional return values */ + if (hasmultret(e.k)) { + fs.setmultret(e); + if (e.k == VCALL && nret == 1) { /* tail call? */ + LuaC.SET_OPCODE(fs.getcodePtr(e), Lua.OP_TAILCALL); + LuaC._assert (Lua.GETARG_A(fs.getcode(e)) == fs.nactvar); + } + first = fs.nactvar; + nret = Lua.LUA_MULTRET; /* return all values */ + } else { + if (nret == 1) /* only one single value? */ + first = fs.exp2anyreg(e); + else { + fs.exp2nextreg(e); /* values must go to the `stack' */ + first = fs.nactvar; /* return all `active' values */ + LuaC._assert (nret == fs.freereg - first); + } + } + } + fs.ret(first, nret); + } + + + boolean statement() { + int line = this.linenumber; /* may be needed for error messages */ + switch (this.t.token) { + case TK_IF: { /* stat -> ifstat */ + this.ifstat(line); + return false; + } + case TK_WHILE: { /* stat -> whilestat */ + this.whilestat(line); + return false; + } + case TK_DO: { /* stat -> DO block END */ + this.next(); /* skip DO */ + this.block(); + this.check_match(TK_END, TK_DO, line); + return false; + } + case TK_FOR: { /* stat -> forstat */ + this.forstat(line); + return false; + } + case TK_REPEAT: { /* stat -> repeatstat */ + this.repeatstat(line); + return false; + } + case TK_FUNCTION: { + this.funcstat(line); /* stat -> funcstat */ + return false; + } + case TK_LOCAL: { /* stat -> localstat */ + this.next(); /* skip LOCAL */ + if (this.testnext(TK_FUNCTION)) /* local function? */ + this.localfunc(); + else + this.localstat(); + return false; + } + case TK_RETURN: { /* stat -> retstat */ + this.retstat(); + return true; /* must be last statement */ + } + case TK_BREAK: { /* stat -> breakstat */ + this.next(); /* skip BREAK */ + this.breakstat(); + return true; /* must be last statement */ + } + default: { + this.exprstat(); + return false; /* to avoid warnings */ + } + } + } + + void chunk() { + /* chunk -> { stat [`;'] } */ + boolean islast = false; + this.enterlevel(); + while (!islast && !block_follow(this.t.token)) { + islast = this.statement(); + this.testnext(';'); + LuaC._assert (this.fs.f.maxstacksize >= this.fs.freereg + && this.fs.freereg >= this.fs.nactvar); + this.fs.freereg = this.fs.nactvar; /* free registers */ + } + this.leavelevel(); + } + + /* }====================================================================== */ + +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/compiler/LuaC.java b/luaj-2.0.3/src/core/org/luaj/vm2/compiler/LuaC.java new file mode 100644 index 0000000000..f5bb61bf5d --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/compiler/LuaC.java @@ -0,0 +1,251 @@ +/******************************************************************************* +* Copyright (c) 2009-2011 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.compiler; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Hashtable; + +import org.luaj.vm2.LoadState; +import org.luaj.vm2.LocVars; +import org.luaj.vm2.Lua; +import org.luaj.vm2.LuaClosure; +import org.luaj.vm2.LuaError; +import org.luaj.vm2.LuaFunction; +import org.luaj.vm2.LuaString; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Prototype; +import org.luaj.vm2.LoadState.LuaCompiler; + +/** + * Compiler for Lua. + *

+ * Compiles lua source files into lua bytecode within a {@link Prototype}, + * loads lua binary files directly into a{@link Prototype}, + * and optionaly instantiates a {@link LuaClosure} around the result + * using a user-supplied environment. + *

+ * Implements the {@link LuaCompiler} interface for loading + * initialized chunks, which is an interface common to + * lua bytecode compiling and java bytecode compiling. + *

+ * Teh {@link LuaC} compiler is installed by default by both the + * {@link JsePlatform} and {@link JmePlatform} classes, + * so in the following example, the default {@link LuaC} compiler + * will be used: + *

 {@code
+ * LuaValue _G = JsePlatform.standardGlobals();
+ * LoadState.load( new ByteArrayInputStream("print 'hello'".getBytes()), "main.lua", _G ).call();
+ * } 
+ * @see LuaCompiler + * @see LuaJC + * @see JsePlatform + * @see JmePlatform + * @see BaseLib + * @see LuaValue + * @see LuaCompiler + * @see Prototype + */ +public class LuaC extends Lua implements LuaCompiler { + + public static final LuaC instance = new LuaC(); + + /** Install the compiler so that LoadState will first + * try to use it when handed bytes that are + * not already a compiled lua chunk. + */ + public static void install() { + org.luaj.vm2.LoadState.compiler = instance; + } + + protected static void _assert(boolean b) { + if (!b) + throw new LuaError("compiler assert failed"); + } + + public static final int MAXSTACK = 250; + static final int LUAI_MAXUPVALUES = 60; + static final int LUAI_MAXVARS = 200; + static final int NO_REG = MAXARG_A; + + + /* OpMode - basic instruction format */ + static final int + iABC = 0, + iABx = 1, + iAsBx = 2; + + /* OpArgMask */ + static final int + OpArgN = 0, /* argument is not used */ + OpArgU = 1, /* argument is used */ + OpArgR = 2, /* argument is a register or a jump offset */ + OpArgK = 3; /* argument is a constant or register/constant */ + + + static void SET_OPCODE(InstructionPtr i,int o) { + i.set( ( i.get() & (MASK_NOT_OP)) | ((o << POS_OP) & MASK_OP) ); + } + + static void SETARG_A(InstructionPtr i,int u) { + i.set( ( i.get() & (MASK_NOT_A)) | ((u << POS_A) & MASK_A) ); + } + + static void SETARG_B(InstructionPtr i,int u) { + i.set( ( i.get() & (MASK_NOT_B)) | ((u << POS_B) & MASK_B) ); + } + + static void SETARG_C(InstructionPtr i,int u) { + i.set( ( i.get() & (MASK_NOT_C)) | ((u << POS_C) & MASK_C) ); + } + + static void SETARG_Bx(InstructionPtr i,int u) { + i.set( ( i.get() & (MASK_NOT_Bx)) | ((u << POS_Bx) & MASK_Bx) ); + } + + static void SETARG_sBx(InstructionPtr i,int u) { + SETARG_Bx( i, u + MAXARG_sBx ); + } + + static int CREATE_ABC(int o, int a, int b, int c) { + return ((o << POS_OP) & MASK_OP) | + ((a << POS_A) & MASK_A) | + ((b << POS_B) & MASK_B) | + ((c << POS_C) & MASK_C) ; + } + + static int CREATE_ABx(int o, int a, int bc) { + return ((o << POS_OP) & MASK_OP) | + ((a << POS_A) & MASK_A) | + ((bc << POS_Bx) & MASK_Bx) ; + } + + // vector reallocation + + static LuaValue[] realloc(LuaValue[] v, int n) { + LuaValue[] a = new LuaValue[n]; + if ( v != null ) + System.arraycopy(v, 0, a, 0, Math.min(v.length,n)); + return a; + } + + static Prototype[] realloc(Prototype[] v, int n) { + Prototype[] a = new Prototype[n]; + if ( v != null ) + System.arraycopy(v, 0, a, 0, Math.min(v.length,n)); + return a; + } + + static LuaString[] realloc(LuaString[] v, int n) { + LuaString[] a = new LuaString[n]; + if ( v != null ) + System.arraycopy(v, 0, a, 0, Math.min(v.length,n)); + return a; + } + + static LocVars[] realloc(LocVars[] v, int n) { + LocVars[] a = new LocVars[n]; + if ( v != null ) + System.arraycopy(v, 0, a, 0, Math.min(v.length,n)); + return a; + } + + static int[] realloc(int[] v, int n) { + int[] a = new int[n]; + if ( v != null ) + System.arraycopy(v, 0, a, 0, Math.min(v.length,n)); + return a; + } + + static byte[] realloc(byte[] v, int n) { + byte[] a = new byte[n]; + if ( v != null ) + System.arraycopy(v, 0, a, 0, Math.min(v.length,n)); + return a; + } + + public int nCcalls; + Hashtable strings; + + protected LuaC() {} + + private LuaC(Hashtable strings) { + this.strings = strings; + } + + /** Load into a Closure or LuaFunction, with the supplied initial environment */ + public LuaFunction load(InputStream stream, String name, LuaValue env) throws IOException { + Prototype p = compile( stream, name ); + return new LuaClosure( p, env ); + } + + /** Compile a prototype or load as a binary chunk */ + public static Prototype compile(InputStream stream, String name) throws IOException { + int firstByte = stream.read(); + return ( firstByte == '\033' )? + LoadState.loadBinaryChunk(firstByte, stream, name): + (new LuaC(new Hashtable())).luaY_parser(firstByte, stream, name); + } + + /** Parse the input */ + private Prototype luaY_parser(int firstByte, InputStream z, String name) { + LexState lexstate = new LexState(this, z); + FuncState funcstate = new FuncState(); + // lexstate.buff = buff; + lexstate.setinput( this, firstByte, z, (LuaString) LuaValue.valueOf(name) ); + lexstate.open_func(funcstate); + /* main func. is always vararg */ + funcstate.f.is_vararg = LuaC.VARARG_ISVARARG; + funcstate.f.source = (LuaString) LuaValue.valueOf(name); + lexstate.next(); /* read first token */ + lexstate.chunk(); + lexstate.check(LexState.TK_EOS); + lexstate.close_func(); + LuaC._assert (funcstate.prev == null); + LuaC._assert (funcstate.f.nups == 0); + LuaC._assert (lexstate.fs == null); + return funcstate.f; + } + + // look up and keep at most one copy of each string + public LuaString newTString(byte[] bytes, int offset, int len) { + LuaString tmp = LuaString.valueOf(bytes, offset, len); + LuaString v = (LuaString) strings.get(tmp); + if ( v == null ) { + // must copy bytes, since bytes could be from reusable buffer + byte[] copy = new byte[len]; + System.arraycopy(bytes, offset, copy, 0, len); + v = LuaString.valueOf(copy); + strings.put(v, v); + } + return v; + } + + public String pushfstring(String string) { + return string; + } + + public LuaFunction load(Prototype p, String filename, LuaValue env) { + return new LuaClosure( p, env ); + } + +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/lib/BaseLib.java b/luaj-2.0.3/src/core/org/luaj/vm2/lib/BaseLib.java new file mode 100644 index 0000000000..717d0a50e0 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/lib/BaseLib.java @@ -0,0 +1,430 @@ +/******************************************************************************* +* Copyright (c) 2009 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.lib; + +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; + +import org.luaj.vm2.LoadState; +import org.luaj.vm2.Lua; +import org.luaj.vm2.LuaError; +import org.luaj.vm2.LuaString; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaThread; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; + +/** + * Subclass of {@link LibFunction} which implements the lua basic library functions. + *

+ * This contains all library functions listed as "basic functions" in the lua documentation for JME. + * The functions dofile and loadfile use the + * {@link #FINDER} instance to find resource files. + * Since JME has no file system by default, {@link BaseLib} implements + * {@link ResourceFinder} using {@link Class#getResource(String)}, + * which is the closest equivalent on JME. + * The default loader chain in {@link PackageLib} will use these as well. + *

+ * To use basic library functions that include a {@link ResourceFinder} based on + * directory lookup, use {@link JseBaseLib} instead. + *

+ * Typically, this library is included as part of a call to either + * {@link JmePlatform#standardGlobals()} + *

+ * To instantiate and use it directly, + * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: + *

 {@code
+ * LuaTable _G = new LuaTable();
+ * LuaThread.setGlobals(_G);
+ * _G.load(new BaseLib());
+ * _G.get("print").call(LuaValue.valueOf("hello, world"));
+ * } 
+ * Doing so will ensure the library is properly initialized + * and loaded into the globals table. + *

+ * This is a direct port of the corresponding library in C. + * @see JseBaseLib + * @see ResourceFinder + * @see #FINDER + * @see LibFunction + * @see JsePlatform + * @see JmePlatform + * @see http://www.lua.org/manual/5.1/manual.html#5.1 + */ +public class BaseLib extends OneArgFunction implements ResourceFinder { + + public static BaseLib instance; + + public InputStream STDIN = null; + public PrintStream STDOUT = System.out; + public PrintStream STDERR = System.err; + + /** + * Singleton file opener for this Java ClassLoader realm. + * + * Unless set or changed elsewhere, will be set by the BaseLib that is created. + */ + public static ResourceFinder FINDER; + + private LuaValue next; + private LuaValue inext; + + private static final String[] LIB2_KEYS = { + "collectgarbage", // ( opt [,arg] ) -> value + "error", // ( message [,level] ) -> ERR + "setfenv", // (f, table) -> void + }; + private static final String[] LIBV_KEYS = { + "assert", // ( v [,message] ) -> v, message | ERR + "dofile", // ( filename ) -> result1, ... + "getfenv", // ( [f] ) -> env + "getmetatable", // ( object ) -> table + "load", // ( func [,chunkname] ) -> chunk | nil, msg + "loadfile", // ( [filename] ) -> chunk | nil, msg + "loadstring", // ( string [,chunkname] ) -> chunk | nil, msg + "pcall", // (f, arg1, ...) -> status, result1, ... + "xpcall", // (f, err) -> result1, ... + "print", // (...) -> void + "select", // (f, ...) -> value1, ... + "unpack", // (list [,i [,j]]) -> result1, ... + "type", // (v) -> value + "rawequal", // (v1, v2) -> boolean + "rawget", // (table, index) -> value + "rawset", // (table, index, value) -> table + "setmetatable", // (table, metatable) -> table + "tostring", // (e) -> value + "tonumber", // (e [,base]) -> value + "pairs", // "pairs" (t) -> iter-func, t, nil + "ipairs", // "ipairs", // (t) -> iter-func, t, 0 + "next", // "next" ( table, [index] ) -> next-index, next-value + "__inext", // "inext" ( table, [int-index] ) -> next-index, next-value + }; + + /** + * Construct a base libarary instance. + */ + public BaseLib() { + instance = this; + } + + public LuaValue call(LuaValue arg) { + env.set( "_G", env ); + env.set( "_VERSION", Lua._VERSION ); + bind( env, BaseLib2.class, LIB2_KEYS ); + bind( env, BaseLibV.class, LIBV_KEYS ); + + // remember next, and inext for use in pairs and ipairs + next = env.get("next"); + inext = env.get("__inext"); + + // inject base lib int vararg instances + for ( int i=0; i value + String s = arg1.checkjstring(); + int result = 0; + if ( "collect".equals(s) ) { + System.gc(); + return ZERO; + } else if ( "count".equals(s) ) { + Runtime rt = Runtime.getRuntime(); + long used = rt.totalMemory() - rt.freeMemory(); + return valueOf(used/1024.); + } else if ( "step".equals(s) ) { + System.gc(); + return LuaValue.TRUE; + } else { + this.argerror(1, "gc op"); + } + return NIL; + case 1: // "error", // ( message [,level] ) -> ERR + throw new LuaError( arg1.isnil()? null: arg1.tojstring(), arg2.optint(1) ); + case 2: { // "setfenv", // (f, table) -> void + LuaTable t = arg2.checktable(); + LuaValue f = getfenvobj(arg1); + if ( ! f.isthread() && ! f.isclosure() ) + error("'setfenv' cannot change environment of given object"); + f.setfenv(t); + return f.isthread()? NONE: f; + } + } + return NIL; + } + } + + private static LuaValue getfenvobj(LuaValue arg) { + if ( arg.isfunction() ) + return arg; + int level = arg.optint(1); + arg.argcheck(level>=0, 1, "level must be non-negative"); + if ( level == 0 ) + return LuaThread.getRunning(); + LuaValue f = LuaThread.getCallstackFunction(level); + arg.argcheck(f != null, 1, "invalid level"); + return f; + } + + static final class BaseLibV extends VarArgFunction { + public BaseLib baselib; + public Varargs invoke(Varargs args) { + switch ( opcode ) { + case 0: // "assert", // ( v [,message] ) -> v, message | ERR + if ( !args.arg1().toboolean() ) + error( args.narg()>1? args.optjstring(2,"assertion failed!"): "assertion failed!" ); + return args; + case 1: // "dofile", // ( filename ) -> result1, ... + { + Varargs v = args.isnil(1)? + BaseLib.loadStream( baselib.STDIN, "=stdin" ): + BaseLib.loadFile( args.checkjstring(1) ); + return v.isnil(1)? error(v.tojstring(2)): v.arg1().invoke(); + } + case 2: // "getfenv", // ( [f] ) -> env + { + LuaValue f = getfenvobj(args.arg1()); + LuaValue e = f.getfenv(); + return e!=null? e: NIL; + } + case 3: // "getmetatable", // ( object ) -> table + { + LuaValue mt = args.checkvalue(1).getmetatable(); + return mt!=null? mt.rawget(METATABLE).optvalue(mt): NIL; + } + case 4: // "load", // ( func [,chunkname] ) -> chunk | nil, msg + { + LuaValue func = args.checkfunction(1); + String chunkname = args.optjstring(2, "function"); + return BaseLib.loadStream(new StringInputStream(func), chunkname); + } + case 5: // "loadfile", // ( [filename] ) -> chunk | nil, msg + { + return args.isnil(1)? + BaseLib.loadStream( baselib.STDIN, "stdin" ): + BaseLib.loadFile( args.checkjstring(1) ); + } + case 6: // "loadstring", // ( string [,chunkname] ) -> chunk | nil, msg + { + LuaString script = args.checkstring(1); + String chunkname = args.optjstring(2, "string"); + return BaseLib.loadStream(script.toInputStream(),chunkname); + } + case 7: // "pcall", // (f, arg1, ...) -> status, result1, ... + { + LuaValue func = args.checkvalue(1); + LuaThread.CallStack cs = LuaThread.onCall(this); + try { + return pcall(func,args.subargs(2),null); + } finally { + cs.onReturn(); + } + } + case 8: // "xpcall", // (f, err) -> result1, ... + { + LuaThread.CallStack cs = LuaThread.onCall(this); + try { + return pcall(args.arg1(),NONE,args.checkvalue(2)); + } finally { + cs.onReturn(); + } + } + case 9: // "print", // (...) -> void + { + LuaValue tostring = LuaThread.getGlobals().get("tostring"); + for ( int i=1, n=args.narg(); i<=n; i++ ) { + if ( i>1 ) baselib.STDOUT.write( '\t' ); + LuaString s = tostring.call( args.arg(i) ).strvalue(); + int z = s.indexOf((byte)0, 0); + baselib.STDOUT.write( s.m_bytes, s.m_offset, z>=0? z: s.m_length ); + } + baselib.STDOUT.println(); + return NONE; + } + case 10: // "select", // (f, ...) -> value1, ... + { + int n = args.narg()-1; + if ( args.arg1().equals(valueOf("#")) ) + return valueOf(n); + int i = args.checkint(1); + if ( i == 0 || i < -n ) + argerror(1,"index out of range"); + return args.subargs(i<0? n+i+2: i+1); + } + case 11: // "unpack", // (list [,i [,j]]) -> result1, ... + { + int na = args.narg(); + LuaTable t = args.checktable(1); + int n = t.length(); + int i = na>=2? args.checkint(2): 1; + int j = na>=3? args.checkint(3): n; + n = j-i+1; + if ( n<0 ) return NONE; + if ( n==1 ) return t.get(i); + if ( n==2 ) return varargsOf(t.get(i),t.get(j)); + LuaValue[] v = new LuaValue[n]; + for ( int k=0; k value + return valueOf(args.checkvalue(1).typename()); + case 13: // "rawequal", // (v1, v2) -> boolean + return valueOf(args.checkvalue(1) == args.checkvalue(2)); + case 14: // "rawget", // (table, index) -> value + return args.checktable(1).rawget(args.checkvalue(2)); + case 15: { // "rawset", // (table, index, value) -> table + LuaTable t = args.checktable(1); + t.rawset(args.checknotnil(2), args.checkvalue(3)); + return t; + } + case 16: { // "setmetatable", // (table, metatable) -> table + final LuaValue t = args.arg1(); + final LuaValue mt0 = t.getmetatable(); + if ( mt0!=null && !mt0.rawget(METATABLE).isnil() ) + error("cannot change a protected metatable"); + final LuaValue mt = args.checkvalue(2); + return t.setmetatable(mt.isnil()? null: mt.checktable()); + } + case 17: { // "tostring", // (e) -> value + LuaValue arg = args.checkvalue(1); + LuaValue h = arg.metatag(TOSTRING); + if ( ! h.isnil() ) + return h.call(arg); + LuaValue v = arg.tostring(); + if ( ! v.isnil() ) + return v; + return valueOf(arg.tojstring()); + } + case 18: { // "tonumber", // (e [,base]) -> value + LuaValue arg1 = args.checkvalue(1); + final int base = args.optint(2,10); + if (base == 10) { /* standard conversion */ + return arg1.tonumber(); + } else { + if ( base < 2 || base > 36 ) + argerror(2, "base out of range"); + return arg1.checkstring().tonumber(base); + } + } + case 19: // "pairs" (t) -> iter-func, t, nil + return varargsOf( baselib.next, args.checktable(1), NIL ); + case 20: // "ipairs", // (t) -> iter-func, t, 0 + return varargsOf( baselib.inext, args.checktable(1), ZERO ); + case 21: // "next" ( table, [index] ) -> next-index, next-value + return args.checktable(1).next(args.arg(2)); + case 22: // "inext" ( table, [int-index] ) -> next-index, next-value + return args.checktable(1).inext(args.arg(2)); + } + return NONE; + } + } + + public static Varargs pcall(LuaValue func, Varargs args, LuaValue errfunc) { + LuaValue olderr = LuaThread.setErrorFunc(errfunc); + try { + Varargs result = varargsOf(LuaValue.TRUE, func.invoke(args)); + LuaThread.setErrorFunc(olderr); + return result; + } catch ( LuaError le ) { + LuaThread.setErrorFunc(olderr); + String m = le.getMessage(); + return varargsOf(FALSE, m!=null? valueOf(m): NIL); + } catch ( Exception e ) { + LuaThread.setErrorFunc(olderr); + String m = e.getMessage(); + return varargsOf(FALSE, valueOf(m!=null? m: e.toString())); + } + } + + /** + * Load from a named file, returning the chunk or nil,error of can't load + * @return Varargs containing chunk, or NIL,error-text on error + */ + public static Varargs loadFile(String filename) { + InputStream is = FINDER.findResource(filename); + if ( is == null ) + return varargsOf(NIL, valueOf("cannot open "+filename+": No such file or directory")); + try { + return loadStream(is, "@"+filename); + } finally { + try { + is.close(); + } catch ( Exception e ) { + e.printStackTrace(); + } + } + } + + public static Varargs loadStream(InputStream is, String chunkname) { + try { + if ( is == null ) + return varargsOf(NIL, valueOf("not found: "+chunkname)); + return LoadState.load(is, chunkname, LuaThread.getGlobals()); + } catch (Exception e) { + return varargsOf(NIL, valueOf(e.getMessage())); + } + } + + + private static class StringInputStream extends InputStream { + final LuaValue func; + byte[] bytes; + int offset, remaining = 0; + StringInputStream(LuaValue func) { + this.func = func; + } + public int read() throws IOException { + if ( remaining <= 0 ) { + LuaValue s = func.call(); + if ( s.isnil() ) + return -1; + LuaString ls = s.strvalue(); + bytes = ls.m_bytes; + offset = ls.m_offset; + remaining = ls.m_length; + if (remaining <= 0) + return -1; + } + --remaining; + return bytes[offset++]; + } + } +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/lib/CoroutineLib.java b/luaj-2.0.3/src/core/org/luaj/vm2/lib/CoroutineLib.java new file mode 100644 index 0000000000..5eb1b15468 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/lib/CoroutineLib.java @@ -0,0 +1,134 @@ +/******************************************************************************* +* Copyright (c) 2007-2011 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. +******************************************************************************/ +package org.luaj.vm2.lib; + +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaThread; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; + +/** + * Subclass of {@link LibFunction} which implements the lua standard {@code coroutine} + * library. + *

+ * The coroutine library in luaj has the same behavior as the + * coroutine library in C, but is implemented using Java Threads to maintain + * the call state between invocations. Therefore it can be yielded from anywhere, + * similar to the "Coco" yield-from-anywhere patch available for C-based lua. + * However, coroutines that are yielded but never resumed to complete their execution + * may not be collected by the garbage collector. + *

+ * Typically, this library is included as part of a call to either + * {@link JsePlatform#standardGlobals()} or {@link JmePlatform#standardGlobals()} + *

+ * To instantiate and use it directly, + * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: + *

 {@code
+ * LuaTable _G = new LuaTable();
+ * _G.load(new CoroutineLib());
+ * } 
+ * Doing so will ensure the library is properly initialized + * and loaded into the globals table. + *

+ * @see LibFunction + * @see JsePlatform + * @see JmePlatform + * @see http://www.lua.org/manual/5.1/manual.html#5.2 + */ +public class CoroutineLib extends VarArgFunction { + + private static final int INIT = 0; + private static final int CREATE = 1; + private static final int RESUME = 2; + private static final int RUNNING = 3; + private static final int STATUS = 4; + private static final int YIELD = 5; + private static final int WRAP = 6; + private static final int WRAPPED = 7; + + public CoroutineLib() { + } + + private LuaTable init() { + LuaTable t = new LuaTable(); + bind(t, CoroutineLib.class, new String[] { + "create", "resume", "running", "status", "yield", "wrap" }, + CREATE); + env.set("coroutine", t); + PackageLib.instance.LOADED.set("coroutine", t); + return t; + } + + public Varargs invoke(Varargs args) { + switch ( opcode ) { + case INIT: { + return init(); + } + case CREATE: { + final LuaValue func = args.checkfunction(1); + /* DAN200 START */ + //return new LuaThread(func, LuaThread.getGlobals() ); + final LuaThread thread = new LuaThread( func, LuaThread.getGlobals() ); + LuaThread.getRunning().addChild( thread ); + return thread; + /* DAN200 END */ + } + case RESUME: { + final LuaThread t = args.checkthread(1); + return t.resume( args.subargs(2) ); + } + case RUNNING: { + final LuaThread r = LuaThread.getRunning(); + return LuaThread.isMainThread(r)? NIL: r; + } + case STATUS: { + return valueOf( args.checkthread(1).getStatus() ); + } + case YIELD: { + return LuaThread.yield( args ); + } + case WRAP: { + final LuaValue func = args.checkfunction(1); + final LuaThread thread = new LuaThread(func, func.getfenv()); + /* DAN200 START */ + LuaThread.getRunning().addChild( thread ); + /* DAN200 END */ + CoroutineLib cl = new CoroutineLib(); + cl.setfenv(thread); + cl.name = "wrapped"; + cl.opcode = WRAPPED; + return cl; + } + case WRAPPED: { + final LuaThread t = (LuaThread) env; + final Varargs result = t.resume( args ); + if ( result.arg1().toboolean() ) { + return result.subargs(2); + } else { + error( result.arg(2).tojstring() ); + } + } + default: + return NONE; + } + } +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/lib/DebugLib.java b/luaj-2.0.3/src/core/org/luaj/vm2/lib/DebugLib.java new file mode 100644 index 0000000000..da3e103a62 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/lib/DebugLib.java @@ -0,0 +1,977 @@ +/******************************************************************************* +* Copyright (c) 2009-2011 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.lib; + +import java.lang.ref.WeakReference; + +import org.luaj.vm2.Lua; +import org.luaj.vm2.LuaBoolean; +import org.luaj.vm2.LuaClosure; +import org.luaj.vm2.LuaError; +import org.luaj.vm2.LuaFunction; +import org.luaj.vm2.LuaNil; +import org.luaj.vm2.LuaNumber; +import org.luaj.vm2.LuaString; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaThread; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Print; +import org.luaj.vm2.Prototype; +import org.luaj.vm2.Varargs; + +/** + * Subclass of {@link LibFunction} which implements the lua standard {@code debug} + * library. + *

+ * The debug library in luaj tries to emulate the behavior of the corresponding C-based lua library. + * To do this, it must maintain a separate stack of calls to {@link LuaClosure} and {@link LibFunction} + * instances. + * Especially when lua-to-java bytecode compiling is being used + * via a {@link LuaCompiler} such as {@link LuaJC}, + * this cannot be done in all cases. + *

+ * Typically, this library is included as part of a call to either + * {@link JsePlatform#debugGlobals()} or {@link JmePlatform#debugGlobals()} + *

+ * To instantiate and use it directly, + * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: + *

 {@code
+ * LuaTable _G = new LuaTable();
+ * _G.load(new DebugLib());
+ * } 
+ * Doing so will ensure the library is properly initialized + * and loaded into the globals table. + *

+ * @see LibFunction + * @see JsePlatform + * @see JmePlatform + * @see http://www.lua.org/manual/5.1/manual.html#5.9 + */ +public class DebugLib extends VarArgFunction { + public static final boolean CALLS = (null != System.getProperty("CALLS")); + public static final boolean TRACE = (null != System.getProperty("TRACE")); + + // leave this unset to allow obfuscators to + // remove it in production builds + public static boolean DEBUG_ENABLED; + + static final String[] NAMES = { + "debug", + "getfenv", + "gethook", + "getinfo", + "getlocal", + "getmetatable", + "getregistry", + "getupvalue", + "setfenv", + "sethook", + "setlocal", + "setmetatable", + "setupvalue", + "traceback", + }; + + private static final int INIT = 0; + private static final int DEBUG = 1; + private static final int GETFENV = 2; + private static final int GETHOOK = 3; + private static final int GETINFO = 4; + private static final int GETLOCAL = 5; + private static final int GETMETATABLE = 6; + private static final int GETREGISTRY = 7; + private static final int GETUPVALUE = 8; + private static final int SETFENV = 9; + private static final int SETHOOK = 10; + private static final int SETLOCAL = 11; + private static final int SETMETATABLE = 12; + private static final int SETUPVALUE = 13; + private static final int TRACEBACK = 14; + + /* maximum stack for a Lua function */ + private static final int MAXSTACK = 250; + + private static final LuaString LUA = valueOf("Lua"); + private static final LuaString JAVA = valueOf("Java"); + private static final LuaString QMARK = valueOf("?"); + private static final LuaString GLOBAL = valueOf("global"); + private static final LuaString LOCAL = valueOf("local"); + private static final LuaString METHOD = valueOf("method"); + private static final LuaString UPVALUE = valueOf("upvalue"); + private static final LuaString FIELD = valueOf("field"); + private static final LuaString CALL = valueOf("call"); + private static final LuaString LINE = valueOf("line"); + private static final LuaString COUNT = valueOf("count"); + private static final LuaString RETURN = valueOf("return"); + private static final LuaString TAILRETURN = valueOf("tail return"); + + private static final LuaString FUNC = valueOf("func"); + private static final LuaString NUPS = valueOf("nups"); + private static final LuaString NAME = valueOf("name"); + private static final LuaString NAMEWHAT = valueOf("namewhat"); + private static final LuaString WHAT = valueOf("what"); + private static final LuaString SOURCE = valueOf("source"); + private static final LuaString SHORT_SRC = valueOf("short_src"); + private static final LuaString LINEDEFINED = valueOf("linedefined"); + private static final LuaString LASTLINEDEFINED = valueOf("lastlinedefined"); + private static final LuaString CURRENTLINE = valueOf("currentline"); + private static final LuaString ACTIVELINES = valueOf("activelines"); + + public DebugLib() { + } + + private LuaTable init() { + DEBUG_ENABLED = true; + LuaTable t = new LuaTable(); + bind(t, DebugLib.class, NAMES, DEBUG); + env.set("debug", t); + PackageLib.instance.LOADED.set("debug", t); + return t; + } + + public Varargs invoke(Varargs args) { + switch ( opcode ) { + case INIT: return init(); + case DEBUG: return _debug(args); + case GETFENV: return _getfenv(args); + case GETHOOK: return _gethook(args); + case GETINFO: return _getinfo(args,this); + case GETLOCAL: return _getlocal(args); + case GETMETATABLE: return _getmetatable(args); + case GETREGISTRY: return _getregistry(args); + case GETUPVALUE: return _getupvalue(args); + case SETFENV: return _setfenv(args); + case SETHOOK: return _sethook(args); + case SETLOCAL: return _setlocal(args); + case SETMETATABLE: return _setmetatable(args); + case SETUPVALUE: return _setupvalue(args); + case TRACEBACK: return _traceback(args); + default: return NONE; + } + } + + // ------------------------ Debug Info management -------------------------- + // + // when DEBUG_ENABLED is set to true, these functions will be called + // by Closure instances as they process bytecodes. + // + // Each thread will get a DebugState attached to it by the debug library + // which will track function calls, hook functions, etc. + // + static class DebugInfo { + LuaValue func; + LuaClosure closure; + LuaValue[] stack; + Varargs varargs, extras; + int pc, top; + + private DebugInfo() { + func = NIL; + } + private DebugInfo(LuaValue func) { + pc = -1; + setfunction( func ); + } + void setargs(Varargs varargs, LuaValue[] stack) { + this.varargs = varargs; + this.stack = stack; + } + void setfunction( LuaValue func ) { + this.func = func; + this.closure = (func instanceof LuaClosure? (LuaClosure) func: null); + } + void clear() { + func = NIL; + closure = null; + stack = null; + varargs = extras = null; + pc = top = 0; + } + public void bytecode(int pc, Varargs extras, int top) { + this.pc = pc; + this.top = top; + this.extras = extras; + } + public int currentline() { + if ( closure == null ) return -1; + int[] li = closure.p.lineinfo; + return li==null || pc<0 || pc>=li.length? -1: li[pc]; + } + public LuaString[] getfunckind() { + if ( closure == null || pc<0 ) return null; + int stackpos = (closure.p.code[pc] >> 6) & 0xff; + return getobjname(this, stackpos); + } + public String sourceline() { + if ( closure == null ) return func.tojstring(); + String s = closure.p.source.tojstring(); + int line = currentline(); + return (s.startsWith("@")||s.startsWith("=")? s.substring(1): s) + ":" + line; + } + public String tracename() { + // if ( func != null ) + // return func.tojstring(); + LuaString[] kind = getfunckind(); + if ( kind == null ) + return "function ?"; + return "function "+kind[0].tojstring(); + } + public LuaString getlocalname(int index) { + if ( closure == null ) return null; + return closure.p.getlocalname(index, pc); + } + public String tojstring() { + return tracename()+" "+sourceline(); + } + } + + /** DebugState is associated with a Thread */ + static class DebugState { + private final WeakReference thread_ref; + private int debugCalls = 0; + private DebugInfo[] debugInfo = new DebugInfo[LuaThread.MAX_CALLSTACK+1]; + private LuaValue hookfunc; + private boolean hookcall,hookline,hookrtrn,inhook; + private int hookcount,hookcodes; + private int line; + DebugState(LuaThread thread) { + this.thread_ref = new WeakReference(thread); + } + public DebugInfo nextInfo() { + DebugInfo di = debugInfo[debugCalls]; + if ( di == null ) + debugInfo[debugCalls] = di = new DebugInfo(); + return di; + } + public DebugInfo pushInfo( int calls ) { + while ( debugCalls < calls ) { + nextInfo(); + ++debugCalls; + } + return debugInfo[debugCalls-1]; + } + public void popInfo(int calls) { + while ( debugCalls > calls ) + debugInfo[--debugCalls].clear(); + } + void callHookFunc(DebugState ds, LuaString type, LuaValue arg) { + if ( inhook || hookfunc == null ) + return; + inhook = true; + try { + int n = debugCalls; + ds.nextInfo().setargs( arg, null ); + ds.pushInfo(n+1).setfunction(hookfunc); + try { + hookfunc.call(type,arg); + } finally { + ds.popInfo(n); + } + } catch ( Exception e ) { + e.printStackTrace(); + } finally { + inhook = false; + } + } + public void sethook(LuaValue func, boolean call, boolean line, boolean rtrn, int count) { + this.hookcount = count; + this.hookcall = call; + this.hookline = line; + this.hookrtrn = rtrn; + this.hookfunc = func; + } + DebugInfo getDebugInfo() { + try { + return debugInfo[debugCalls-1]; + } catch ( Exception e ) { + if ( debugCalls <= 0 ) + return debugInfo[debugCalls++] = new DebugInfo(); + return null; + } + } + DebugInfo getDebugInfo(int level) { + return level < 0 || level >= debugCalls? null: debugInfo[debugCalls-level-1]; + } + public DebugInfo findDebugInfo(LuaValue func) { + for ( int i=debugCalls; --i>=0; ) { + if ( debugInfo[i].func == func ) { + return debugInfo[i]; + } + } + return new DebugInfo(func); + } + public String tojstring() { + LuaThread thread = (LuaThread) thread_ref.get(); + return thread != null? DebugLib.traceback(thread, 0): "orphaned thread"; + } + } + + static DebugState getDebugState( LuaThread thread ) { + if ( thread.debugState == null ) + thread.debugState = new DebugState(thread); + return (DebugState) thread.debugState; + } + + static DebugState getDebugState() { + return getDebugState( LuaThread.getRunning() ); + } + + /** Called by Closures to set up stack and arguments to next call */ + public static void debugSetupCall(Varargs args, LuaValue[] stack) { + DebugState ds = getDebugState(); + if ( ds.inhook ) + return; + ds.nextInfo().setargs( args, stack ); + } + + /** Called by Closures and recursing java functions on entry + * @param thread the thread for the call + * @param calls the number of calls in the call stack + * @param func the function called + */ + public static void debugOnCall(LuaThread thread, int calls, LuaFunction func) { + DebugState ds = getDebugState(); + if ( ds.inhook ) + return; + DebugInfo di = ds.pushInfo(calls); + di.setfunction( func ); + if(CALLS)System.out.println("calling "+func); + if ( ds.hookcall ) + ds.callHookFunc( ds, CALL, LuaValue.NIL ); + } + + /** Called by Closures and recursing java functions on return + * @param thread the thread for the call + * @param calls the number of calls in the call stack + */ + public static void debugOnReturn(LuaThread thread, int calls) { + DebugState ds = getDebugState(thread); + if ( ds.inhook ) + return; + if(CALLS)System.out.println("returning"); + try { + if ( ds.hookrtrn ) + ds.callHookFunc( ds, RETURN, LuaValue.NIL ); + } finally { + getDebugState().popInfo(calls); + } + } + + /** Called by Closures on bytecode execution */ + public static void debugBytecode( int pc, Varargs extras, int top ) { + DebugState ds = getDebugState(); + if ( ds.inhook ) + return; + DebugInfo di = ds.getDebugInfo(); + if(TRACE)Print.printState(di.closure, pc, di.stack, top, di.varargs); + di.bytecode( pc, extras, top ); + if ( ds.hookcount > 0 ) { + if ( ++ds.hookcodes >= ds.hookcount ) { + ds.hookcodes = 0; + ds.callHookFunc( ds, COUNT, LuaValue.NIL ); + } + } + if ( ds.hookline ) { + int newline = di.currentline(); + if ( newline != ds.line ) { + int c = di.closure.p.code[pc]; + if ( (c&0x3f) != Lua.OP_JMP || ((c>>>14)-0x1ffff) >= 0 ) { + ds.line = newline; + ds.callHookFunc( ds, LINE, LuaValue.valueOf(newline) ); + } + } + } + } + + // ------------------- library function implementations ----------------- + + // j2se subclass may wish to override and provide actual console here. + // j2me platform has not System.in to provide console. + static Varargs _debug(Varargs args) { + return NONE; + } + + static Varargs _gethook(Varargs args) { + int a=1; + LuaThread thread = args.isthread(a)? args.checkthread(a++): LuaThread.getRunning(); + DebugState ds = getDebugState(thread); + return varargsOf( + ds.hookfunc, + valueOf((ds.hookcall?"c":"")+(ds.hookline?"l":"")+(ds.hookrtrn?"r":"")), + valueOf(ds.hookcount)); + } + + static Varargs _sethook(Varargs args) { + int a=1; + LuaThread thread = args.isthread(a)? args.checkthread(a++): LuaThread.getRunning(); + LuaValue func = args.optfunction(a++, null); + String str = args.optjstring(a++,""); + int count = args.optint(a++,0); + boolean call=false,line=false,rtrn=false; + for ( int i=0; i0? + ds.getDebugInfo(level-1): + new DebugInfo( level0func ); + } else { + di = ds.findDebugInfo( func.checkfunction() ); + } + if ( di == null ) + return NIL; + + // start a table + LuaTable info = new LuaTable(); + LuaClosure c = di.closure; + for (int i = 0, j = what.length(); i < j; i++) { + switch (what.charAt(i)) { + case 'S': { + if ( c != null ) { + Prototype p = c.p; + info.set(WHAT, LUA); + info.set(SOURCE, p.source); + info.set(SHORT_SRC, valueOf(sourceshort(p))); + info.set(LINEDEFINED, valueOf(p.linedefined)); + info.set(LASTLINEDEFINED, valueOf(p.lastlinedefined)); + } else { + String shortName = di.func.tojstring(); + LuaString name = LuaString.valueOf("[Java] "+shortName); + info.set(WHAT, JAVA); + info.set(SOURCE, name); + info.set(SHORT_SRC, valueOf(shortName)); + info.set(LINEDEFINED, LuaValue.MINUSONE); + info.set(LASTLINEDEFINED, LuaValue.MINUSONE); + } + break; + } + case 'l': { + int line = di.currentline(); + info.set( CURRENTLINE, valueOf(line) ); + break; + } + case 'u': { + info.set(NUPS, valueOf(c!=null? c.p.nups: 0)); + break; + } + case 'n': { + LuaString[] kind = di.getfunckind(); + info.set(NAME, kind!=null? kind[0]: QMARK); + info.set(NAMEWHAT, kind!=null? kind[1]: EMPTYSTRING); + break; + } + case 'f': { + info.set( FUNC, di.func ); + break; + } + case 'L': { + LuaTable lines = new LuaTable(); + info.set(ACTIVELINES, lines); +// if ( di.luainfo != null ) { +// int line = di.luainfo.currentline(); +// if ( line >= 0 ) +// lines.set(1, IntValue.valueOf(line)); +// } + break; + } + } + } + return info; + } + + public static String sourceshort(Prototype p) { + String name = p.source.tojstring(); + if ( name.startsWith("@") || name.startsWith("=") ) + name = name.substring(1); + else if ( name.startsWith("\033") ) + name = "binary string"; + return name; + } + + static Varargs _getlocal(Varargs args) { + int a=1; + LuaThread thread = args.isthread(a)? args.checkthread(a++): LuaThread.getRunning(); + int level = args.checkint(a++); + int local = args.checkint(a++); + + DebugState ds = getDebugState(thread); + DebugInfo di = ds.getDebugInfo(level-1); + LuaString name = (di!=null? di.getlocalname(local): null); + if ( name != null ) { + LuaValue value = di.stack[local-1]; + return varargsOf( name, value ); + } else { + return NIL; + } + } + + static Varargs _setlocal(Varargs args) { + int a=1; + LuaThread thread = args.isthread(a)? args.checkthread(a++): LuaThread.getRunning(); + int level = args.checkint(a++); + int local = args.checkint(a++); + LuaValue value = args.arg(a++); + + DebugState ds = getDebugState(thread); + DebugInfo di = ds.getDebugInfo(level-1); + LuaString name = (di!=null? di.getlocalname(local): null); + if ( name != null ) { + di.stack[local-1] = value; + return name; + } else { + return NIL; + } + } + + static LuaValue _getmetatable(Varargs args) { + LuaValue object = args.arg(1); + LuaValue mt = object.getmetatable(); + return mt!=null? mt: NIL; + } + + static Varargs _setmetatable(Varargs args) { + LuaValue object = args.arg(1); + try { + LuaValue mt = args.opttable(2, null); + switch ( object.type() ) { + case TNIL: LuaNil.s_metatable = mt; break; + case TNUMBER: LuaNumber.s_metatable = mt; break; + case TBOOLEAN: LuaBoolean.s_metatable = mt; break; + case TSTRING: LuaString.s_metatable = mt; break; + case TFUNCTION: LuaFunction.s_metatable = mt; break; + case TTHREAD: LuaThread.s_metatable = mt; break; + default: object.setmetatable( mt ); + } + return LuaValue.TRUE; + } catch ( LuaError e ) { + return varargsOf(FALSE, valueOf(e.toString())); + } + } + + static Varargs _getregistry(Varargs args) { + return new LuaTable(); + } + + static LuaString findupvalue(LuaClosure c, int up) { + if ( c.upValues != null && up > 0 && up <= c.upValues.length ) { + if ( c.p.upvalues != null && up <= c.p.upvalues.length ) + return c.p.upvalues[up-1]; + else + return LuaString.valueOf( "."+up ); + } + return null; + } + + static Varargs _getupvalue(Varargs args) { + LuaValue func = args.checkfunction(1); + int up = args.checkint(2); + if ( func instanceof LuaClosure ) { + LuaClosure c = (LuaClosure) func; + LuaString name = findupvalue(c, up); + if ( name != null ) { + return varargsOf(name, c.upValues[up-1].getValue() ); + } + } + return NIL; + } + + static LuaValue _setupvalue(Varargs args) { + LuaValue func = args.checkfunction(1); + int up = args.checkint(2); + LuaValue value = args.arg(3); + if ( func instanceof LuaClosure ) { + LuaClosure c = (LuaClosure) func; + LuaString name = findupvalue(c, up); + if ( name != null ) { + c.upValues[up-1].setValue(value); + return name; + } + } + return NIL; + } + + static LuaValue _traceback(Varargs args) { + int a=1; + LuaThread thread = args.isthread(a)? args.checkthread(a++): LuaThread.getRunning(); + String message = args.optjstring(a++, null); + int level = args.optint(a++,1); + String tb = DebugLib.traceback(thread, level-1); + return valueOf(message!=null? message+"\n"+tb: tb); + } + + // =================== public utilities ==================== + + /** + * Get a traceback as a string for the current thread + */ + public static String traceback(int level) { + return traceback(LuaThread.getRunning(), level); + } + + /** + * Get a traceback for a particular thread. + * @param thread LuaThread to provide stack trace for + * @param level 0-based level to start reporting on + * @return String containing the stack trace. + */ + public static String traceback(LuaThread thread, int level) { + StringBuffer sb = new StringBuffer(); + DebugState ds = getDebugState(thread); + sb.append( "stack traceback:" ); + DebugInfo di = ds.getDebugInfo(level); + if ( di != null ) { + sb.append( "\n\t" ); + sb.append( di.sourceline() ); + sb.append( " in " ); + while ( (di = ds.getDebugInfo(++level)) != null ) { + sb.append( di.tracename() ); + sb.append( "\n\t" ); + sb.append( di.sourceline() ); + sb.append( " in " ); + } + sb.append( "main chunk" ); + } + return sb.toString(); + } + + + /** + * Get file and line for the nearest calling closure. + * @return String identifying the file and line of the nearest lua closure, + * or the function name of the Java call if no closure is being called. + */ + public static String fileline() { + DebugState ds = getDebugState(LuaThread.getRunning()); + DebugInfo di; + for ( int i=0, n=ds.debugCalls; i 0) { + /* cannot jump to a setlist count */ + int d = pt.code[dest - 1]; + if ((Lua.GET_OPCODE(d) == Lua.OP_SETLIST && Lua.GETARG_C(d) == 0)) return 0; + } + } + break; + } + } + if (Lua.testAMode(op)) { + if (a == reg) + last = pc; /* change register `a' */ + } + if (Lua.testTMode(op)) { + if (!(pc + 2 < pt.code.length)) return 0; /* check skip */ + if (!(Lua.GET_OPCODE(pt.code[pc + 1]) == Lua.OP_JMP)) return 0; + } + switch (op) { + case Lua.OP_LOADBOOL: { + if (!(c == 0 || pc + 2 < pt.code.length)) return 0; /* check its jump */ + break; + } + case Lua.OP_LOADNIL: { + if (a <= reg && reg <= b) + last = pc; /* set registers from `a' to `b' */ + break; + } + case Lua.OP_GETUPVAL: + case Lua.OP_SETUPVAL: { + if (!(b < pt.nups)) return 0; + break; + } + case Lua.OP_GETGLOBAL: + case Lua.OP_SETGLOBAL: { + if (!(pt.k[b].isstring())) return 0; + break; + } + case Lua.OP_SELF: { + if (!checkreg(pt, a + 1)) return 0; + if (reg == a + 1) + last = pc; + break; + } + case Lua.OP_CONCAT: { + if (!(b < c)) return 0; /* at least two operands */ + break; + } + case Lua.OP_TFORLOOP: { + if (!(c >= 1)) return 0; /* at least one result (control variable) */ + if (!checkreg(pt, a + 2 + c)) return 0; /* space for results */ + if (reg >= a + 2) + last = pc; /* affect all regs above its base */ + break; + } + case Lua.OP_FORLOOP: + case Lua.OP_FORPREP: + if (!checkreg(pt, a + 3)) return 0; + /* go through */ + case Lua.OP_JMP: { + int dest = pc + 1 + b; + /* not full check and jump is forward and do not skip `lastpc'? */ + if (reg != Lua.NO_REG && pc < dest && dest <= lastpc) + pc += b; /* do the jump */ + break; + } + case Lua.OP_CALL: + case Lua.OP_TAILCALL: { + if (b != 0) { + if (!checkreg(pt, a + b - 1)) return 0; + } + c--; /* c = num. returns */ + if (c == Lua.LUA_MULTRET) { + if (!(checkopenop(pt, pc))) return 0; + } else if (c != 0) + if (!checkreg(pt, a + c - 1)) return 0; + if (reg >= a) + last = pc; /* affect all registers above base */ + break; + } + case Lua.OP_RETURN: { + b--; /* b = num. returns */ + if (b > 0) + if (!checkreg(pt, a + b - 1)) return 0; + break; + } + case Lua.OP_SETLIST: { + if (b > 0) + if (!checkreg(pt, a + b)) return 0; + if (c == 0) + pc++; + break; + } + case Lua.OP_CLOSURE: { + int nup, j; + if (!(b < pt.p.length)) return 0; + nup = pt.p[b].nups; + if (!(pc + nup < pt.code.length)) return 0; + for (j = 1; j <= nup; j++) { + int op1 = Lua.GET_OPCODE(pt.code[pc + j]); + if (!(op1 == Lua.OP_GETUPVAL || op1 == Lua.OP_MOVE)) return 0; + } + if (reg != Lua.NO_REG) /* tracing? */ + pc += nup; /* do not 'execute' these pseudo-instructions */ + break; + } + case Lua.OP_VARARG: { + if (!((pt.is_vararg & Lua.VARARG_ISVARARG) != 0 + && (pt.is_vararg & Lua.VARARG_NEEDSARG) == 0)) return 0; + b--; + if (b == Lua.LUA_MULTRET) + if (!(checkopenop(pt, pc))) return 0; + if (!checkreg(pt, a + b - 1)) return 0; + break; + } + default: + break; + } + } + return pt.code[last]; + } + +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/lib/IoLib.java b/luaj-2.0.3/src/core/org/luaj/vm2/lib/IoLib.java new file mode 100644 index 0000000000..0afa7fe5f9 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/lib/IoLib.java @@ -0,0 +1,607 @@ +/******************************************************************************* +* Copyright (c) 2009-2011 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.lib; + +import java.io.ByteArrayOutputStream; +import java.io.EOFException; +import java.io.IOException; + +import org.luaj.vm2.LuaString; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; + +/** + * Abstract base class extending {@link LibFunction} which implements the + * core of the lua standard {@code io} library. + *

+ * It contains the implementation of the io library support that is common to + * the JSE and JME platforms. + * In practice on of the concrete IOLib subclasses is chosen: + * {@link org.luaj.vm2.lib.jse.JseIoLib} for the JSE platform, and + * {@link org.luaj.vm2.lib.jme.JmeIoLib} for the JME platform. + *

+ * The JSE implementation conforms almost completely to the C-based lua library, + * while the JME implementation follows closely except in the area of random-access files, + * which are difficult to support properly on JME. + *

+ * Typically, this library is included as part of a call to either + * {@link JsePlatform#standardGlobals()} or {@link JmePlatform#standardGlobals()} + *

+ * To instantiate and use it directly, + * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: + *

 {@code
+ * LuaTable _G = new LuaTable();
+ * _G.load(new JseIoLib());
+ * LuaThread.setGlobals(_G);
+ * _G.load(new JseBaseLib());
+ * _G.load(new PackageLib());
+ * _G.load(new JseIoLib());
+ * _G.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
+ * } 
+ * Doing so will ensure the library is properly initialized + * and loaded into the globals table. + *

+ * This has been implemented to match as closely as possible the behavior in the corresponding library in C. + * @see LibFunction + * @see JsePlatform + * @see JmePlatform + * @see JseIoLib + * @see JmeIoLib + * @see http://www.lua.org/manual/5.1/manual.html#5.7 + */ +abstract +public class IoLib extends OneArgFunction { + + abstract + protected class File extends LuaValue{ + abstract public void write( LuaString string ) throws IOException; + abstract public void flush() throws IOException; + abstract public boolean isstdfile(); + abstract public void close() throws IOException; + abstract public boolean isclosed(); + // returns new position + abstract public int seek(String option, int bytecount) throws IOException; + abstract public void setvbuf(String mode, int size); + // get length remaining to read + abstract public int remaining() throws IOException; + // peek ahead one character + abstract public int peek() throws IOException, EOFException; + // return char if read, -1 if eof, throw IOException on other exception + abstract public int read() throws IOException, EOFException; + // return number of bytes read if positive, false if eof, throw IOException on other exception + abstract public int read(byte[] bytes, int offset, int length) throws IOException; + + // delegate method access to file methods table + public LuaValue get( LuaValue key ) { + return filemethods.get(key); + } + + // essentially a userdata instance + public int type() { + return LuaValue.TUSERDATA; + } + public String typename() { + return "userdata"; + } + + // displays as "file" type + public String tojstring() { + return "file: " + Integer.toHexString(hashCode()); + } + } + + + /** + * Wrap the standard input. + * @return File + * @throws IOException + */ + abstract protected File wrapStdin() throws IOException; + + /** + * Wrap the standard output. + * @return File + * @throws IOException + */ + abstract protected File wrapStdout() throws IOException; + + /** + * Open a file in a particular mode. + * @param filename + * @param readMode true if opening in read mode + * @param appendMode true if opening in append mode + * @param updateMode true if opening in update mode + * @param binaryMode true if opening in binary mode + * @return File object if successful + * @throws IOException if could not be opened + */ + abstract protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException; + + /** + * Open a temporary file. + * @return File object if successful + * @throws IOException if could not be opened + */ + abstract protected File tmpFile() throws IOException; + + /** + * Start a new process and return a file for input or output + * @param prog the program to execute + * @param mode "r" to read, "w" to write + * @return File to read to or write from + * @throws IOException if an i/o exception occurs + */ + abstract protected File openProgram(String prog, String mode) throws IOException; + + private File infile = null; + private File outfile = null; + private File errfile = null; + + private static final LuaValue STDIN = valueOf("stdin"); + private static final LuaValue STDOUT = valueOf("stdout"); + private static final LuaValue STDERR = valueOf("stderr"); + private static final LuaValue FILE = valueOf("file"); + private static final LuaValue CLOSED_FILE = valueOf("closed file"); + + private static final int IO_CLOSE = 0; + private static final int IO_FLUSH = 1; + private static final int IO_INPUT = 2; + private static final int IO_LINES = 3; + private static final int IO_OPEN = 4; + private static final int IO_OUTPUT = 5; + private static final int IO_POPEN = 6; + private static final int IO_READ = 7; + private static final int IO_TMPFILE = 8; + private static final int IO_TYPE = 9; + private static final int IO_WRITE = 10; + + private static final int FILE_CLOSE = 11; + private static final int FILE_FLUSH = 12; + private static final int FILE_LINES = 13; + private static final int FILE_READ = 14; + private static final int FILE_SEEK = 15; + private static final int FILE_SETVBUF = 16; + private static final int FILE_WRITE = 17; + + private static final int IO_INDEX = 18; + private static final int LINES_ITER = 19; + + public static final String[] IO_NAMES = { + "close", + "flush", + "input", + "lines", + "open", + "output", + "popen", + "read", + "tmpfile", + "type", + "write", + }; + + public static final String[] FILE_NAMES = { + "close", + "flush", + "lines", + "read", + "seek", + "setvbuf", + "write", + }; + + LuaTable filemethods; + + public IoLib() { + } + + public LuaValue call(LuaValue arg) { + + // io lib functions + LuaTable t = new LuaTable(); + bind(t, IoLibV.class, IO_NAMES ); + + // create file methods table + filemethods = new LuaTable(); + bind(filemethods, IoLibV.class, FILE_NAMES, FILE_CLOSE ); + + // set up file metatable + LuaTable mt = new LuaTable(); + bind(mt, IoLibV.class, new String[] { "__index" }, IO_INDEX ); + t.setmetatable( mt ); + + // all functions link to library instance + setLibInstance( t ); + setLibInstance( filemethods ); + setLibInstance( mt ); + + // return the table + env.set("io", t); + PackageLib.instance.LOADED.set("io", t); + return t; + } + + private void setLibInstance(LuaTable t) { + LuaValue[] k = t.keys(); + for ( int i=0, n=k.length; i bool + public Varargs _io_flush() throws IOException { + checkopen(output()); + outfile.flush(); + return LuaValue.TRUE; + } + + // io.tmpfile() -> file + public Varargs _io_tmpfile() throws IOException { + return tmpFile(); + } + + // io.close([file]) -> void + public Varargs _io_close(LuaValue file) throws IOException { + File f = file.isnil()? output(): checkfile(file); + checkopen(f); + return ioclose(f); + } + + // io.input([file]) -> file + public Varargs _io_input(LuaValue file) { + infile = file.isnil()? input(): + file.isstring()? ioopenfile(file.checkjstring(),"r"): + checkfile(file); + return infile; + } + + // io.output(filename) -> file + public Varargs _io_output(LuaValue filename) { + outfile = filename.isnil()? output(): + filename.isstring()? ioopenfile(filename.checkjstring(),"w"): + checkfile(filename); + return outfile; + } + + // io.type(obj) -> "file" | "closed file" | nil + public Varargs _io_type(LuaValue obj) { + File f = optfile(obj); + return f!=null? + f.isclosed()? CLOSED_FILE: FILE: + NIL; + } + + // io.popen(prog, [mode]) -> file + public Varargs _io_popen(String prog, String mode) throws IOException { + return openProgram(prog, mode); + } + + // io.open(filename, [mode]) -> file | nil,err + public Varargs _io_open(String filename, String mode) throws IOException { + return rawopenfile(filename, mode); + } + + // io.lines(filename) -> iterator + public Varargs _io_lines(String filename) { + infile = filename==null? input(): ioopenfile(filename,"r"); + checkopen(infile); + return lines(infile); + } + + // io.read(...) -> (...) + public Varargs _io_read(Varargs args) throws IOException { + checkopen(input()); + return ioread(infile,args); + } + + // io.write(...) -> void + public Varargs _io_write(Varargs args) throws IOException { + checkopen(output()); + return iowrite(outfile,args); + } + + // file:close() -> void + public Varargs _file_close(LuaValue file) throws IOException { + return ioclose(checkfile(file)); + } + + // file:flush() -> void + public Varargs _file_flush(LuaValue file) throws IOException { + checkfile(file).flush(); + return LuaValue.TRUE; + } + + // file:setvbuf(mode,[size]) -> void + public Varargs _file_setvbuf(LuaValue file, String mode, int size) { + checkfile(file).setvbuf(mode,size); + return LuaValue.TRUE; + } + + // file:lines() -> iterator + public Varargs _file_lines(LuaValue file) { + return lines(checkfile(file)); + } + + // file:read(...) -> (...) + public Varargs _file_read(LuaValue file, Varargs subargs) throws IOException { + return ioread(checkfile(file),subargs); + } + + // file:seek([whence][,offset]) -> pos | nil,error + public Varargs _file_seek(LuaValue file, String whence, int offset) throws IOException { + return valueOf( checkfile(file).seek(whence,offset) ); + } + + // file:write(...) -> void + public Varargs _file_write(LuaValue file, Varargs subargs) throws IOException { + return iowrite(checkfile(file),subargs); + } + + // __index, returns a field + public Varargs _io_index(LuaValue v) { + return v.equals(STDOUT)?output(): + v.equals(STDIN)? input(): + v.equals(STDERR)? errput(): NIL; + } + + // lines iterator(s,var) -> var' + public Varargs _lines_iter(LuaValue file) throws IOException { + return freadline(checkfile(file)); + } + + private File output() { + return outfile!=null? outfile: (outfile=ioopenfile("-","w")); + } + + private File errput() { + return errfile!=null? errfile: (errfile=ioopenfile("-","w")); + } + + private File ioopenfile(String filename, String mode) { + try { + return rawopenfile(filename, mode); + } catch ( Exception e ) { + error("io error: "+e.getMessage()); + return null; + } + } + + private static Varargs ioclose(File f) throws IOException { + if ( f.isstdfile() ) + return errorresult("cannot close standard file"); + else { + f.close(); + return successresult(); + } + } + + private static Varargs successresult() { + return LuaValue.TRUE; + } + + private static Varargs errorresult(Exception ioe) { + String s = ioe.getMessage(); + return errorresult("io error: "+(s!=null? s: ioe.toString())); + } + + private static Varargs errorresult(String errortext) { + return varargsOf(NIL, valueOf(errortext)); + } + + private Varargs lines(final File f) { + try { + return new IoLibV(f,"lnext",LINES_ITER,this); + } catch ( Exception e ) { + return error("lines: "+e); + } + } + + private static Varargs iowrite(File f, Varargs args) throws IOException { + for ( int i=1, n=args.narg(); i<=n; i++ ) + f.write( args.checkstring(i) ); + return LuaValue.TRUE; + } + + private Varargs ioread(File f, Varargs args) throws IOException { + int i,n=args.narg(); + LuaValue[] v = new LuaValue[n]; + LuaValue ai,vi; + LuaString fmt; + for ( i=0; i 0; + boolean isbinary = mode.endsWith("b"); + return openFile( filename, isreadmode, isappend, isupdate, isbinary ); + } + + + // ------------- file reading utilitied ------------------ + + public static LuaValue freadbytes(File f, int count) throws IOException { + byte[] b = new byte[count]; + int r; + if ( ( r = f.read(b,0,b.length) ) < 0 ) + return NIL; + return LuaString.valueOf(b, 0, r); + } + public static LuaValue freaduntil(File f,boolean lineonly) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int c; + try { + if ( lineonly ) { + loop: while ( (c = f.read()) > 0 ) { + switch ( c ) { + case '\r': break; + case '\n': break loop; + default: baos.write(c); break; + } + } + } else { + while ( (c = f.read()) > 0 ) + baos.write(c); + } + } catch ( EOFException e ) { + c = -1; + } + return ( c < 0 && baos.size() == 0 )? + (LuaValue) NIL: + (LuaValue) LuaString.valueOf(baos.toByteArray()); + } + public static LuaValue freadline(File f) throws IOException { + return freaduntil(f,true); + } + public static LuaValue freadall(File f) throws IOException { + int n = f.remaining(); + if ( n >= 0 ) { + return freadbytes(f, n); + } else { + return freaduntil(f,false); + } + } + public static LuaValue freadnumber(File f) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + freadchars(f," \t\r\n",null); + freadchars(f,"-+",baos); + //freadchars(f,"0",baos); + //freadchars(f,"xX",baos); + freadchars(f,"0123456789",baos); + freadchars(f,".",baos); + freadchars(f,"0123456789",baos); + //freadchars(f,"eEfFgG",baos); + // freadchars(f,"+-",baos); + //freadchars(f,"0123456789",baos); + String s = baos.toString(); + return s.length()>0? valueOf( Double.parseDouble(s) ): NIL; + } + private static void freadchars(File f, String chars, ByteArrayOutputStream baos) throws IOException { + int c; + while ( true ) { + c = f.peek(); + if ( chars.indexOf(c) < 0 ) { + return; + } + f.read(); + if ( baos != null ) + baos.write( c ); + } + } + + + +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/lib/LibFunction.java b/luaj-2.0.3/src/core/org/luaj/vm2/lib/LibFunction.java new file mode 100644 index 0000000000..ac01611d78 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/lib/LibFunction.java @@ -0,0 +1,200 @@ +/******************************************************************************* +* Copyright (c) 2009-2011 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.lib; + +import org.luaj.vm2.LuaError; +import org.luaj.vm2.LuaFunction; +import org.luaj.vm2.LuaValue; + +/** + * Subclass of {@link LuaFunction} common to Java functions exposed to lua. + *

+ * To provide for common implementations in JME and JSE, + * library functions are typically grouped on one or more library classes + * and an opcode per library function is defined and used to key the switch + * to the correct function within the library. + *

+ * Since lua functions can be called with too few or too many arguments, + * and there are overloaded {@link LuaValue#call()} functions with varying + * number of arguments, a Java function exposed in lua needs to handle the + * argument fixup when a function is called with a number of arguments + * differs from that expected. + *

+ * To simplify the creation of library functions, + * there are 5 direct subclasses to handle common cases based on number of + * argument values and number of return return values. + *

    + *
  • {@link ZeroArgFunction}
  • + *
  • {@link OneArgFunction}
  • + *
  • {@link TwoArgFunction}
  • + *
  • {@link ThreeArgFunction}
  • + *
  • {@link VarArgFunction}
  • + *
+ *

+ * To be a Java library that can be loaded via {@code require}, it should have + * a public constructor that returns a {@link LuaValue} that, when executed, + * initializes the library. + *

+ * For example, the following code will implement a library called "hyperbolic" + * with two functions, "sinh", and "cosh": +

 {@code 
+ * import org.luaj.vm2.LuaValue;
+ * import org.luaj.vm2.lib.OneArgFunction;
+ * 
+ * public class hyperbolic extends OneArgFunction {
+ *
+ *	public hyperbolic() {}
+ *
+ *	public LuaValue call(LuaValue libname) {
+ *		LuaValue library = tableOf();
+ *		library.set( "sinh", new sinh() );
+ *		library.set( "cosh", new cosh() );
+ *		env.set( "hyperbolic", library );
+ *		return library;
+ *	}
+ *
+ *	static class sinh extends OneArgFunction {
+ *		public LuaValue call(LuaValue x) {
+ *			return LuaValue.valueOf(Math.sinh(x.checkdouble()));
+ *		}
+ *	}
+ *	
+ *	static class cosh extends OneArgFunction {
+ *		public LuaValue call(LuaValue x) {
+ *			return LuaValue.valueOf(Math.cosh(x.checkdouble()));
+ *		}
+ *	}
+ *}
+ *}
+ * The default constructor is used to instantiate the library + * in response to {@code require 'hyperbolic'} statement, + * provided it is on Javas class path. + * This instance is then invoked with the name supplied to require() + * as the only argument, and library should initialized whatever global + * data it needs to and place it into the environment if needed. + * In this case, it creates two function, 'sinh', and 'cosh', and puts + * them into a global table called 'hyperbolic.' + * It placed the library table into the globals via the {@link #env} + * local variable which corresponds to the globals that apply when the + * library is loaded. + *

+ * To test it, a script such as this can be used: + *

 {@code
+ * local t = require('hyperbolic')
+ * print( 't', t )
+ * print( 'hyperbolic', hyperbolic )
+ * for k,v in pairs(t) do
+ * 	print( 'k,v', k,v )
+ * end
+ * print( 'sinh(.5)', hyperbolic.sinh(.5) )
+ * print( 'cosh(.5)', hyperbolic.cosh(.5) )
+ * }
+ *

+ * It should produce something like: + *

 {@code
+ * t	table: 3dbbd23f
+ * hyperbolic	table: 3dbbd23f
+ * k,v	cosh	function: 3dbbd128
+ * k,v	sinh	function: 3dbbd242
+ * sinh(.5)	0.5210953
+ * cosh(.5)	1.127626
+ * }
+ *

+ * See the source code in any of the library functions + * such as {@link BaseLib} or {@link TableLib} for other examples. + */ +abstract public class LibFunction extends LuaFunction { + + /** User-defined opcode to differentiate between instances of the library function class. + *

+ * Subclass will typicall switch on this value to provide the specific behavior for each function. + */ + protected int opcode; + + /** The common name for this function, useful for debugging. + *

+ * Binding functions initialize this to the name to which it is bound. + */ + protected String name; + + /** Default constructor for use by subclasses */ + protected LibFunction() { + } + + public String tojstring() { + return name != null? name: super.tojstring(); + } + + /** + * Bind a set of library functions. + *

+ * An array of names is provided, and the first name is bound + * with opcode = 0, second with 1, etc. + * @param env The environment to apply to each bound function + * @param factory the Class to instantiate for each bound function + * @param names array of String names, one for each function. + * @see #bind(LuaValue, Class, String[], int) + */ + protected void bind(LuaValue env, Class factory, String[] names ) { + bind( env, factory, names, 0 ); + } + + /** + * Bind a set of library functions, with an offset + *

+ * An array of names is provided, and the first name is bound + * with opcode = {@code firstopcode}, second with {@code firstopcode+1}, etc. + * @param env The environment to apply to each bound function + * @param factory the Class to instantiate for each bound function + * @param names array of String names, one for each function. + * @param firstopcode the first opcode to use + * @see #bind(LuaValue, Class, String[]) + */ + protected void bind(LuaValue env, Class factory, String[] names, int firstopcode ) { + try { + for ( int i=0, n=names.length; i + * It contains only the math library support that is possible on JME. + * For a more complete implementation based on math functions specific to JSE + * use {@link org.luaj.vm2.lib.jse.JseMathLib}. + * In Particular the following math functions are not implemented by this library: + *

    + *
  • acos
  • + *
  • asin
  • + *
  • atan
  • + *
  • cosh
  • + *
  • log
  • + *
  • log10
  • + *
  • sinh
  • + *
  • tanh
  • + *
  • atan2
  • + *
+ *

+ * The implementations of {@code exp()} and {@code pow()} are constructed by + * hand for JME, so will be slower and less accurate than when executed on the JSE platform. + *

+ * Typically, this library is included as part of a call to either + * {@link JmePlatform#standardGlobals()} + *

+ * To instantiate and use it directly, + * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: + *

 {@code
+ * LuaTable _G = new LuaTable();
+ * LuaThread.setGlobals(_G);
+ * _G.load(new BaseLib());
+ * _G.load(new PackageLib());
+ * _G.load(new MathLib());
+ * System.out.println( _G.get("math").get("sqrt").call( LuaValue.valueOf(2) ) );
+ * } 
+ * Doing so will ensure the library is properly initialized + * and loaded into the globals table. + *

+ * This has been implemented to match as closely as possible the behavior in the corresponding library in C. + * @see LibFunction + * @see JsePlatform + * @see JmePlatform + * @see JseMathLib + * @see http://www.lua.org/manual/5.1/manual.html#5.6 + */ +public class MathLib extends OneArgFunction { + + public static MathLib MATHLIB = null; + + private Random random; + + public MathLib() { + MATHLIB = this; + } + + public LuaValue call(LuaValue arg) { + LuaTable t = new LuaTable(0,30); + t.set( "pi", Math.PI ); + t.set( "huge", LuaDouble.POSINF ); + bind( t, MathLib1.class, new String[] { + "abs", "ceil", "cos", "deg", + "exp", "floor", "rad", "sin", + "sqrt", "tan" } ); + bind( t, MathLib2.class, new String[] { + "fmod", "ldexp", "pow", } ); + bind( t, MathLibV.class, new String[] { + "frexp", "max", "min", "modf", + "randomseed", "random", } ); + ((MathLibV) t.get("randomseed")).mathlib = this; + ((MathLibV) t.get("random" )).mathlib = this; + env.set("math", t); + PackageLib.instance.LOADED.set("math", t); + return t; + } + + static final class MathLib1 extends OneArgFunction { + public LuaValue call(LuaValue arg) { + switch ( opcode ) { + case 0: return valueOf(Math.abs(arg.checkdouble())); + case 1: return valueOf(Math.ceil(arg.checkdouble())); + case 2: return valueOf(Math.cos(arg.checkdouble())); + case 3: return valueOf(Math.toDegrees(arg.checkdouble())); + case 4: return dpow(Math.E,arg.checkdouble()); + case 5: return valueOf(Math.floor(arg.checkdouble())); + case 6: return valueOf(Math.toRadians(arg.checkdouble())); + case 7: return valueOf(Math.sin(arg.checkdouble())); + case 8: return valueOf(Math.sqrt(arg.checkdouble())); + case 9: return valueOf(Math.tan(arg.checkdouble())); + } + return NIL; + } + } + + static final class MathLib2 extends TwoArgFunction { + protected MathLib mathlib; + public LuaValue call(LuaValue arg1, LuaValue arg2) { + switch ( opcode ) { + case 0: { // fmod + double x = arg1.checkdouble(); + double y = arg2.checkdouble(); + double q = x/y; + double f = x - y * (q>=0? Math.floor(q): Math.ceil(q)); + return valueOf( f ); + } + case 1: { // ldexp + double x = arg1.checkdouble(); + double y = arg2.checkdouble()+1023.5; + long e = (long) ((0!=(1&((int)y)))? Math.floor(y): Math.ceil(y-1)); + return valueOf(x * Double.longBitsToDouble(e << 52)); + } + case 2: { // pow + return dpow(arg1.checkdouble(), arg2.checkdouble()); + } + } + return NIL; + } + } + + /** compute power using installed math library, or default if there is no math library installed */ + public static LuaValue dpow(double a, double b) { + return LuaDouble.valueOf( + MATHLIB!=null? + MATHLIB.dpow_lib(a,b): + dpow_default(a,b) ); + } + public static double dpow_d(double a, double b) { + return MATHLIB!=null? + MATHLIB.dpow_lib(a,b): + dpow_default(a,b); + } + + /** + * Hook to override default dpow behavior with faster implementation. + */ + public double dpow_lib(double a, double b) { + return dpow_default(a,b); + } + + /** + * Default JME version computes using longhand heuristics. + */ + protected static double dpow_default(double a, double b) { + if ( b < 0 ) + return 1 / dpow_default( a, -b ); + double p = 1; + int whole = (int) b; + for ( double v=a; whole > 0; whole>>=1, v*=v ) + if ( (whole & 1) != 0 ) + p *= v; + if ( (b -= whole) > 0 ) { + int frac = (int) (0x10000 * b); + for ( ; (frac&0xffff)!=0; frac<<=1 ) { + a = Math.sqrt(a); + if ( (frac & 0x8000) != 0 ) + p *= a; + } + } + return p; + } + + static final class MathLibV extends VarArgFunction { + protected MathLib mathlib; + public Varargs invoke(Varargs args) { + switch ( opcode ) { + case 0: { // frexp + double x = args.checkdouble(1); + if ( x == 0 ) return varargsOf(ZERO,ZERO); + long bits = Double.doubleToLongBits( x ); + double m = ((bits & (~(-1L<<52))) + (1L<<52)) * ((bits >= 0)? (.5 / (1L<<52)): (-.5 / (1L<<52))); + double e = (((int) (bits >> 52)) & 0x7ff) - 1022; + return varargsOf( valueOf(m), valueOf(e) ); + } + case 1: { // max + double m = args.checkdouble(1); + for ( int i=2,n=args.narg(); i<=n; ++i ) + m = Math.max(m,args.checkdouble(i)); + return valueOf(m); + } + case 2: { // min + double m = args.checkdouble(1); + for ( int i=2,n=args.narg(); i<=n; ++i ) + m = Math.min(m,args.checkdouble(i)); + return valueOf(m); + } + case 3: { // modf + double x = args.checkdouble(1); + double intPart = ( x > 0 ) ? Math.floor( x ) : Math.ceil( x ); + double fracPart = x - intPart; + return varargsOf( valueOf(intPart), valueOf(fracPart) ); + } + case 4: { // randomseed + long seed = args.checklong(1); + mathlib.random = new Random(seed); + return NONE; + } + case 5: { // random + if ( mathlib.random == null ) + mathlib.random = new Random(); + + switch ( args.narg() ) { + case 0: + return valueOf( mathlib.random.nextDouble() ); + case 1: { + int m = args.checkint(1); + if (m<1) argerror(1, "interval is empty"); + return valueOf( 1 + mathlib.random.nextInt(m) ); + } + default: { + int m = args.checkint(1); + int n = args.checkint(2); + if (n + * Subclasses need only implement {@link LuaValue#call(LuaValue)} to complete this class, + * simplifying development. + * All other uses of {@link #call()}, {@link #invoke(Varargs)},etc, + * are routed through this method by this class, + * dropping or extending arguments with {@code nil} values as required. + *

+ * If more than one argument are required, or no arguments are required, + * or variable argument or variable return values, + * then use one of the related function + * {@link ZeroArgFunction}, {@link TwoArgFunction}, {@link ThreeArgFunction}, or {@link VarArgFunction}. + *

+ * See {@link LibFunction} for more information on implementation libraries and library functions. + * @see #call(LuaValue) + * @see LibFunction + * @see ZeroArgFunction + * @see TwoArgFunction + * @see ThreeArgFunction + * @see VarArgFunction + */ +abstract public class OneArgFunction extends LibFunction { + + abstract public LuaValue call(LuaValue arg); + + /** Default constructor */ + public OneArgFunction() { + } + + /** Constructor with specific environment + * @param env The environment to apply during constructon. + */ + public OneArgFunction( LuaValue env ) { + this.env = env; + } + + public final LuaValue call() { + return call(NIL); + } + + public final LuaValue call(LuaValue arg1, LuaValue arg2) { + return call(arg1); + } + + public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { + return call(arg1); + } + + public Varargs invoke(Varargs varargs) { + return call(varargs.arg1()); + } +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/lib/OsLib.java b/luaj-2.0.3/src/core/org/luaj/vm2/lib/OsLib.java new file mode 100644 index 0000000000..77c931542f --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/lib/OsLib.java @@ -0,0 +1,323 @@ +/******************************************************************************* +* Copyright (c) 2009 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.lib; + +import java.io.IOException; + +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; + +/** + * Subclass of {@link LibFunction} which implements the standard lua {@code os} library. + *

+ * It is a usable base with simplified stub functions + * for library functions that cannot be implemented uniformly + * on Jse and Jme. + *

+ * This can be installed as-is on either platform, or extended + * and refined to be used in a complete Jse implementation. + *

+ * Because the nature of the {@code os} library is to encapsulate + * os-specific features, the behavior of these functions varies considerably + * from their counterparts in the C platform. + *

+ * The following functions have limited implementations of features + * that are not supported well on Jme: + *

    + *
  • {@code execute()}
  • + *
  • {@code remove()}
  • + *
  • {@code rename()}
  • + *
  • {@code tmpname()}
  • + *
+ *

+ * Typically, this library is included as part of a call to either + * {@link JmePlatform#standardGlobals()} + *

+ * To instantiate and use it directly, + * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: + *

 {@code
+ * LuaTable _G = new LuaTable();
+ * LuaThread.setGlobals(_G);
+ * _G.load(new BaseLib());
+ * _G.load(new PackageLib());
+ * _G.load(new OsLib());
+ * System.out.println( _G.get("os").get("time").call() );
+ * } 
+ * Doing so will ensure the library is properly initialized + * and loaded into the globals table. + *

+ * @see LibFunction + * @see JseOsLib + * @see JsePlatform + * @see JmePlatform + * @see http://www.lua.org/manual/5.1/manual.html#5.8 + */ +public class OsLib extends VarArgFunction { + public static String TMP_PREFIX = ".luaj"; + public static String TMP_SUFFIX = "tmp"; + + private static final int INIT = 0; + private static final int CLOCK = 1; + private static final int DATE = 2; + private static final int DIFFTIME = 3; + private static final int EXECUTE = 4; + private static final int EXIT = 5; + private static final int GETENV = 6; + private static final int REMOVE = 7; + private static final int RENAME = 8; + private static final int SETLOCALE = 9; + private static final int TIME = 10; + private static final int TMPNAME = 11; + + private static final String[] NAMES = { + "clock", + "date", + "difftime", + "execute", + "exit", + "getenv", + "remove", + "rename", + "setlocale", + "time", + "tmpname", + }; + + private static final long t0 = System.currentTimeMillis(); + private static long tmpnames = t0; + + /** + * Create and OsLib instance. + */ + public OsLib() { + } + + public LuaValue init() { + LuaTable t = new LuaTable(); + bind(t, this.getClass(), NAMES, CLOCK); + env.set("os", t); + PackageLib.instance.LOADED.set("os", t); + return t; + } + + public Varargs invoke(Varargs args) { + try { + switch ( opcode ) { + case INIT: + return init(); + case CLOCK: + return valueOf(clock()); + case DATE: { + String s = args.optjstring(1, null); + double t = args.optdouble(2,-1); + return valueOf( date(s, t==-1? System.currentTimeMillis()/1000.: t) ); + } + case DIFFTIME: + return valueOf(difftime(args.checkdouble(1),args.checkdouble(2))); + case EXECUTE: + return valueOf(execute(args.optjstring(1, null))); + case EXIT: + exit(args.optint(1, 0)); + return NONE; + case GETENV: { + final String val = getenv(args.checkjstring(1)); + return val!=null? valueOf(val): NIL; + } + case REMOVE: + remove(args.checkjstring(1)); + return LuaValue.TRUE; + case RENAME: + rename(args.checkjstring(1), args.checkjstring(2)); + return LuaValue.TRUE; + case SETLOCALE: { + String s = setlocale(args.optjstring(1,null), args.optjstring(2, "all")); + return s!=null? valueOf(s): NIL; + } + case TIME: + return valueOf(time(args.arg1().isnil()? null: args.checktable(1))); + case TMPNAME: + return valueOf(tmpname()); + } + return NONE; + } catch ( IOException e ) { + return varargsOf(NIL, valueOf(e.getMessage())); + } + } + + /** + * @return an approximation of the amount in seconds of CPU time used by + * the program. + */ + protected double clock() { + return (System.currentTimeMillis()-t0) / 1000.; + } + + /** + * Returns the number of seconds from time t1 to time t2. + * In POSIX, Windows, and some other systems, this value is exactly t2-t1. + * @param t2 + * @param t1 + * @return diffeence in time values, in seconds + */ + protected double difftime(double t2, double t1) { + return t2 - t1; + } + + /** + * If the time argument is present, this is the time to be formatted + * (see the os.time function for a description of this value). + * Otherwise, date formats the current time. + * + * If format starts with '!', then the date is formatted in Coordinated + * Universal Time. After this optional character, if format is the string + * "*t", then date returns a table with the following fields: year + * (four digits), month (1--12), day (1--31), hour (0--23), min (0--59), + * sec (0--61), wday (weekday, Sunday is 1), yday (day of the year), + * and isdst (daylight saving flag, a boolean). + * + * If format is not "*t", then date returns the date as a string, + * formatted according to the same rules as the C function strftime. + * + * When called without arguments, date returns a reasonable date and + * time representation that depends on the host system and on the + * current locale (that is, os.date() is equivalent to os.date("%c")). + * + * @param format + * @param time time since epoch, or -1 if not supplied + * @return a LString or a LTable containing date and time, + * formatted according to the given string format. + */ + protected String date(String format, double time) { + return new java.util.Date((long)(time*1000)).toString(); + } + + /** + * This function is equivalent to the C function system. + * It passes command to be executed by an operating system shell. + * It returns a status code, which is system-dependent. + * If command is absent, then it returns nonzero if a shell + * is available and zero otherwise. + * @param command command to pass to the system + */ + protected int execute(String command) { + return 0; + } + + /** + * Calls the C function exit, with an optional code, to terminate the host program. + * @param code + */ + protected void exit(int code) { + /* DAN200 START */ + //System.exit(code); + /* DAN200 END */ + } + + /** + * Returns the value of the process environment variable varname, + * or null if the variable is not defined. + * @param varname + * @return String value, or null if not defined + */ + protected String getenv(String varname) { + return System.getProperty(varname); + } + + /** + * Deletes the file or directory with the given name. + * Directories must be empty to be removed. + * If this function fails, it throws and IOException + * + * @param filename + * @throws IOException if it fails + */ + protected void remove(String filename) throws IOException { + throw new IOException( "not implemented" ); + } + + /** + * Renames file or directory named oldname to newname. + * If this function fails,it throws and IOException + * + * @param oldname old file name + * @param newname new file name + * @throws IOException if it fails + */ + protected void rename(String oldname, String newname) throws IOException { + throw new IOException( "not implemented" ); + } + + /** + * Sets the current locale of the program. locale is a string specifying + * a locale; category is an optional string describing which category to change: + * "all", "collate", "ctype", "monetary", "numeric", or "time"; the default category + * is "all". + * + * If locale is the empty string, the current locale is set to an implementation- + * defined native locale. If locale is the string "C", the current locale is set + * to the standard C locale. + * + * When called with null as the first argument, this function only returns the + * name of the current locale for the given category. + * + * @param locale + * @param category + * @return the name of the new locale, or null if the request + * cannot be honored. + */ + protected String setlocale(String locale, String category) { + return "C"; + } + + /** + * Returns the current time when called without arguments, + * or a time representing the date and time specified by the given table. + * This table must have fields year, month, and day, + * and may have fields hour, min, sec, and isdst + * (for a description of these fields, see the os.date function). + * @param table + * @return long value for the time + */ + protected long time(LuaTable table) { + return System.currentTimeMillis(); + } + + /** + * Returns a string with a file name that can be used for a temporary file. + * The file must be explicitly opened before its use and explicitly removed + * when no longer needed. + * + * On some systems (POSIX), this function also creates a file with that name, + * to avoid security risks. (Someone else might create the file with wrong + * permissions in the time between getting the name and creating the file.) + * You still have to open the file to use it and to remove it (even if you + * do not use it). + * + * @return String filename to use + */ + protected String tmpname() { + synchronized ( OsLib.class ) { + return TMP_PREFIX+(tmpnames++)+TMP_SUFFIX; + } + } +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/lib/PackageLib.java b/luaj-2.0.3/src/core/org/luaj/vm2/lib/PackageLib.java new file mode 100644 index 0000000000..256c25195f --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/lib/PackageLib.java @@ -0,0 +1,466 @@ +/******************************************************************************* +* Copyright (c) 2010-2011 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.lib; + +import java.io.InputStream; +import java.io.PrintStream; + +import org.luaj.vm2.LuaFunction; +import org.luaj.vm2.LuaString; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaThread; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; + +/** + * Subclass of {@link LibFunction} which implements the lua standard package and module + * library functions. + * + *

+ * Typically, this library is included as part of a call to either + * {@link JsePlatform#standardGlobals()} or {@link JmePlatform#standardGlobals()} + *

+ * To instantiate and use it directly, + * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: + *

 {@code
+ * LuaTable _G = new LuaTable();
+ * LuaThread.setGlobals(_G);
+ * _G.load(new BaseLib());
+ * _G.load(new PackageLib());
+ * System.out.println( _G.get("require").call(LuaValue.valueOf("hyperbolic")) );
+ * } 
+ * In practice, the first 4 lines of the above are minimal requirements to get + * and initialize a globals table capable of basic reqire, print, and other functions, + * so it is much more convenient to use the {@link JsePlatform} and {@link JmePlatform} + * utility classes instead. + *

+ * This has been implemented to match as closely as possible the behavior in the corresponding library in C. + * However, the default filesystem search semantics are different and delegated to the bas library + * as outlined in the {@link BaseLib} and {@link JseBaseLib} documetnation. + * @see LibFunction + * @see BaseLib + * @see JseBaseLib + * @see JsePlatform + * @see JmePlatform + * @see http://www.lua.org/manual/5.1/manual.html#5.3 + */ +public class PackageLib extends OneArgFunction { + + public static String DEFAULT_LUA_PATH = "?.lua"; + + public InputStream STDIN = null; + public PrintStream STDOUT = System.out; + public LuaTable LOADED; + public LuaTable PACKAGE; + + /** Most recent instance of PackageLib */ + public static PackageLib instance; + + /** Loader that loads from preload table if found there */ + public LuaValue preload_loader; + + /** Loader that loads as a lua script using the LUA_PATH */ + public LuaValue lua_loader; + + /** Loader that loads as a Java class. Class must have public constructor and be a LuaValue */ + public LuaValue java_loader; + + private static final LuaString _M = valueOf("_M"); + private static final LuaString _NAME = valueOf("_NAME"); + private static final LuaString _PACKAGE = valueOf("_PACKAGE"); + private static final LuaString _DOT = valueOf("."); + private static final LuaString _LOADERS = valueOf("loaders"); + private static final LuaString _LOADED = valueOf("loaded"); + private static final LuaString _LOADLIB = valueOf("loadlib"); + private static final LuaString _PRELOAD = valueOf("preload"); + private static final LuaString _PATH = valueOf("path"); + private static final LuaString _SEEALL = valueOf("seeall"); + private static final LuaString _SENTINEL = valueOf("\u0001"); + + private static final int OP_MODULE = 0; + private static final int OP_REQUIRE = 1; + private static final int OP_LOADLIB = 2; + private static final int OP_SEEALL = 3; + private static final int OP_PRELOAD_LOADER = 4; + private static final int OP_LUA_LOADER = 5; + private static final int OP_JAVA_LOADER = 6; + + public PackageLib() { + instance = this; + } + + public LuaValue call(LuaValue arg) { + env.set("require", new PkgLib1(env,"require",OP_REQUIRE,this)); + env.set("module", new PkgLibV(env,"module",OP_MODULE,this)); + env.set( "package", PACKAGE=tableOf( new LuaValue[] { + _LOADED, LOADED=tableOf(), + _PRELOAD, tableOf(), + _PATH, valueOf(DEFAULT_LUA_PATH), + _LOADLIB, new PkgLibV(env,"loadlib",OP_LOADLIB,this), + _SEEALL, new PkgLib1(env,"seeall",OP_SEEALL,this), + _LOADERS, listOf(new LuaValue[] { + preload_loader = new PkgLibV(env,"preload_loader", OP_PRELOAD_LOADER,this), + lua_loader = new PkgLibV(env,"lua_loader", OP_LUA_LOADER,this), + java_loader = new PkgLibV(env,"java_loader", OP_JAVA_LOADER,this), + }) }) ); + LOADED.set("package", PACKAGE); + return env; + } + + static final class PkgLib1 extends OneArgFunction { + PackageLib lib; + public PkgLib1(LuaValue env,String name, int opcode, PackageLib lib) { + this.env = env; + this.name = name; + this.opcode = opcode; + this.lib = lib; + } + public LuaValue call(LuaValue arg) { + switch ( opcode ) { + case OP_REQUIRE: + return lib.require(arg); + case OP_SEEALL: { + LuaTable t = arg.checktable(); + LuaValue m = t.getmetatable(); + if ( m == null ) + t.setmetatable(m=tableOf()); + m.set( INDEX, LuaThread.getGlobals() ); + return NONE; + } + } + return NIL; + } + } + + static final class PkgLibV extends VarArgFunction { + PackageLib lib; + public PkgLibV(LuaValue env,String name, int opcode, PackageLib lib) { + this.env = env; + this.name = name; + this.opcode = opcode; + this.lib = lib; + } + public Varargs invoke(Varargs args) { + switch ( opcode ) { + case OP_MODULE: + return lib.module(args); + case OP_LOADLIB: + return loadlib(args); + case OP_PRELOAD_LOADER: { + return lib.loader_preload(args); + } + case OP_LUA_LOADER: { + return lib.loader_Lua(args); + } + case OP_JAVA_LOADER: { + return lib.loader_Java(args); + } + } + return NONE; + } + } + + /** Allow packages to mark themselves as loaded */ + public void setIsLoaded(String name, LuaTable value) { + LOADED.set(name, value); + } + + public void setLuaPath( String newLuaPath ) { + PACKAGE.set( _PATH, valueOf(newLuaPath) ); + } + + public String tojstring() { + return "package"; + } + + + // ======================== Module, Package loading ============================= + /** + * module (name [, ...]) + * + * Creates a module. If there is a table in package.loaded[name], this table + * is the module. Otherwise, if there is a global table t with the given + * name, this table is the module. Otherwise creates a new table t and sets + * it as the value of the global name and the value of package.loaded[name]. + * This function also initializes t._NAME with the given name, t._M with the + * module (t itself), and t._PACKAGE with the package name (the full module + * name minus last component; see below). Finally, module sets t as the new + * environment of the current function and the new value of + * package.loaded[name], so that require returns t. + * + * If name is a compound name (that is, one with components separated by + * dots), module creates (or reuses, if they already exist) tables for each + * component. For instance, if name is a.b.c, then module stores the module + * table in field c of field b of global a. + * + * This function may receive optional options after the module name, where + * each option is a function to be applied over the module. + */ + public Varargs module(Varargs args) { + LuaString modname = args.checkstring(1); + int n = args.narg(); + LuaValue value = LOADED.get(modname); + LuaValue module; + if ( ! value.istable() ) { /* not found? */ + + /* try global variable (and create one if it does not exist) */ + LuaValue globals = LuaThread.getGlobals(); + module = findtable( globals, modname ); + if ( module == null ) + error( "name conflict for module '"+modname+"'" ); + LOADED.set(modname, module); + } else { + module = (LuaTable) value; + } + + + /* check whether table already has a _NAME field */ + LuaValue name = module.get(_NAME); + if ( name.isnil() ) { + modinit( module, modname ); + } + + // set the environment of the current function + LuaFunction f = LuaThread.getCallstackFunction(1); + if ( f == null ) + error("no calling function"); + if ( ! f.isclosure() ) + error("'module' not called from a Lua function"); + f.setfenv(module); + + // apply the functions + for ( int i=2; i<=n; i++ ) + args.arg(i).call( module ); + + // returns no results + return NONE; + } + + /** + * + * @param table the table at which to start the search + * @param fname the name to look up or create, such as "abc.def.ghi" + * @return the table for that name, possible a new one, or null if a non-table has that name already. + */ + private static final LuaValue findtable(LuaValue table, LuaString fname) { + int b, e=(-1); + do { + e = fname.indexOf(_DOT, b=e+1 ); + if ( e < 0 ) + e = fname.m_length; + LuaString key = fname.substring(b, e); + LuaValue val = table.rawget(key); + if ( val.isnil() ) { /* no such field? */ + LuaTable field = new LuaTable(); /* new table for field */ + table.set(key, field); + table = field; + } else if ( ! val.istable() ) { /* field has a non-table value? */ + return null; + } else { + table = val; + } + } while ( e < fname.m_length ); + return table; + } + + private static final void modinit(LuaValue module, LuaString modname) { + /* module._M = module */ + module.set(_M, module); + int e = modname.lastIndexOf(_DOT); + module.set(_NAME, modname ); + module.set(_PACKAGE, (e<0? EMPTYSTRING: modname.substring(0,e+1)) ); + } + + /** + * require (modname) + * + * Loads the given module. The function starts by looking into the package.loaded table to + * determine whether modname is already loaded. If it is, then require returns the value + * stored at package.loaded[modname]. Otherwise, it tries to find a loader for the module. + * + * To find a loader, require is guided by the package.loaders array. By changing this array, + * we can change how require looks for a module. The following explanation is based on the + * default configuration for package.loaders. + * + * First require queries package.preload[modname]. If it has a value, this value + * (which should be a function) is the loader. Otherwise require searches for a Lua loader + * using the path stored in package.path. If that also fails, it searches for a C loader + * using the path stored in package.cpath. If that also fails, it tries an all-in-one loader + * (see package.loaders). + * + * Once a loader is found, require calls the loader with a single argument, modname. + * If the loader returns any value, require assigns the returned value to package.loaded[modname]. + * If the loader returns no value and has not assigned any value to package.loaded[modname], + * then require assigns true to this entry. In any case, require returns the final value of + * package.loaded[modname]. + * + * If there is any error loading or running the module, or if it cannot find any loader for + * the module, then require signals an error. + */ + public LuaValue require( LuaValue arg ) { + LuaString name = arg.checkstring(); + LuaValue loaded = LOADED.get(name); + if ( loaded.toboolean() ) { + if ( loaded == _SENTINEL ) + error("loop or previous error loading module '"+name+"'"); + return loaded; + } + + /* else must load it; iterate over available loaders */ + LuaTable tbl = PACKAGE.get(_LOADERS).checktable(); + StringBuffer sb = new StringBuffer(); + LuaValue chunk = null; + for ( int i=1; true; i++ ) { + LuaValue loader = tbl.get(i); + if ( loader.isnil() ) { + error( "module '"+name+"' not found: "+name+sb ); + } + + /* call loader with module name as argument */ + chunk = loader.call(name); + if ( chunk.isfunction() ) + break; + if ( chunk.isstring() ) + sb.append( chunk.tojstring() ); + } + + // load the module using the loader + LOADED.set(name, _SENTINEL); + LuaValue result = chunk.call(name); + if ( ! result.isnil() ) + LOADED.set( name, result ); + else if ( (result = LOADED.get(name)) == _SENTINEL ) + LOADED.set( name, result = LuaValue.TRUE ); + return result; + } + + public static Varargs loadlib( Varargs args ) { + args.checkstring(1); + return varargsOf(NIL, valueOf("dynamic libraries not enabled"), valueOf("absent")); + } + + LuaValue loader_preload( Varargs args ) { + LuaString name = args.checkstring(1); + LuaValue preload = PACKAGE.get(_PRELOAD).checktable(); + LuaValue val = preload.get(name); + return val.isnil()? + valueOf("\n\tno field package.preload['"+name+"']"): + val; + } + + LuaValue loader_Lua( Varargs args ) { + String name = args.checkjstring(1); + InputStream is = null; + + + // get package path + LuaValue pp = PACKAGE.get(_PATH); + if ( ! pp.isstring() ) + return valueOf("package.path is not a string"); + String path = pp.tojstring(); + + // check the path elements + int e = -1; + int n = path.length(); + StringBuffer sb = null; + name = name.replace('.','/'); + while ( e < n ) { + + // find next template + int b = e+1; + e = path.indexOf(';',b); + if ( e < 0 ) + e = path.length(); + String template = path.substring(b,e); + + // create filename + int q = template.indexOf('?'); + String filename = template; + if ( q >= 0 ) { + filename = template.substring(0,q) + name + template.substring(q+1); + } + + // try loading the file + Varargs v = BaseLib.loadFile(filename); + if ( v.arg1().isfunction() ) + return v.arg1(); + + // report error + if ( sb == null ) + sb = new StringBuffer(); + sb.append( "\n\t'"+filename+"': "+v.arg(2) ); + } + return valueOf(sb.toString()); + } + + LuaValue loader_Java( Varargs args ) { + String name = args.checkjstring(1); + String classname = toClassname( name ); + Class c = null; + LuaValue v = null; + try { + c = Class.forName(classname); + v = (LuaValue) c.newInstance(); + v.setfenv(env); + return v; + } catch ( ClassNotFoundException cnfe ) { + return valueOf("\n\tno class '"+classname+"'" ); + } catch ( Exception e ) { + return valueOf("\n\tjava load failed on '"+classname+"', "+e ); + } + } + + /** Convert lua filename to valid class name */ + public static final String toClassname( String filename ) { + int n=filename.length(); + int j=n; + if ( filename.endsWith(".lua") ) + j -= 4; + for ( int k=0; k='a'&&c<='z') || (c>='A'&&c<='Z') || (c>='0'&&c<='9') ) + return true; + switch ( c ) { + case '.': + case '$': + case '_': + return true; + default: + return false; + } + } +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/lib/ResourceFinder.java b/luaj-2.0.3/src/core/org/luaj/vm2/lib/ResourceFinder.java new file mode 100644 index 0000000000..218fa8e455 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/lib/ResourceFinder.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2009-2011 Luaj.org. 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. + ******************************************************************************/ +package org.luaj.vm2.lib; + +import java.io.InputStream; + +/** + * Interface for opening application resource files such as scripts sources. + *

+ * This is used by required to load files that are part of + * the application, and implemented by BaseLib + * for both the Jme and Jse platforms. + *

+ * The Jme version of base lib {@link BaseLib} + * implements {@link BaseLib#FINDER} via {@link Class#getResourceAsStream(String)}, + * while the Jse version {@link JseBaseLib} implements it using {@link java.io.File#File(String)}. + *

+ * The io library does not use this API for file manipulation. + *

+ * @see BaseLib + * @see BaseLib#FINDER + * @see JseBaseLib + * @see JmePlatform + * @see JsePlatform + */ +public interface ResourceFinder { + + /** + * Try to open a file, or return null if not found. + * + * @see org.luaj.vm2.lib.BaseLib + * @see org.luaj.vm2.lib.jse.JseBaseLib + * + * @param filename + * @return InputStream, or null if not found. + */ + public InputStream findResource( String filename ); +} \ No newline at end of file diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/lib/StringLib.java b/luaj-2.0.3/src/core/org/luaj/vm2/lib/StringLib.java new file mode 100644 index 0000000000..d7bc7cd902 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/lib/StringLib.java @@ -0,0 +1,1190 @@ +/******************************************************************************* +* Copyright (c) 2009-2011 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.lib; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import org.luaj.vm2.LuaClosure; +import org.luaj.vm2.Buffer; +import org.luaj.vm2.LuaString; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; +import org.luaj.vm2.compiler.DumpState; + +/** + * Subclass of {@link LibFunction} which implements the lua standard {@code string} + * library. + * + *

+ * Typically, this library is included as part of a call to either + * {@link JsePlatform#standardGlobals()} or {@link JmePlatform#standardGlobals()} + *

+ * To instantiate and use it directly, + * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: + *

 {@code
+ * LuaTable _G = new LuaTable();
+ * LuaThread.setGlobals(_G);
+ * _G.load(new BaseLib());
+ * _G.load(new PackageLib());
+ * _G.load(new StringLib());
+ * System.out.println( _G.get("string").get("upper").call( LuaValue.valueOf("abcde") ) );
+ * } 
+ * Doing so will ensure the library is properly initialized + * and loaded into the globals table. + *

+ * This is a direct port of the corresponding library in C. + * @see LibFunction + * @see JsePlatform + * @see JmePlatform + * @see http://www.lua.org/manual/5.1/manual.html#5.4 + */ +public class StringLib extends OneArgFunction { + + public static LuaTable instance; + + public StringLib() { + } + + public LuaValue call(LuaValue arg) { + LuaTable t = new LuaTable(); + bind(t, StringLib1.class, new String[] { + "dump", "len", "lower", "reverse", "upper", } ); + bind(t, StringLibV.class, new String[] { + "byte", "char", "find", "format", + "gmatch", "gsub", "match", "rep", + "sub"} ); + env.set("string", t); + instance = t; + if ( LuaString.s_metatable == null ) + LuaString.s_metatable = tableOf( new LuaValue[] { INDEX, t } ); + PackageLib.instance.LOADED.set("string", t); + return t; + } + + static final class StringLib1 extends OneArgFunction { + public LuaValue call(LuaValue arg) { + switch ( opcode ) { + case 0: return dump(arg); // dump (function) + case 1: return StringLib.len(arg); // len (function) + case 2: return lower(arg); // lower (function) + case 3: return reverse(arg); // reverse (function) + case 4: return upper(arg); // upper (function) + } + return NIL; + } + } + + static final class StringLibV extends VarArgFunction { + public Varargs invoke(Varargs args) { + switch ( opcode ) { + case 0: return StringLib.byte_( args ); + case 1: return StringLib.char_( args ); + case 2: return StringLib.find( args ); + case 3: return StringLib.format( args ); + case 4: return StringLib.gmatch( args ); + case 5: return StringLib.gsub( args ); + case 6: return StringLib.match( args ); + case 7: return StringLib.rep( args ); + case 8: return StringLib.sub( args ); + } + return NONE; + } + } + + /** + * string.byte (s [, i [, j]]) + * + * Returns the internal numerical codes of the + * characters s[i], s[i+1], ..., s[j]. The default value for i is 1; the + * default value for j is i. + * + * Note that numerical codes are not necessarily portable across platforms. + * + * @param args the calling args + */ + static Varargs byte_( Varargs args ) { + LuaString s = args.checkstring(1); + int l = s.m_length; + int posi = posrelat( args.optint(2,1), l ); + int pose = posrelat( args.optint(3,posi), l ); + int n,i; + if (posi <= 0) posi = 1; + if (pose > l) pose = l; + if (posi > pose) return NONE; /* empty interval; return no values */ + n = (int)(pose - posi + 1); + if (posi + n <= pose) /* overflow? */ + error("string slice too long"); + LuaValue[] v = new LuaValue[n]; + for (i=0; i=256) argerror(a, "invalid value"); + bytes[i] = (byte) c; + } + return LuaString.valueOf( bytes ); + } + + /** + * string.dump (function) + * + * Returns a string containing a binary representation of the given function, + * so that a later loadstring on this string returns a copy of the function. + * function must be a Lua function without upvalues. + * + * TODO: port dumping code as optional add-on + */ + static LuaValue dump( LuaValue arg ) { + LuaValue f = arg.checkfunction(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + DumpState.dump( ((LuaClosure)f).p, baos, true ); + return LuaString.valueOf(baos.toByteArray()); + } catch (IOException e) { + return error( e.getMessage() ); + } + } + + /** + * string.find (s, pattern [, init [, plain]]) + * + * Looks for the first match of pattern in the string s. + * If it finds a match, then find returns the indices of s + * where this occurrence starts and ends; otherwise, it returns nil. + * A third, optional numerical argument init specifies where to start the search; + * its default value is 1 and may be negative. A value of true as a fourth, + * optional argument plain turns off the pattern matching facilities, + * so the function does a plain "find substring" operation, + * with no characters in pattern being considered "magic". + * Note that if plain is given, then init must be given as well. + * + * If the pattern has captures, then in a successful match the captured values + * are also returned, after the two indices. + */ + static Varargs find( Varargs args ) { + return str_find_aux( args, true ); + } + + /** + * string.format (formatstring, ...) + * + * Returns a formatted version of its variable number of arguments following + * the description given in its first argument (which must be a string). + * The format string follows the same rules as the printf family of standard C functions. + * The only differences are that the options/modifiers *, l, L, n, p, and h are not supported + * and that there is an extra option, q. The q option formats a string in a form suitable + * to be safely read back by the Lua interpreter: the string is written between double quotes, + * and all double quotes, newlines, embedded zeros, and backslashes in the string are correctly + * escaped when written. For instance, the call + * string.format('%q', 'a string with "quotes" and \n new line') + * + * will produce the string: + * "a string with \"quotes\" and \ + * new line" + * + * The options c, d, E, e, f, g, G, i, o, u, X, and x all expect a number as argument, + * whereas q and s expect a string. + * + * This function does not accept string values containing embedded zeros, + * except as arguments to the q option. + */ + static Varargs format( Varargs args ) { + LuaString fmt = args.checkstring( 1 ); + final int n = fmt.length(); + Buffer result = new Buffer(n); + int arg = 1; + int c; + + for ( int i = 0; i < n; ) { + switch ( c = fmt.luaByte( i++ ) ) { + case '\n': + result.append( "\n" ); + break; + default: + result.append( (byte) c ); + break; + case L_ESC: + if ( i < n ) { + if ( ( c = fmt.luaByte( i ) ) == L_ESC ) { + ++i; + result.append( (byte)L_ESC ); + } else { + arg++; + FormatDesc fdsc = new FormatDesc(args, fmt, i ); + i += fdsc.length; + switch ( fdsc.conversion ) { + case 'c': + fdsc.format( result, (byte)args.checkint( arg ) ); + break; + case 'i': + case 'd': + fdsc.format( result, args.checkint( arg ) ); + break; + case 'o': + case 'u': + case 'x': + case 'X': + fdsc.format( result, args.checklong( arg ) ); + break; + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + fdsc.format( result, args.checkdouble( arg ) ); + break; + case 'q': + addquoted( result, args.checkstring( arg ) ); + break; + case 's': { + LuaString s = args.checkstring( arg ); + if ( fdsc.precision == -1 && s.length() >= 100 ) { + result.append( s ); + } else { + fdsc.format( result, s ); + } + } break; + default: + error("invalid option '%"+(char)fdsc.conversion+"' to 'format'"); + break; + } + } + } + } + } + + return result.tostring(); + } + + private static void addquoted(Buffer buf, LuaString s) { + int c; + buf.append( (byte) '"' ); + for ( int i = 0, n = s.length(); i < n; i++ ) { + switch ( c = s.luaByte( i ) ) { + case '"': case '\\': case '\n': + buf.append( (byte)'\\' ); + buf.append( (byte)c ); + break; + case '\r': + buf.append( "\\r" ); + break; + case '\0': + buf.append( "\\000" ); + break; + default: + /* DAN200 START */ + //buf.append( (byte) c ); + if( (c >= 32 && c <= 126) || (c >= 160 && c <= 255) ) { + buf.append( (byte)c ); + } else { + String str = Integer.toString(c); + while( str.length() < 3 ) { + str = "0" + str; + } + buf.append( "\\" + str ); + } + /* DAN200 END */ + break; + } + } + buf.append( (byte) '"' ); + } + + private static final String FLAGS = "-+ #0"; + + static class FormatDesc { + + private boolean leftAdjust; + private boolean zeroPad; + private boolean explicitPlus; + private boolean space; + private boolean alternateForm; + private static final int MAX_FLAGS = 5; + + private int width; + private int precision; + + public final int conversion; + public final int length; + + public FormatDesc(Varargs args, LuaString strfrmt, final int start) { + int p = start, n = strfrmt.length(); + int c = 0; + + boolean moreFlags = true; + while ( moreFlags ) { + switch ( c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 ) ) { + case '-': leftAdjust = true; break; + case '+': explicitPlus = true; break; + case ' ': space = true; break; + case '#': alternateForm = true; break; + case '0': zeroPad = true; break; + default: moreFlags = false; break; + } + } + if ( p - start > MAX_FLAGS ) + error("invalid format (repeated flags)"); + + width = -1; + if ( Character.isDigit( (char)c ) ) { + width = c - '0'; + c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 ); + if ( Character.isDigit( (char) c ) ) { + width = width * 10 + (c - '0'); + c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 ); + } + } + + precision = -1; + if ( c == '.' ) { + c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 ); + if ( Character.isDigit( (char) c ) ) { + precision = c - '0'; + c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 ); + if ( Character.isDigit( (char) c ) ) { + precision = precision * 10 + (c - '0'); + c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 ); + } + } + } + + if ( Character.isDigit( (char) c ) ) + error("invalid format (width or precision too long)"); + + zeroPad &= !leftAdjust; // '-' overrides '0' + conversion = c; + length = p - start; + } + + public void format(Buffer buf, byte c) { + // TODO: not clear that any of width, precision, or flags apply here. + buf.append(c); + } + + public void format(Buffer buf, long number) { + String digits; + + if ( number == 0 && precision == 0 ) { + digits = ""; + } else { + int radix; + switch ( conversion ) { + case 'x': + case 'X': + radix = 16; + break; + case 'o': + radix = 8; + break; + default: + radix = 10; + break; + } + digits = Long.toString( number, radix ); + if ( conversion == 'X' ) + digits = digits.toUpperCase(); + } + + int minwidth = digits.length(); + int ndigits = minwidth; + int nzeros; + + if ( number < 0 ) { + ndigits--; + } else if ( explicitPlus || space ) { + minwidth++; + } + + if ( precision > ndigits ) + nzeros = precision - ndigits; + else if ( precision == -1 && zeroPad && width > minwidth ) + nzeros = width - minwidth; + else + nzeros = 0; + + minwidth += nzeros; + int nspaces = width > minwidth ? width - minwidth : 0; + + if ( !leftAdjust ) + pad( buf, ' ', nspaces ); + + if ( number < 0 ) { + if ( nzeros > 0 ) { + buf.append( (byte)'-' ); + digits = digits.substring( 1 ); + } + } else if ( explicitPlus ) { + buf.append( (byte)'+' ); + } else if ( space ) { + buf.append( (byte)' ' ); + } + + if ( nzeros > 0 ) + pad( buf, '0', nzeros ); + + buf.append( digits ); + + if ( leftAdjust ) + pad( buf, ' ', nspaces ); + } + + public void format(Buffer buf, double x) { + // TODO + buf.append( String.valueOf( x ) ); + } + + public void format(Buffer buf, LuaString s) { + int nullindex = s.indexOf( (byte)'\0', 0 ); + if ( nullindex != -1 ) + s = s.substring( 0, nullindex ); + buf.append(s); + } + + public static final void pad(Buffer buf, char c, int n) { + byte b = (byte)c; + while ( n-- > 0 ) + buf.append(b); + } + } + + /** + * string.gmatch (s, pattern) + * + * Returns an iterator function that, each time it is called, returns the next captures + * from pattern over string s. If pattern specifies no captures, then the + * whole match is produced in each call. + * + * As an example, the following loop + * s = "hello world from Lua" + * for w in string.gmatch(s, "%a+") do + * print(w) + * end + * + * will iterate over all the words from string s, printing one per line. + * The next example collects all pairs key=value from the given string into a table: + * t = {} + * s = "from=world, to=Lua" + * for k, v in string.gmatch(s, "(%w+)=(%w+)") do + * t[k] = v + * end + * + * For this function, a '^' at the start of a pattern does not work as an anchor, + * as this would prevent the iteration. + */ + static Varargs gmatch( Varargs args ) { + LuaString src = args.checkstring( 1 ); + LuaString pat = args.checkstring( 2 ); + return new GMatchAux(args, src, pat); + } + + static class GMatchAux extends VarArgFunction { + private final int srclen; + private final MatchState ms; + private int soffset; + public GMatchAux(Varargs args, LuaString src, LuaString pat) { + this.srclen = src.length(); + this.ms = new MatchState(args, src, pat); + this.soffset = 0; + } + public Varargs invoke(Varargs args) { + for ( ; soffset=0 ) { + int soff = soffset; + soffset = res; + /* DAN200 START */ + if (res == soff) soffset++; + /* DAN200 END */ + return ms.push_captures( true, soff, res ); + } + } + return NIL; + } + } + + + /** + * string.gsub (s, pattern, repl [, n]) + * Returns a copy of s in which all (or the first n, if given) occurrences of the + * pattern have been replaced by a replacement string specified by repl, which + * may be a string, a table, or a function. gsub also returns, as its second value, + * the total number of matches that occurred. + * + * If repl is a string, then its value is used for replacement. + * The character % works as an escape character: any sequence in repl of the form %n, + * with n between 1 and 9, stands for the value of the n-th captured substring (see below). + * The sequence %0 stands for the whole match. The sequence %% stands for a single %. + * + * If repl is a table, then the table is queried for every match, using the first capture + * as the key; if the pattern specifies no captures, then the whole match is used as the key. + * + * If repl is a function, then this function is called every time a match occurs, + * with all captured substrings passed as arguments, in order; if the pattern specifies + * no captures, then the whole match is passed as a sole argument. + * + * If the value returned by the table query or by the function call is a string or a number, + * then it is used as the replacement string; otherwise, if it is false or nil, + * then there is no replacement (that is, the original match is kept in the string). + * + * Here are some examples: + * x = string.gsub("hello world", "(%w+)", "%1 %1") + * --> x="hello hello world world" + * + * x = string.gsub("hello world", "%w+", "%0 %0", 1) + * --> x="hello hello world" + * + * x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1") + * --> x="world hello Lua from" + * + * x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv) + * --> x="home = /home/roberto, user = roberto" + * + * x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s) + * return loadstring(s)() + * end) + * --> x="4+5 = 9" + * + * local t = {name="lua", version="5.1"} + * x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t) + * --> x="lua-5.1.tar.gz" + */ + static Varargs gsub( Varargs args ) { + LuaString src = args.checkstring( 1 ); + final int srclen = src.length(); + LuaString p = args.checkstring( 2 ); + LuaValue repl = args.arg( 3 ); + int max_s = args.optint( 4, srclen + 1 ); + final boolean anchor = p.length() > 0 && p.charAt( 0 ) == '^'; + + Buffer lbuf = new Buffer( srclen ); + MatchState ms = new MatchState( args, src, p ); + + int soffset = 0; + int n = 0; + while ( n < max_s ) { + ms.reset(); + int res = ms.match( soffset, anchor ? 1 : 0 ); + if ( res != -1 ) { + n++; + ms.add_value( lbuf, soffset, res, repl ); + } + if ( res != -1 && res > soffset ) + soffset = res; + else if ( soffset < srclen ) + lbuf.append( (byte) src.luaByte( soffset++ ) ); + else + break; + if ( anchor ) + break; + } + lbuf.append( src.substring( soffset, srclen ) ); + return varargsOf(lbuf.tostring(), valueOf(n)); + } + + /** + * string.len (s) + * + * Receives a string and returns its length. The empty string "" has length 0. + * Embedded zeros are counted, so "a\000bc\000" has length 5. + */ + static LuaValue len( LuaValue arg ) { + return arg.checkstring().len(); + } + + /** + * string.lower (s) + * + * Receives a string and returns a copy of this string with all uppercase letters + * changed to lowercase. All other characters are left unchanged. + * The definition of what an uppercase letter is depends on the current locale. + */ + static LuaValue lower( LuaValue arg ) { + return valueOf( arg.checkjstring().toLowerCase() ); + } + + /** + * string.match (s, pattern [, init]) + * + * Looks for the first match of pattern in the string s. If it finds one, + * then match returns the captures from the pattern; otherwise it returns + * nil. If pattern specifies no captures, then the whole match is returned. + * A third, optional numerical argument init specifies where to start the + * search; its default value is 1 and may be negative. + */ + static Varargs match( Varargs args ) { + return str_find_aux( args, false ); + } + + /** + * string.rep (s, n) + * + * Returns a string that is the concatenation of n copies of the string s. + */ + static Varargs rep( Varargs args ) { + LuaString s = args.checkstring( 1 ); + int n = args.checkint( 2 ); + final byte[] bytes = new byte[ s.length() * n ]; + int len = s.length(); + for ( int offset = 0; offset < bytes.length; offset += len ) { + s.copyInto( 0, bytes, offset, len ); + } + return LuaString.valueOf( bytes ); + } + + /** + * string.reverse (s) + * + * Returns a string that is the string s reversed. + */ + static LuaValue reverse( LuaValue arg ) { + LuaString s = arg.checkstring(); + int n = s.length(); + byte[] b = new byte[n]; + for ( int i=0, j=n-1; i l ) + end = l; + + if ( start <= end ) { + return s.substring( start-1 , end ); + } else { + return EMPTYSTRING; + } + } + + /** + * string.upper (s) + * + * Receives a string and returns a copy of this string with all lowercase letters + * changed to uppercase. All other characters are left unchanged. + * The definition of what a lowercase letter is depends on the current locale. + */ + static LuaValue upper( LuaValue arg ) { + return valueOf(arg.checkjstring().toUpperCase()); + } + + /** + * This utility method implements both string.find and string.match. + */ + static Varargs str_find_aux( Varargs args, boolean find ) { + LuaString s = args.checkstring( 1 ); + LuaString pat = args.checkstring( 2 ); + int init = args.optint( 3, 1 ); + + if ( init > 0 ) { + init = Math.min( init - 1, s.length() ); + } else if ( init < 0 ) { + init = Math.max( 0, s.length() + init ); + } + + boolean fastMatch = find && ( args.arg(4).toboolean() || pat.indexOfAny( SPECIALS ) == -1 ); + + if ( fastMatch ) { + int result = s.indexOf( pat, init ); + if ( result != -1 ) { + return varargsOf( valueOf(result+1), valueOf(result+pat.length()) ); + } + } else { + MatchState ms = new MatchState( args, s, pat ); + + boolean anchor = false; + int poff = 0; + if ( pat.luaByte( 0 ) == '^' ) { + anchor = true; + poff = 1; + } + + int soff = init; + do { + int res; + ms.reset(); + if ( ( res = ms.match( soff, poff ) ) != -1 ) { + if ( find ) { + return varargsOf( valueOf(soff+1), valueOf(res), ms.push_captures( false, soff, res )); + } else { + return ms.push_captures( true, soff, res ); + } + } + } while ( soff++ < s.length() && !anchor ); + } + return NIL; + } + + private static int posrelat( int pos, int len ) { + return ( pos >= 0 ) ? pos : len + pos + 1; + } + + // Pattern matching implementation + + private static final int L_ESC = '%'; + private static final LuaString SPECIALS = valueOf("^$*+?.([%-"); + private static final int MAX_CAPTURES = 32; + + private static final int CAP_UNFINISHED = -1; + private static final int CAP_POSITION = -2; + + private static final byte MASK_ALPHA = 0x01; + private static final byte MASK_LOWERCASE = 0x02; + private static final byte MASK_UPPERCASE = 0x04; + private static final byte MASK_DIGIT = 0x08; + private static final byte MASK_PUNCT = 0x10; + private static final byte MASK_SPACE = 0x20; + private static final byte MASK_CONTROL = 0x40; + private static final byte MASK_HEXDIGIT = (byte)0x80; + + private static final byte[] CHAR_TABLE; + + static { + CHAR_TABLE = new byte[256]; + + for ( int i = 0; i < 256; ++i ) { + final char c = (char) i; + CHAR_TABLE[i] = (byte)( ( Character.isDigit( c ) ? MASK_DIGIT : 0 ) | + ( Character.isLowerCase( c ) ? MASK_LOWERCASE : 0 ) | + ( Character.isUpperCase( c ) ? MASK_UPPERCASE : 0 ) | + ( ( c < ' ' || c == 0x7F ) ? MASK_CONTROL : 0 ) ); + if ( ( c >= 'a' && c <= 'f' ) || ( c >= 'A' && c <= 'F' ) || ( c >= '0' && c <= '9' ) ) { + CHAR_TABLE[i] |= MASK_HEXDIGIT; + } + if ( ( c >= '!' && c <= '/' ) || ( c >= ':' && c <= '@' ) ) { + CHAR_TABLE[i] |= MASK_PUNCT; + } + if ( ( CHAR_TABLE[i] & ( MASK_LOWERCASE | MASK_UPPERCASE ) ) != 0 ) { + CHAR_TABLE[i] |= MASK_ALPHA; + } + } + + CHAR_TABLE[' '] = MASK_SPACE; + CHAR_TABLE['\r'] |= MASK_SPACE; + CHAR_TABLE['\n'] |= MASK_SPACE; + CHAR_TABLE['\t'] |= MASK_SPACE; + /* DAN200 START */ + //CHAR_TABLE[0x0C /* '\v' */ ] |= MASK_SPACE; + CHAR_TABLE[0x0B /* '\v' */ ] |= MASK_SPACE; + /* DAN200 END */ + CHAR_TABLE['\f'] |= MASK_SPACE; + }; + + static class MatchState { + final LuaString s; + final LuaString p; + final Varargs args; + int level; + int[] cinit; + int[] clen; + + MatchState( Varargs args, LuaString s, LuaString pattern ) { + this.s = s; + this.p = pattern; + this.args = args; + this.level = 0; + this.cinit = new int[ MAX_CAPTURES ]; + this.clen = new int[ MAX_CAPTURES ]; + } + + void reset() { + level = 0; + } + + private void add_s( Buffer lbuf, LuaString news, int soff, int e ) { + int l = news.length(); + for ( int i = 0; i < l; ++i ) { + byte b = (byte) news.luaByte( i ); + if ( b != L_ESC ) { + lbuf.append( (byte) b ); + } else { + ++i; // skip ESC + b = (byte) news.luaByte( i ); + if ( !Character.isDigit( (char) b ) ) { + lbuf.append( b ); + } else if ( b == '0' ) { + lbuf.append( s.substring( soff, e ) ); + } else { + lbuf.append( push_onecapture( b - '1', soff, e ).strvalue() ); + } + } + } + } + + public void add_value( Buffer lbuf, int soffset, int end, LuaValue repl ) { + switch ( repl.type() ) { + case LuaValue.TSTRING: + case LuaValue.TNUMBER: + add_s( lbuf, repl.strvalue(), soffset, end ); + return; + + case LuaValue.TFUNCTION: + repl = repl.invoke( push_captures( true, soffset, end ) ).arg1(); + break; + + case LuaValue.TTABLE: + // Need to call push_onecapture here for the error checking + repl = repl.get( push_onecapture( 0, soffset, end ) ); + break; + + default: + error( "bad argument: string/function/table expected" ); + return; + } + + if ( !repl.toboolean() ) { + repl = s.substring( soffset, end ); + } else if ( ! repl.isstring() ) { + error( "invalid replacement value (a "+repl.typename()+")" ); + } + lbuf.append( repl.strvalue() ); + } + + Varargs push_captures( boolean wholeMatch, int soff, int end ) { + int nlevels = ( this.level == 0 && wholeMatch ) ? 1 : this.level; + switch ( nlevels ) { + case 0: return NONE; + case 1: return push_onecapture( 0, soff, end ); + } + LuaValue[] v = new LuaValue[nlevels]; + for ( int i = 0; i < nlevels; ++i ) + v[i] = push_onecapture( i, soff, end ); + return varargsOf(v); + } + + private LuaValue push_onecapture( int i, int soff, int end ) { + if ( i >= this.level ) { + if ( i == 0 ) { + return s.substring( soff, end ); + } else { + return error( "invalid capture index" ); + } + } else { + int l = clen[i]; + if ( l == CAP_UNFINISHED ) { + return error( "unfinished capture" ); + } + if ( l == CAP_POSITION ) { + return valueOf( cinit[i] + 1 ); + } else { + int begin = cinit[i]; + return s.substring( begin, begin + l ); + } + } + } + + private int check_capture( int l ) { + l -= '1'; + if ( l < 0 || l >= level || this.clen[l] == CAP_UNFINISHED ) { + error("invalid capture index"); + } + return l; + } + + private int capture_to_close() { + int level = this.level; + for ( level--; level >= 0; level-- ) + if ( clen[level] == CAP_UNFINISHED ) + return level; + error("invalid pattern capture"); + return 0; + } + + int classend( int poffset ) { + switch ( p.luaByte( poffset++ ) ) { + case L_ESC: + if ( poffset == p.length() ) { + error( "malformed pattern (ends with %)" ); + } + return poffset + 1; + + case '[': + if ( p.luaByte( poffset ) == '^' ) poffset++; + do { + if ( poffset == p.length() ) { + error( "malformed pattern (missing ])" ); + } + if ( p.luaByte( poffset++ ) == L_ESC && poffset != p.length() ) + poffset++; + } while ( p.luaByte( poffset ) != ']' ); + return poffset + 1; + default: + return poffset; + } + } + + static boolean match_class( int c, int cl ) { + final char lcl = Character.toLowerCase( (char) cl ); + int cdata = CHAR_TABLE[c]; + + boolean res; + switch ( lcl ) { + case 'a': res = ( cdata & MASK_ALPHA ) != 0; break; + case 'd': res = ( cdata & MASK_DIGIT ) != 0; break; + case 'l': res = ( cdata & MASK_LOWERCASE ) != 0; break; + case 'u': res = ( cdata & MASK_UPPERCASE ) != 0; break; + case 'c': res = ( cdata & MASK_CONTROL ) != 0; break; + case 'p': res = ( cdata & MASK_PUNCT ) != 0; break; + case 's': res = ( cdata & MASK_SPACE ) != 0; break; + case 'w': res = ( cdata & ( MASK_ALPHA | MASK_DIGIT ) ) != 0; break; + case 'x': res = ( cdata & MASK_HEXDIGIT ) != 0; break; + case 'z': res = ( c == 0 ); break; + default: return cl == c; + } + return ( lcl == cl ) ? res : !res; + } + + boolean matchbracketclass( int c, int poff, int ec ) { + boolean sig = true; + if ( p.luaByte( poff + 1 ) == '^' ) { + sig = false; + poff++; + } + while ( ++poff < ec ) { + if ( p.luaByte( poff ) == L_ESC ) { + poff++; + if ( match_class( c, p.luaByte( poff ) ) ) + return sig; + } + else if ( ( p.luaByte( poff + 1 ) == '-' ) && ( poff + 2 < ec ) ) { + poff += 2; + if ( p.luaByte( poff - 2 ) <= c && c <= p.luaByte( poff ) ) + return sig; + } + else if ( p.luaByte( poff ) == c ) return sig; + } + return !sig; + } + + boolean singlematch( int c, int poff, int ep ) { + switch ( p.luaByte( poff ) ) { + case '.': return true; + case L_ESC: return match_class( c, p.luaByte( poff + 1 ) ); + case '[': return matchbracketclass( c, poff, ep - 1 ); + default: return p.luaByte( poff ) == c; + } + } + + /** + * Perform pattern matching. If there is a match, returns offset into s + * where match ends, otherwise returns -1. + */ + int match( int soffset, int poffset ) { + while ( true ) { + // Check if we are at the end of the pattern - + // equivalent to the '\0' case in the C version, but our pattern + // string is not NUL-terminated. + if ( poffset == p.length() ) + return soffset; + switch ( p.luaByte( poffset ) ) { + case '(': + if ( ++poffset < p.length() && p.luaByte( poffset ) == ')' ) + return start_capture( soffset, poffset + 1, CAP_POSITION ); + else + return start_capture( soffset, poffset, CAP_UNFINISHED ); + case ')': + return end_capture( soffset, poffset + 1 ); + case L_ESC: + if ( poffset + 1 == p.length() ) + error("malformed pattern (ends with '%')"); + switch ( p.luaByte( poffset + 1 ) ) { + case 'b': + soffset = matchbalance( soffset, poffset + 2 ); + if ( soffset == -1 ) return -1; + poffset += 4; + continue; + case 'f': { + poffset += 2; + if ( p.luaByte( poffset ) != '[' ) { + error("Missing [ after %f in pattern"); + } + int ep = classend( poffset ); + int previous = ( soffset == 0 ) ? -1 : s.luaByte( soffset - 1 ); + if ( matchbracketclass( previous, poffset, ep - 1 ) || + matchbracketclass( s.luaByte( soffset ), poffset, ep - 1 ) ) + return -1; + poffset = ep; + continue; + } + default: { + int c = p.luaByte( poffset + 1 ); + if ( Character.isDigit( (char) c ) ) { + soffset = match_capture( soffset, c ); + if ( soffset == -1 ) + return -1; + return match( soffset, poffset + 2 ); + } + } + } + case '$': + if ( poffset + 1 == p.length() ) + return ( soffset == s.length() ) ? soffset : -1; + } + int ep = classend( poffset ); + boolean m = soffset < s.length() && singlematch( s.luaByte( soffset ), poffset, ep ); + int pc = ( ep < p.length() ) ? p.luaByte( ep ) : '\0'; + + switch ( pc ) { + case '?': + int res; + if ( m && ( ( res = match( soffset + 1, ep + 1 ) ) != -1 ) ) + return res; + poffset = ep + 1; + continue; + case '*': + return max_expand( soffset, poffset, ep ); + case '+': + return ( m ? max_expand( soffset + 1, poffset, ep ) : -1 ); + case '-': + return min_expand( soffset, poffset, ep ); + default: + if ( !m ) + return -1; + soffset++; + poffset = ep; + continue; + } + } + } + + int max_expand( int soff, int poff, int ep ) { + int i = 0; + while ( soff + i < s.length() && + singlematch( s.luaByte( soff + i ), poff, ep ) ) + i++; + while ( i >= 0 ) { + int res = match( soff + i, ep + 1 ); + if ( res != -1 ) + return res; + i--; + } + return -1; + } + + int min_expand( int soff, int poff, int ep ) { + for ( ;; ) { + int res = match( soff, ep + 1 ); + if ( res != -1 ) + return res; + else if ( soff < s.length() && singlematch( s.luaByte( soff ), poff, ep ) ) + soff++; + else return -1; + } + } + + int start_capture( int soff, int poff, int what ) { + int res; + int level = this.level; + if ( level >= MAX_CAPTURES ) { + error( "too many captures" ); + } + cinit[ level ] = soff; + clen[ level ] = what; + this.level = level + 1; + if ( ( res = match( soff, poff ) ) == -1 ) + this.level--; + return res; + } + + int end_capture( int soff, int poff ) { + int l = capture_to_close(); + int res; + clen[l] = soff - cinit[l]; + if ( ( res = match( soff, poff ) ) == -1 ) + clen[l] = CAP_UNFINISHED; + return res; + } + + int match_capture( int soff, int l ) { + l = check_capture( l ); + int len = clen[ l ]; + if ( ( s.length() - soff ) >= len && + LuaString.equals( s, cinit[l], s, soff, len ) ) + return soff + len; + else + return -1; + } + + int matchbalance( int soff, int poff ) { + final int plen = p.length(); + if ( poff == plen || poff + 1 == plen ) { + error( "unbalanced pattern" ); + } + /* DAN200 START */ + if ( soff >= s.length() ) + return -1; + /* DAN200 END */ + if ( s.luaByte( soff ) != p.luaByte( poff ) ) + return -1; + else { + int b = p.luaByte( poff ); + int e = p.luaByte( poff + 1 ); + int cont = 1; + while ( ++soff < s.length() ) { + if ( s.luaByte( soff ) == e ) { + if ( --cont == 0 ) return soff + 1; + } + else if ( s.luaByte( soff ) == b ) cont++; + } + } + return -1; + } + } +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/lib/TableLib.java b/luaj-2.0.3/src/core/org/luaj/vm2/lib/TableLib.java new file mode 100644 index 0000000000..c26b9d4083 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/lib/TableLib.java @@ -0,0 +1,124 @@ +/******************************************************************************* +* Copyright (c) 2009 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.lib; + +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; + +/** + * Subclass of {@link LibFunction} which implements the lua standard {@code table} + * library. + * + *

+ * Typically, this library is included as part of a call to either + * {@link JsePlatform#standardGlobals()} or {@link JmePlatform#standardGlobals()} + *

+ * To instantiate and use it directly, + * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: + *

 {@code
+ * LuaTable _G = new LuaTable();
+ * LuaThread.setGlobals(_G);
+ * _G.load(new BaseLib());
+ * _G.load(new PackageLib());
+ * _G.load(new TableLib());
+ * LuaValue tbl = LuaValue.listOf( new LuaValue[] {
+ * 		LuaValue.valueOf( "abc" ),
+ * 		LuaValue.valueOf( "def" ) } );
+ * LuaValue sep = LuaValue.valueOf( "-" );
+ * System.out.println( _G.get("table").get("concat").call( tbl, sep ) );
+ * } 
+ * Doing so will ensure the library is properly initialized + * and loaded into the globals table. + *

+ * This has been implemented to match as closely as possible the behavior in the corresponding library in C. + * @see LibFunction + * @see JsePlatform + * @see JmePlatform + * @see http://www.lua.org/manual/5.1/manual.html#5.5 + */ +public class TableLib extends OneArgFunction { + + public TableLib() { + } + + private LuaTable init() { + LuaTable t = new LuaTable(); + bind(t, TableLib.class, new String[] { "getn", "maxn", }, 1 ); + bind(t, TableLibV.class, new String[] { + "remove", "concat", "insert", "sort", "foreach", "foreachi", } ); + env.set("table", t); + PackageLib.instance.LOADED.set("table", t); + return t; + } + + public LuaValue call(LuaValue arg) { + switch ( opcode ) { + case 0: // init library + return init(); + case 1: // "getn" (table) -> number + return arg.checktable().getn(); + case 2: // "maxn" (table) -> number + return valueOf( arg.checktable().maxn()); + } + return NIL; + } + + static final class TableLibV extends VarArgFunction { + public Varargs invoke(Varargs args) { + switch ( opcode ) { + case 0: { // "remove" (table [, pos]) -> removed-ele + LuaTable table = args.checktable(1); + int pos = args.narg()>1? args.checkint(2): 0; + return table.remove(pos); + } + case 1: { // "concat" (table [, sep [, i [, j]]]) -> string + LuaTable table = args.checktable(1); + return table.concat( + args.optstring(2,LuaValue.EMPTYSTRING), + args.optint(3,1), + args.isvalue(4)? args.checkint(4): table.length() ); + } + case 2: { // "insert" (table, [pos,] value) -> prev-ele + final LuaTable table = args.checktable(1); + final int pos = args.narg()>2? args.checkint(2): 0; + final LuaValue value = args.arg( args.narg()>2? 3: 2 ); + table.insert( pos, value ); + return NONE; + } + case 3: { // "sort" (table [, comp]) -> void + LuaTable table = args.checktable(1); + LuaValue compare = (args.isnoneornil(2)? NIL: args.checkfunction(2)); + table.sort( compare ); + return NONE; + } + case 4: { // (table, func) -> void + return args.checktable(1).foreach( args.checkfunction(2) ); + } + case 5: { // "foreachi" (table, func) -> void + return args.checktable(1).foreachi( args.checkfunction(2) ); + } + } + return NONE; + } + } +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/lib/ThreeArgFunction.java b/luaj-2.0.3/src/core/org/luaj/vm2/lib/ThreeArgFunction.java new file mode 100644 index 0000000000..d958d72610 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/lib/ThreeArgFunction.java @@ -0,0 +1,80 @@ +/******************************************************************************* +* Copyright (c) 2009 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.lib; + +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; + +/** Abstract base class for Java function implementations that take two arguments and + * return one value. + *

+ * Subclasses need only implement {@link LuaValue#call(LuaValue,LuaValue,LuaValue)} to complete this class, + * simplifying development. + * All other uses of {@link #call()}, {@link #invoke(Varargs)},etc, + * are routed through this method by this class, + * dropping or extending arguments with {@code nil} values as required. + *

+ * If more or less than three arguments are required, + * or variable argument or variable return values, + * then use one of the related function + * {@link ZeroArgFunction}, {@link OneArgFunction}, {@link TwoArgFunction}, or {@link VarArgFunction}. + *

+ * See {@link LibFunction} for more information on implementation libraries and library functions. + * @see #call(LuaValue,LuaValue,LuaValue) + * @see LibFunction + * @see ZeroArgFunction + * @see OneArgFunction + * @see TwoArgFunction + * @see VarArgFunction + */ +abstract public class ThreeArgFunction extends LibFunction { + + abstract public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3); + + /** Default constructor */ + public ThreeArgFunction() { + } + + /** Constructor with specific environment + * @param env The environment to apply during constructon. + */ + public ThreeArgFunction( LuaValue env ) { + this.env = env; + } + + public final LuaValue call() { + return call(NIL, NIL, NIL); + } + + public final LuaValue call(LuaValue arg) { + return call(arg, NIL, NIL); + } + + public LuaValue call(LuaValue arg1, LuaValue arg2) { + return call(arg1, arg2, NIL); + } + + public Varargs invoke(Varargs varargs) { + return call(varargs.arg1(),varargs.arg(2),varargs.arg(3)); + } + +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/lib/TwoArgFunction.java b/luaj-2.0.3/src/core/org/luaj/vm2/lib/TwoArgFunction.java new file mode 100644 index 0000000000..b2c1b0c75b --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/lib/TwoArgFunction.java @@ -0,0 +1,80 @@ +/******************************************************************************* +* Copyright (c) 2009 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.lib; + +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; + +/** Abstract base class for Java function implementations that take two arguments and + * return one value. + *

+ * Subclasses need only implement {@link LuaValue#call(LuaValue,LuaValue)} to complete this class, + * simplifying development. + * All other uses of {@link #call()}, {@link #invoke(Varargs)},etc, + * are routed through this method by this class, + * dropping or extending arguments with {@code nil} values as required. + *

+ * If more or less than two arguments are required, + * or variable argument or variable return values, + * then use one of the related function + * {@link ZeroArgFunction}, {@link OneArgFunction}, {@link ThreeArgFunction}, or {@link VarArgFunction}. + *

+ * See {@link LibFunction} for more information on implementation libraries and library functions. + * @see #call(LuaValue,LuaValue) + * @see LibFunction + * @see ZeroArgFunction + * @see OneArgFunction + * @see ThreeArgFunction + * @see VarArgFunction + */ +abstract public class TwoArgFunction extends LibFunction { + + abstract public LuaValue call(LuaValue arg1, LuaValue arg2); + + /** Default constructor */ + public TwoArgFunction() { + } + + /** Constructor with specific environment + * @param env The environment to apply during constructon. + */ + public TwoArgFunction( LuaValue env ) { + this.env = env; + } + + public final LuaValue call() { + return call(NIL, NIL); + } + + public final LuaValue call(LuaValue arg) { + return call(arg, NIL); + } + + public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { + return call(arg1, arg2); + } + + public Varargs invoke(Varargs varargs) { + return call(varargs.arg1(),varargs.arg(2)); + } + +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/lib/VarArgFunction.java b/luaj-2.0.3/src/core/org/luaj/vm2/lib/VarArgFunction.java new file mode 100644 index 0000000000..9fb07af1a3 --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/lib/VarArgFunction.java @@ -0,0 +1,100 @@ +/******************************************************************************* +* Copyright (c) 2009 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.lib; + +import org.luaj.vm2.LuaThread; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; + +/** Abstract base class for Java function implementations that takes varaiable arguments and + * returns multiple return values. + *

+ * Subclasses need only implement {@link LuaValue#invoke(Varargs)} to complete this class, + * simplifying development. + * All other uses of {@link #call(LuaValue)}, {@link #invoke()},etc, + * are routed through this method by this class, + * converting arguments to {@linnk Varargs} and + * dropping or extending return values with {@code nil} values as required. + *

+ * If between one and three arguments are required, and only one return value is returned, + * {@link ZeroArgFunction}, {@link OneArgFunction}, {@link TwoArgFunction}, or {@link ThreeArgFunction}. + *

+ * See {@link LibFunction} for more information on implementation libraries and library functions. + * @see #invoke(Varargs) + * @see LibFunction + * @see ZeroArgFunction + * @see OneArgFunction + * @see TwoArgFunction + * @see ThreeArgFunction + */ +abstract public class VarArgFunction extends LibFunction { + public VarArgFunction() { + } + + public VarArgFunction( LuaValue env ) { + this.env = env; + } + + public LuaValue call() { + return invoke(NONE).arg1(); + } + + public LuaValue call(LuaValue arg) { + return invoke(arg).arg1(); + } + + public LuaValue call(LuaValue arg1, LuaValue arg2) { + return invoke(varargsOf(arg1,arg2)).arg1(); + } + + public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { + return invoke(varargsOf(arg1,arg2,arg3)).arg1(); + } + + /** + * Override and implement for the best performance. + * May not have expected behavior for tail calls. + * Should not be used if either: + * - function needs to be used as a module + * - function has a possibility of returning a TailcallVarargs + * @param args the arguments to the function call. + */ + public Varargs invoke(Varargs args) { + LuaThread.CallStack cs = LuaThread.onCall(this); + try { + return this.onInvoke(args).eval(); + } finally { + cs.onReturn(); + } + } + + /** + * Override to provide a call implementation that runs in an environment + * that can participate in setfenv, and behaves as expected + * when returning TailcallVarargs. + * @param args the arguments to the function call. + */ + public Varargs onInvoke(Varargs args) { + return invoke(args); + } + +} diff --git a/luaj-2.0.3/src/core/org/luaj/vm2/lib/ZeroArgFunction.java b/luaj-2.0.3/src/core/org/luaj/vm2/lib/ZeroArgFunction.java new file mode 100644 index 0000000000..526d2fedeb --- /dev/null +++ b/luaj-2.0.3/src/core/org/luaj/vm2/lib/ZeroArgFunction.java @@ -0,0 +1,77 @@ +/******************************************************************************* +* Copyright (c) 2009-2011 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.lib; + +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; + +/** Abstract base class for Java function implementations that take no arguments and + * return one value. + *

+ * Subclasses need only implement {@link LuaValue#call()} to complete this class, + * simplifying development. + * All other uses of {@link #call(LuaValue)}, {@link #invoke(Varargs)},etc, + * are routed through this method by this class. + *

+ * If one or more arguments are required, or variable argument or variable return values, + * then use one of the related function + * {@link OneArgFunction}, {@link TwoArgFunction}, {@link ThreeArgFunction}, or {@link VarArgFunction}. + *

+ * See {@link LibFunction} for more information on implementation libraries and library functions. + * @see #call() + * @see LibFunction + * @see OneArgFunction + * @see TwoArgFunction + * @see ThreeArgFunction + * @see VarArgFunction + */ +abstract public class ZeroArgFunction extends LibFunction { + + abstract public LuaValue call(); + + /** Default constructor */ + public ZeroArgFunction() { + } + + /** Constructor with specific environment + * @param env The environment to apply during constructon. + */ + public ZeroArgFunction( LuaValue env ) { + this.env = env; + } + + public LuaValue call(LuaValue arg) { + return call(); + } + + public LuaValue call(LuaValue arg1, LuaValue arg2) { + return call(); + } + + public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { + return call(); + } + + public Varargs invoke(Varargs varargs) { + return call(); + } +} diff --git a/luaj-2.0.3/src/jme/org/luaj/vm2/lib/jme/JmeIoLib.java b/luaj-2.0.3/src/jme/org/luaj/vm2/lib/jme/JmeIoLib.java new file mode 100644 index 0000000000..1a66df9e20 --- /dev/null +++ b/luaj-2.0.3/src/jme/org/luaj/vm2/lib/jme/JmeIoLib.java @@ -0,0 +1,227 @@ +/******************************************************************************* +* Copyright (c) 2009-2011 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.lib.jme; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import javax.microedition.io.Connector; +import javax.microedition.io.StreamConnection; + +import org.luaj.vm2.LuaString; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.BaseLib; +import org.luaj.vm2.lib.IoLib; +import org.luaj.vm2.lib.LibFunction; + +/** + * Subclass of {@link IoLib} and therefore {@link LibFunction} which implements the lua standard {@code io} + * library for the JSE platform. + *

+ * The implementation of the is based on CLDC 1.0 and StreamConnection. + * However, seek is not supported. + *

+ * Typically, this library is included as part of a call to + * {@link JmePlatform#standardGlobals()} + *

+ * To instantiate and use it directly, + * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: + *

 {@code
+ * LuaTable _G = new LuaTable();
+ * LuaThread.setGlobals(_G);
+ * _G.load(new BaseLib());
+ * _G.load(new PackageLib());
+ * _G.load(new JmeIoLib());
+ * _G.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
+ * } 
+ * Doing so will ensure the library is properly initialized + * and loaded into the globals table. + *

+ * This has been implemented to match as closely as possible the behavior in the corresponding library in C. + * @see LibFunction + * @see JsePlatform + * @see JmePlatform + * @see IoLib + * @see JseIoLib + * @see http://www.lua.org/manual/5.1/manual.html#5.6 + */ +public class JmeIoLib extends IoLib { + + public JmeIoLib() { + super(); + } + + protected File wrapStdin() throws IOException { + return new FileImpl(BaseLib.instance.STDIN); + } + + protected File wrapStdout() throws IOException { + return new FileImpl(BaseLib.instance.STDOUT); + } + + protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException { + String url = "file:///" + filename; + int mode = readMode? Connector.READ: Connector.READ_WRITE; + StreamConnection conn = (StreamConnection) Connector.open( url, mode ); + File f = readMode? + new FileImpl(conn, conn.openInputStream(), null): + new FileImpl(conn, conn.openInputStream(), conn.openOutputStream()); + /* + if ( appendMode ) { + f.seek("end",0); + } else { + if ( ! readMode ) + conn.truncate(0); + } + */ + return f; + } + + private static void notimplemented() throws IOException { + throw new IOException("not implemented"); + } + + protected File openProgram(String prog, String mode) throws IOException { + notimplemented(); + return null; + } + + protected File tmpFile() throws IOException { + notimplemented(); + return null; + } + + private final class FileImpl extends File { + private final StreamConnection conn; + private final InputStream is; + private final OutputStream os; + private boolean closed = false; + private boolean nobuffer = false; + private int lookahead = -1; + private FileImpl( StreamConnection conn, InputStream is, OutputStream os ) { + this.conn = conn; + this.is = is; + this.os = os; + } + private FileImpl( InputStream i ) { + this( null, i, null ); + } + private FileImpl( OutputStream o ) { + this( null, null, o ); + } + public String tojstring() { + return "file ("+this.hashCode()+")"; + } + public boolean isstdfile() { + return conn == null; + } + public void close() throws IOException { + closed = true; + if ( conn != null ) { + conn.close(); + } + } + public void flush() throws IOException { + if ( os != null ) + os.flush(); + } + public void write(LuaString s) throws IOException { + if ( os != null ) + os.write( s.m_bytes, s.m_offset, s.m_length ); + else + notimplemented(); + if ( nobuffer ) + flush(); + } + public boolean isclosed() { + return closed; + } + public int seek(String option, int pos) throws IOException { + /* + if ( conn != null ) { + if ( "set".equals(option) ) { + conn.seek(pos); + return (int) conn.getFilePointer(); + } else if ( "end".equals(option) ) { + conn.seek(conn.length()+1+pos); + return (int) conn.length()+1; + } else { + conn.seek(conn.getFilePointer()+pos); + return (int) conn.getFilePointer(); + } + } + */ + notimplemented(); + return 0; + } + public void setvbuf(String mode, int size) { + nobuffer = "no".equals(mode); + } + + // get length remaining to read + public int remaining() throws IOException { + return -1; + } + + // peek ahead one character + public int peek() throws IOException { + if ( lookahead < 0 ) + lookahead = is.read(); + return lookahead; + } + + // return char if read, -1 if eof, throw IOException on other exception + public int read() throws IOException { + if ( lookahead >= 0 ) { + int c = lookahead; + lookahead = -1; + return c; + } + if ( is != null ) + return is.read(); + notimplemented(); + return 0; + } + + // return number of bytes read if positive, -1 if eof, throws IOException + public int read(byte[] bytes, int offset, int length) throws IOException { + int n,i=0; + if (is!=null) { + if ( length > 0 && lookahead >= 0 ) { + bytes[offset] = (byte) lookahead; + lookahead = -1; + i += 1; + } + for ( ; i 0 ? i : -1 ); + i += n; + } + } else { + notimplemented(); + } + return length; + } + } +} diff --git a/luaj-2.0.3/src/jme/org/luaj/vm2/lib/jme/JmePlatform.java b/luaj-2.0.3/src/jme/org/luaj/vm2/lib/jme/JmePlatform.java new file mode 100644 index 0000000000..04e6482a63 --- /dev/null +++ b/luaj-2.0.3/src/jme/org/luaj/vm2/lib/jme/JmePlatform.java @@ -0,0 +1,130 @@ +/******************************************************************************* + * Copyright (c) 2009 Luaj.org. 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. + ******************************************************************************/ +package org.luaj.vm2.lib.jme; + +import org.luaj.vm2.compiler.LuaC; +import org.luaj.vm2.LoadState; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaThread; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.BaseLib; +import org.luaj.vm2.lib.CoroutineLib; +import org.luaj.vm2.lib.DebugLib; +import org.luaj.vm2.lib.MathLib; +import org.luaj.vm2.lib.OsLib; +import org.luaj.vm2.lib.PackageLib; +import org.luaj.vm2.lib.StringLib; +import org.luaj.vm2.lib.TableLib; + +/** The {@link JmePlatform} class is a convenience class to standardize + * how globals tables are initialized for the JME platform. + *

+ * The JME platform, being limited, cannot implement all libraries in all aspects. The main limitations are + *

    + *
  • Some math functions are not implemented, see {@link MathLib} for details
  • + *
  • Scripts are loaded via Class.getResourceAsStream(), see {@link BaseLib} for details
  • + *
  • OS functions execute(), remove(), rename(), and tmpname() vary, see {@link OsLib} for details
  • + *
  • I/O seek is not implemented, see {@link JmeIoLib} for details
  • + *
  • luajava is not available, see {@link LuajavaLib} for details
  • + *
+ *

+ * It is used to allocate either a set of standard globals using + * {@link #standardGlobals()} or debug globals using {@link #debugGlobals()} + *

+ * A simple example of initializing globals and using them from Java is: + *

 {@code
+ * LuaValue _G = JmePlatform.standardGlobals();
+ * _G.get("print").call(LuaValue.valueOf("hello, world"));
+ * } 
+ *

+ * Once globals are created, a simple way to load and run a script is: + *

 {@code
+ * LoadState.load( getClass().getResourceAsStream("main.lua"), "main.lua", _G ).call();
+ * } 
+ *

+ * although {@code require} could also be used: + *

 {@code
+ * _G.get("require").call(LuaValue.valueOf("main"));
+ * } 
+ * For this to succeed, the file "main.lua" must be a resource in the class path. + * See {@link BaseLib} for details on finding scripts using {@link ResourceFinder}. + *

+ * The standard globals will contain all standard libraries in their JME flavors: + *

    + *
  • {@link BaseLib}
  • + *
  • {@link PackageLib}
  • + *
  • {@link TableLib}
  • + *
  • {@link StringLib}
  • + *
  • {@link CoroutineLib}
  • + *
  • {@link MathLib}
  • + *
  • {@link JmeIoLib}
  • + *
  • {@link OsLib}
  • + *
+ * In addition, the {@link LuaC} compiler is installed so lua files may be loaded in their source form. + *

+ * The debug globals are simply the standard globals plus the {@code debug} library {@link DebugLib}. + *

+ *

+ * The class ensures that initialization is done in the correct order, + * and that linkage is made to {@link LuaThread#setGlobals(LuaValue)}. + * @see JsePlatform + * @see LoadState + */ +public class JmePlatform { + + /** + * Create a standard set of globals for JME including all the libraries. + * + * @return Table of globals initialized with the standard JME libraries + * @see #debugGlobals() + * @see JsePlatform + * @see JmePlatform + */ + public static LuaTable standardGlobals() { + LuaTable _G = new LuaTable(); + _G.load(new BaseLib()); + _G.load(new PackageLib()); + _G.load(new OsLib()); + _G.load(new MathLib()); + _G.load(new TableLib()); + _G.load(new StringLib()); + _G.load(new CoroutineLib()); + _G.load(new JmeIoLib()); + LuaThread.setGlobals(_G); + LuaC.install(); + return _G; + } + + /** Create standard globals including the {@link debug} library. + * + * @return Table of globals initialized with the standard JSE and debug libraries + * @see #standarsGlobals() + * @see JsePlatform + * @see JmePlatform + * @see DebugLib + */ + public static LuaTable debugGlobals() { + LuaTable _G = standardGlobals(); + _G.load(new DebugLib()); + return _G; + } +} diff --git a/luaj-2.0.3/src/jse/META-INF/services/javax.script.ScriptEngineFactory b/luaj-2.0.3/src/jse/META-INF/services/javax.script.ScriptEngineFactory new file mode 100644 index 0000000000..e3e6dde468 --- /dev/null +++ b/luaj-2.0.3/src/jse/META-INF/services/javax.script.ScriptEngineFactory @@ -0,0 +1 @@ +org.luaj.vm2.script.LuaScriptEngineFactory \ No newline at end of file diff --git a/luaj-2.0.3/src/jse/lua.java b/luaj-2.0.3/src/jse/lua.java new file mode 100644 index 0000000000..ecc1230ace --- /dev/null +++ b/luaj-2.0.3/src/jse/lua.java @@ -0,0 +1,223 @@ +/******************************************************************************* +* Copyright (c) 2009 Luaj.org. 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. +******************************************************************************/ + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Vector; + +import org.luaj.vm2.LoadState; +import org.luaj.vm2.Lua; +import org.luaj.vm2.LuaFunction; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; +import org.luaj.vm2.lib.jse.JsePlatform; +import org.luaj.vm2.lua2java.Lua2Java; +import org.luaj.vm2.luajc.LuaJC; + + +/** + * lua command for use in java se environments. + */ +public class lua { + private static final String version = Lua._VERSION + "Copyright (c) 2009 Luaj.org.org"; + + private static final String usage = + "usage: java -cp luaj-jse.jar lua [options] [script [args]].\n" + + "Available options are:\n" + + " -e stat execute string 'stat'\n" + + " -l name require library 'name'\n" + + " -i enter interactive mode after executing 'script'\n" + + " -v show version information\n" + + " -j use lua2java source-to-source compiler\n" + + " -b use luajc bytecode-to-bytecode compiler (requires bcel on class path)\n" + + " -n nodebug - do not load debug library by default\n" + + " -- stop handling options\n" + + " - execute stdin and stop handling options"; + + private static void usageExit() { + System.out.println(usage); + System.exit(-1); + } + + private static LuaValue _G; + + public static void main( String[] args ) throws IOException { + + // process args + boolean interactive = (args.length == 0); + boolean versioninfo = false; + boolean processing = true; + boolean nodebug = false; + boolean luajc = false; + boolean lua2java = false; + Vector libs = null; + try { + // stateful argument processing + for ( int i=0; i= args.length ) + usageExit(); + // input script - defer to last stage + break; + case 'b': + luajc = true; + break; + case 'j': + lua2java = true; + break; + case 'l': + if ( ++i >= args.length ) + usageExit(); + libs = libs!=null? libs: new Vector(); + libs.addElement( args[i] ); + break; + case 'i': + interactive = true; + break; + case 'v': + versioninfo = true; + break; + case 'n': + nodebug = true; + break; + case '-': + if ( args[i].length() > 2 ) + usageExit(); + processing = false; + break; + default: + usageExit(); + break; + } + } + } + + // echo version + if ( versioninfo ) + System.out.println(version); + + // new lua state + _G = nodebug? JsePlatform.standardGlobals(): JsePlatform.debugGlobals(); + if ( luajc ) LuaJC.install(); + if ( lua2java) Lua2Java.install(); + for ( int i=0, n=libs!=null? libs.size(): 0; i "); + System.out.flush(); + String line = reader.readLine(); + if ( line == null ) + return; + processScript( new ByteArrayInputStream(line.getBytes()), "=stdin", null, 0 ); + } + } +} diff --git a/luaj-2.0.3/src/jse/lua2java.java b/luaj-2.0.3/src/jse/lua2java.java new file mode 100644 index 0000000000..276292d948 --- /dev/null +++ b/luaj-2.0.3/src/jse/lua2java.java @@ -0,0 +1,213 @@ +/******************************************************************************* +* Copyright (c) 2010 Luaj.org. 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. +******************************************************************************/ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + +import org.luaj.vm2.Lua; +import org.luaj.vm2.ast.Chunk; +import org.luaj.vm2.lib.jse.JsePlatform; +import org.luaj.vm2.lua2java.JavaCodeGen; +import org.luaj.vm2.parser.LuaParser; + +/** + * Compile lua sources into java sources. + */ +public class lua2java { + private static final String version = Lua._VERSION + "Copyright (C) 2010 luaj.org"; + + private static final String usage = + "usage: java -cp luaj-jse.jar lua2java [options] fileordir [, fileordir ...]\n" + + "Available options are:\n" + + " - process stdin\n" + + " -s src source directory\n" + + " -d dir destination directory\n" + + " -p pkg package prefix to apply to all classes\n" + + " -e enc override default character encoding\n" + + " -r recursively compile all\n" + + " -v verbose\n"; + + private static void usageExit() { + System.out.println(usage); + System.exit(-1); + } + + private String srcdir = null; + private String destdir = null; + private String pkgprefix = null; + private String encoding = "ISO8859-1"; + private boolean recurse = false; + private boolean verbose = false; + private List files = new ArrayList(); + + public static void main( String[] args ) throws IOException { + new lua2java( args ); + } + + private lua2java( String[] args ) throws IOException { + + // process args + try { + List seeds = new ArrayList (); + + // get stateful args + for ( int i=0; i= args.length ) + usageExit(); + srcdir = args[i]; + break; + case 'd': + if ( ++i >= args.length ) + usageExit(); + destdir = args[i]; + break; + case 'p': + if ( ++i >= args.length ) + usageExit(); + pkgprefix = args[i]; + break; + case 'e': + if ( ++i >= args.length ) + usageExit(); + encoding = args[i]; + break; + case 'r': + recurse = true; + break; + case 'v': + verbose = true; + break; + default: + usageExit(); + break; + } + } + } + + // echo version + if ( verbose ) { + System.out.println(version); + System.out.println("srcdir: "+srcdir); + System.out.println("destdir: "+destdir); + System.out.println("files: "+seeds); + System.out.println("encoding: "+encoding); + System.out.println("recurse: "+recurse); + } + + // need at least one seed + if ( seeds.size() <= 0 ) { + System.err.println(usage); + System.exit(-1); + } + + // collect up files to process + for ( int i=0; i number format 'n', (n=0,1 or 4, default="+DumpState.NUMBER_FORMAT_DEFAULT+")\n" + + " -v show version information\n" + + " -- stop handling options\n"; + + private static void usageExit() { + System.out.println(usage); + System.exit(-1); + } + + private boolean list = false; + private String output = "luac.out"; + private boolean parseonly = false; + private boolean stripdebug = false; + private boolean littleendian = false; + private int numberformat = DumpState.NUMBER_FORMAT_DEFAULT; + private boolean versioninfo = false; + private boolean processing = true; + + public static void main( String[] args ) throws IOException { + new luac( args ); + } + + private luac( String[] args ) throws IOException { + + // process args + try { + // get stateful args + for ( int i=0; i= args.length ) + usageExit(); + output = args[i]; + break; + case 'p': + parseonly = true; + break; + case 's': + stripdebug = true; + break; + case 'e': + littleendian = true; + break; + case 'i': + if ( args[i].length() <= 2 ) + usageExit(); + numberformat = Integer.parseInt(args[i].substring(2)); + break; + case 'v': + versioninfo = true; + break; + case '-': + if ( args[i].length() > 2 ) + usageExit(); + processing = false; + break; + default: + usageExit(); + break; + } + } + } + + // echo version + if ( versioninfo ) + System.out.println(version); + + // open output file + OutputStream fos = new FileOutputStream( output ); + + // process input files + try { + JsePlatform.standardGlobals(); + processing = true; + for ( int i=0; i= args.length ) + usageExit(); + srcdir = args[i]; + break; + case 'd': + if ( ++i >= args.length ) + usageExit(); + destdir = args[i]; + break; + case 'l': + loadclasses = true; + break; + case 'p': + if ( ++i >= args.length ) + usageExit(); + pkgprefix = args[i]; + break; + case 'r': + recurse = true; + break; + case 'v': + verbose = true; + break; + default: + usageExit(); + break; + } + } + } + + // echo version + if ( verbose ) { + System.out.println(version); + System.out.println("srcdir: "+srcdir); + System.out.println("destdir: "+srcdir); + System.out.println("files: "+seeds); + System.out.println("recurse: "+recurse); + } + + // need at least one seed + if ( seeds.size() <= 0 ) { + System.err.println(usage); + System.exit(-1); + } + + // collect up files to process + for ( int i=0; i stats = new ArrayList(); + public NameScope scope; + + public void add(Stat s) { + if ( s == null ) + return; + stats.add(s); + } + + public void accept(Visitor visitor) { + visitor.visit(this); + } +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Chunk.java b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Chunk.java new file mode 100644 index 0000000000..1167e96234 --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Chunk.java @@ -0,0 +1,34 @@ +/******************************************************************************* +* Copyright (c) 2010 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.ast; + +public class Chunk { + public final Block block; + + public Chunk(Block b) { + this.block = b; + } + + public void accept( Visitor visitor ) { + visitor.visit( this ); + } +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Exp.java b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Exp.java new file mode 100644 index 0000000000..beb3069c7c --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Exp.java @@ -0,0 +1,313 @@ +/******************************************************************************* +* Copyright (c) 2010 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.ast; + +import org.luaj.vm2.Lua; +import org.luaj.vm2.LuaValue; + +abstract +public class Exp { + abstract public void accept(Visitor visitor); + + public static Exp constant(LuaValue value) { + return new Constant(value); + } + + public static Exp numberconstant(String token) { + return new Constant( LuaValue.valueOf(token).tonumber() ); + } + + public static Exp varargs() { + return new VarargsExp(); + } + + public static Exp tableconstructor(TableConstructor tc) { + return tc; + } + + public static Exp unaryexp(int op, Exp rhs) { + if ( rhs instanceof BinopExp ) { + BinopExp b = (BinopExp) rhs; + if ( precedence(op) > precedence(b.op) ) + return binaryexp( unaryexp(op, b.lhs), b.op, b.rhs ); + } + return new UnopExp(op, rhs); + } + + public static Exp binaryexp(Exp lhs, int op, Exp rhs) { + if ( lhs instanceof UnopExp ) { + UnopExp u = (UnopExp) lhs; + if ( precedence(op) > precedence(u.op) ) + return unaryexp( u.op, binaryexp( u.rhs, op, rhs ) ); + } + // TODO: cumulate string concatenations together + // TODO: constant folding + if ( lhs instanceof BinopExp ) { + BinopExp b = (BinopExp) lhs; + if ( (precedence(op) > precedence(b.op)) || + ((precedence(op) == precedence(b.op)) && isrightassoc(op)) ) + return binaryexp( b.lhs, b.op, binaryexp( b.rhs, op, rhs ) ); + } + if ( rhs instanceof BinopExp ) { + BinopExp b = (BinopExp) rhs; + if ( (precedence(op) > precedence(b.op)) || + ((precedence(op) == precedence(b.op)) && ! isrightassoc(op)) ) + return binaryexp( binaryexp( lhs, op, b.lhs ), b.op, b.rhs ); + } + return new BinopExp(lhs, op, rhs); + } + + static boolean isrightassoc(int op) { + switch ( op ) { + case Lua.OP_CONCAT: + case Lua.OP_POW: return true; + default: return false; + } + } + + static int precedence(int op) { + switch ( op ) { + case Lua.OP_OR: return 0; + case Lua.OP_AND: return 1; + case Lua.OP_LT: case Lua.OP_GT: case Lua.OP_LE: case Lua.OP_GE: case Lua.OP_NEQ: case Lua.OP_EQ: return 2; + case Lua.OP_CONCAT: return 3; + case Lua.OP_ADD: case Lua.OP_SUB: return 4; + case Lua.OP_MUL: case Lua.OP_DIV: case Lua.OP_MOD: return 5; + case Lua.OP_NOT: case Lua.OP_UNM: case Lua.OP_LEN: return 6; + case Lua.OP_POW: return 7; + default: throw new IllegalStateException("precedence of bad op "+op); + } + } + + public static Exp anonymousfunction(FuncBody funcbody) { + return new AnonFuncDef(funcbody); + } + + /** foo */ + public static NameExp nameprefix(String name) { + return new NameExp(name); + } + + /** ( foo.bar ) */ + public static ParensExp parensprefix(Exp exp) { + return new ParensExp(exp); + } + + /** foo[exp] */ + public static IndexExp indexop(PrimaryExp lhs, Exp exp) { + return new IndexExp(lhs, exp); + } + + /** foo.bar */ + public static FieldExp fieldop(PrimaryExp lhs, String name) { + return new FieldExp(lhs, name); + } + + /** foo(2,3) */ + public static FuncCall functionop(PrimaryExp lhs, FuncArgs args) { + return new FuncCall(lhs, args); + } + + /** foo:bar(4,5) */ + public static MethodCall methodop(PrimaryExp lhs, String name, FuncArgs args) { + return new MethodCall(lhs, name, args); + } + + public boolean isvarexp() { + return false; + } + + public boolean isfunccall() { + return false; + } + + public boolean isvarargexp() { + return false; + } + + abstract public static class PrimaryExp extends Exp { + public boolean isvarexp() { + return false; + } + public boolean isfunccall() { + return false; + } + } + + abstract public static class VarExp extends PrimaryExp { + public boolean isvarexp() { + return true; + } + public void markHasAssignment() { + } + } + + public static class NameExp extends VarExp { + public final Name name; + public NameExp(String name) { + this.name = new Name(name); + } + public void markHasAssignment() { + name.variable.hasassignments = true; + } + public void accept(Visitor visitor) { + visitor.visit(this); + } + } + + public static class ParensExp extends PrimaryExp { + public final Exp exp; + public ParensExp(Exp exp) { + this.exp = exp; + } + + public void accept(Visitor visitor) { + visitor.visit(this); + } + } + + public static class FieldExp extends VarExp { + public final PrimaryExp lhs; + public final Name name; + public FieldExp(PrimaryExp lhs, String name) { + this.lhs = lhs; + this.name = new Name(name); + } + + public void accept(Visitor visitor) { + visitor.visit(this); + } + } + + public static class IndexExp extends VarExp { + public final PrimaryExp lhs; + public final Exp exp; + public IndexExp(PrimaryExp lhs, Exp exp) { + this.lhs = lhs; + this.exp = exp; + } + + public void accept(Visitor visitor) { + visitor.visit(this); + } + } + + public static class FuncCall extends PrimaryExp { + public final PrimaryExp lhs; + public final FuncArgs args; + + public FuncCall(PrimaryExp lhs, FuncArgs args) { + this.lhs = lhs; + this.args = args; + } + + public boolean isfunccall() { + return true; + } + + public void accept(Visitor visitor) { + visitor.visit(this); + } + + public boolean isvarargexp() { + return true; + } + } + + public static class MethodCall extends FuncCall { + public final String name; + + public MethodCall(PrimaryExp lhs, String name, FuncArgs args) { + super(lhs, args); + this.name = new String(name); + } + + public boolean isfunccall() { + return true; + } + + public void accept(Visitor visitor) { + visitor.visit(this); + } + } + + public static class Constant extends Exp { + public final LuaValue value; + public Constant(LuaValue value) { + this.value = value; + } + + public void accept(Visitor visitor) { + visitor.visit(this); + } + } + + public static class VarargsExp extends Exp { + + public void accept(Visitor visitor) { + visitor.visit(this); + } + + public boolean isvarargexp() { + return true; + } + } + + public static class UnopExp extends Exp { + public final int op; + public final Exp rhs; + public UnopExp(int op, Exp rhs) { + this.op = op; + this.rhs = rhs; + } + + public void accept(Visitor visitor) { + visitor.visit(this); + } + } + + public static class BinopExp extends Exp { + public final Exp lhs,rhs; + public final int op; + public BinopExp(Exp lhs, int op, Exp rhs) { + this.lhs = lhs; + this.op = op; + this.rhs = rhs; + } + + public void accept(Visitor visitor) { + visitor.visit(this); + } + } + + public static class AnonFuncDef extends Exp { + public final FuncBody body; + public AnonFuncDef(FuncBody funcbody) { + this.body = funcbody; + } + + public void accept(Visitor visitor) { + visitor.visit(this); + } + } + +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/ast/FuncArgs.java b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/FuncArgs.java new file mode 100644 index 0000000000..8188e8039c --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/FuncArgs.java @@ -0,0 +1,66 @@ +/******************************************************************************* +* Copyright (c) 2010 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.ast; + +import java.util.ArrayList; +import java.util.List; + +import org.luaj.vm2.LuaString; + +public class FuncArgs { + + public final List exps; + + /** exp1,exp2... */ + public static FuncArgs explist(List explist) { + return new FuncArgs(explist); + } + + /** {...} */ + public static FuncArgs tableconstructor(TableConstructor table) { + return new FuncArgs(table); + } + + /** "mylib" */ + public static FuncArgs string(LuaString string) { + return new FuncArgs(string); + } + + public FuncArgs(List exps) { + this.exps = exps; + } + + public FuncArgs(LuaString string) { + this.exps = new ArrayList(); + this.exps.add( Exp.constant(string) ); + } + + public FuncArgs(TableConstructor table) { + this.exps = new ArrayList(); + this.exps.add( table ); + } + + public void accept(Visitor visitor) { + visitor.visit(this); + } + +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/ast/FuncBody.java b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/FuncBody.java new file mode 100644 index 0000000000..74cb72814b --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/FuncBody.java @@ -0,0 +1,36 @@ +/******************************************************************************* +* Copyright (c) 2010 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.ast; + +public class FuncBody { + public ParList parlist; + public Block block; + public NameScope scope; + + public FuncBody(ParList parlist, Block block) { + this.parlist = parlist!=null? parlist: ParList.EMPTY_PARLIST; + this.block = block; + } + public void accept(Visitor visitor) { + visitor.visit(this); + } +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/ast/FuncName.java b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/FuncName.java new file mode 100644 index 0000000000..79b334cab5 --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/FuncName.java @@ -0,0 +1,49 @@ +/******************************************************************************* +* Copyright (c) 2010 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.ast; + +import java.util.ArrayList; +import java.util.List; + +public class FuncName { + // example: a.b.c.d:e + + // initial base name: "a" + public final Name name; + + // intermediate field accesses: "b", "c", "d" + public List dots; + + // optional final method name: "e" + public String method; + + public FuncName( String name ) { + this.name = new Name(name); + } + + public void adddot(String dot) { + if ( dots == null ) + dots = new ArrayList(); + dots.add(dot); + } + +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Name.java b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Name.java new file mode 100644 index 0000000000..11b4acc247 --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Name.java @@ -0,0 +1,31 @@ +/******************************************************************************* +* Copyright (c) 2010 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.ast; + + +public class Name { + public final String name; + public Variable variable; + public Name(String name) { + this.name = name; + } +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/ast/NameResolver.java b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/NameResolver.java new file mode 100644 index 0000000000..73ea1edec4 --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/NameResolver.java @@ -0,0 +1,127 @@ +package org.luaj.vm2.ast; + +import java.util.List; + +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.ast.Exp.Constant; +import org.luaj.vm2.ast.Exp.NameExp; +import org.luaj.vm2.ast.Exp.VarExp; +import org.luaj.vm2.ast.Stat.Assign; +import org.luaj.vm2.ast.Stat.FuncDef; +import org.luaj.vm2.ast.Stat.GenericFor; +import org.luaj.vm2.ast.Stat.LocalAssign; +import org.luaj.vm2.ast.Stat.LocalFuncDef; +import org.luaj.vm2.ast.Stat.NumericFor; + +/** + * Visitor that resolves names to scopes. + * Each Name is resolved to a NamedVarible, possibly in a NameScope + * if it is a local, or in no named scope if it is a global. + */ +public class NameResolver extends Visitor { + + private NameScope scope = null; + + private void pushScope() { + scope = new NameScope(scope); + } + private void popScope() { + scope = scope.outerScope; + } + + public void visit(NameScope scope) { + } + + public void visit(Block block) { + pushScope(); + block.scope = scope; + super.visit(block); + popScope(); + } + + public void visit(FuncBody body) { + pushScope(); + scope.functionNestingCount++; + body.scope = scope; + super.visit(body); + popScope(); + } + + public void visit(LocalFuncDef stat) { + defineLocalVar(stat.name); + super.visit(stat); + } + + public void visit(NumericFor stat) { + pushScope(); + stat.scope = scope; + defineLocalVar(stat.name); + super.visit(stat); + popScope(); + } + + public void visit(GenericFor stat) { + pushScope(); + stat.scope = scope; + defineLocalVars( stat.names ); + super.visit(stat); + popScope(); + } + + public void visit(NameExp exp) { + exp.name.variable = resolveNameReference(exp.name); + super.visit(exp); + } + + public void visit(FuncDef stat) { + stat.name.name.variable = resolveNameReference(stat.name.name); + stat.name.name.variable.hasassignments = true; + super.visit(stat); + } + + public void visit(Assign stat) { + super.visit(stat); + for ( int i=0, n=stat.vars.size(); i0 && m names) { + for ( int i=0, n=names.size(); i LUA_KEYWORDS = new HashSet(); + + static { + String[] k = new String[] { + "and", "break", "do", "else", "elseif", "end", + "false", "for", "function", "if", "in", "local", + "nil", "not", "or", "repeat", "return", + "then", "true", "until", "while" }; + for ( int i=0; i namedVariables = new HashMap(); + + public final NameScope outerScope; + + public int functionNestingCount; + + /** Construct default names scope */ + public NameScope() { + this.outerScope = null; + this.functionNestingCount = 0; + } + + /** Construct name scope within another scope*/ + public NameScope(NameScope outerScope) { + this.outerScope = outerScope; + this.functionNestingCount = outerScope!=null? outerScope.functionNestingCount: 0; + } + + /** Look up a name. If it is a global name, then throw IllegalArgumentException. */ + public Variable find( String name ) throws IllegalArgumentException { + validateIsNotKeyword(name); + for ( NameScope n = this; n!=null; n=n.outerScope ) + if ( n.namedVariables.containsKey(name) ) + return (Variable)n.namedVariables.get(name); + Variable value = new Variable(name); + this.namedVariables.put(name, value); + return value; + } + + /** Define a name in this scope. If it is a global name, then throw IllegalArgumentException. */ + public Variable define( String name ) throws IllegalStateException, IllegalArgumentException { + validateIsNotKeyword(name); + Variable value = new Variable(name, this); + this.namedVariables.put(name, value); + return value; + } + + private void validateIsNotKeyword(String name) { + if ( LUA_KEYWORDS.contains(name) ) + throw new IllegalArgumentException("name is a keyword: '"+name+"'"); + } +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/ast/ParList.java b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/ParList.java new file mode 100644 index 0000000000..8801f2a617 --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/ParList.java @@ -0,0 +1,42 @@ +/******************************************************************************* +* Copyright (c) 2010 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.ast; + +import java.util.ArrayList; +import java.util.List; + +public class ParList { + public static final List EMPTY_NAMELIST = new ArrayList(); + public static final ParList EMPTY_PARLIST = new ParList(EMPTY_NAMELIST,false); + + public final List names; + public final boolean isvararg; + + public ParList(List names, boolean isvararg) { + this.names = names; + this.isvararg = isvararg; + } + + public void accept(Visitor visitor) { + visitor.visit(this); + } +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Stat.java b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Stat.java new file mode 100644 index 0000000000..6d7e3163ba --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Stat.java @@ -0,0 +1,250 @@ +/******************************************************************************* +* Copyright (c) 2010 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.ast; + +import java.util.List; + +import org.luaj.vm2.ast.Exp.VarExp; + +abstract +public class Stat { + public abstract void accept(Visitor visitor); + + public static Stat block(Block block) { + return block; + } + + public static Stat whiledo(Exp exp, Block block) { + return new WhileDo(exp, block); + } + + public static Stat repeatuntil(Block block, Exp exp) { + return new RepeatUntil(block, exp); + } + + public static Stat breakstat() { + return new Break(); + } + + public static Stat returnstat(List exps) { + return new Return(exps); + } + + public static Stat assignment(List vars, List exps) { + return new Assign(vars,exps); + } + + public static Stat functioncall(Exp.FuncCall funccall) { + return new FuncCallStat(funccall); + } + + public static Stat localfunctiondef(String name, FuncBody funcbody) { + return new LocalFuncDef(name, funcbody); + } + + public static Stat fornumeric(String name, Exp initial, Exp limit, Exp step, Block block) { + return new NumericFor(name, initial, limit, step, block); + } + + public static Stat functiondef(FuncName funcname, FuncBody funcbody) { + return new FuncDef( funcname, funcbody ); + } + + public static Stat forgeneric(List names, List exps, Block block) { + return new GenericFor(names, exps, block); + } + + public static Stat localassignment(List names, List values) { + return new LocalAssign(names, values); + } + + public static Stat ifthenelse(Exp ifexp, Block ifblock, List elseifexps, List elseifblocks, Block elseblock) { + return new IfThenElse(ifexp, ifblock, elseifexps, elseifblocks, elseblock); + } + + public static class Assign extends Stat { + public final List vars; + public final List exps; + + public Assign(List vars, List exps) { + this.vars = vars; + this.exps = exps; + } + + public void accept(Visitor visitor) { + visitor.visit(this); + } + + } + + public static class WhileDo extends Stat { + public final Exp exp; + public final Block block; + public WhileDo( Exp exp, Block block ) { + this.exp = exp; + this.block = block; + } + public void accept(Visitor visitor) { + visitor.visit( this ); + } + } + + public static class RepeatUntil extends Stat { + public final Block block; + public final Exp exp; + public RepeatUntil( Block block, Exp exp ) { + this.block = block; + this.exp = exp; + } + public void accept(Visitor visitor) { + visitor.visit( this ); + } + } + + public static class Break extends Stat { + public void accept(Visitor visitor) { + visitor.visit( this ); + } + } + + public static class Return extends Stat { + public final List values; + public Return(List values) { + this.values = values; + } + + public void accept(Visitor visitor) { + visitor.visit( this ); + } + + public int nreturns() { + int n = values!=null? values.size(): 0; + if ( n>0 && ((Exp)values.get(n-1)).isvarargexp() ) + n = -1; + return n; + } + } + + public static class FuncCallStat extends Stat { + public final Exp.FuncCall funccall; + public FuncCallStat(Exp.FuncCall funccall) { + this.funccall = funccall; + } + + public void accept(Visitor visitor) { + visitor.visit( this ); + } + } + + public static class LocalFuncDef extends Stat { + public final Name name; + public final FuncBody body; + public LocalFuncDef(String name, FuncBody body) { + this.name = new Name(name); + this.body = body; + } + + public void accept(Visitor visitor) { + visitor.visit( this ); + } + } + + public static class FuncDef extends Stat { + public final FuncName name; + public final FuncBody body; + public FuncDef(FuncName name, FuncBody body) { + this.name = name; + this.body = body; + } + + public void accept(Visitor visitor) { + visitor.visit( this ); + } + } + + public static class GenericFor extends Stat { + public List names; + public List exps; + public Block block; + public NameScope scope; + public GenericFor(List names, List exps, Block block) { + this.names = names; + this.exps = exps; + this.block = block; + } + + public void accept(Visitor visitor) { + visitor.visit( this ); + } + } + + public static class NumericFor extends Stat { + public final Name name; + public final Exp initial,limit,step; + public final Block block; + public NameScope scope; + public NumericFor(String name, Exp initial, Exp limit, Exp step, Block block) { + this.name = new Name(name); + this.initial = initial; + this.limit = limit; + this.step = step; + this.block = block; + } + + public void accept(Visitor visitor) { + visitor.visit( this ); + } + } + + public static class LocalAssign extends Stat { + public final List names; + public final List values; + public LocalAssign(List names, List values) { + this.names = names; + this.values = values; + } + + public void accept(Visitor visitor) { + visitor.visit( this ); + } + } + + public static class IfThenElse extends Stat { + public final Exp ifexp; + public final Block ifblock; + public final List elseifexps; + public final List elseifblocks; + public final Block elseblock; + public IfThenElse(Exp ifexp, Block ifblock, List elseifexps, + List elseifblocks, Block elseblock) { + this.ifexp = ifexp; + this.ifblock = ifblock; + this.elseifexps = elseifexps; + this.elseifblocks = elseifblocks; + this.elseblock = elseblock; + } + + public void accept(Visitor visitor) { + visitor.visit( this ); + } + } +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Str.java b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Str.java new file mode 100644 index 0000000000..38f3e5abdd --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Str.java @@ -0,0 +1,93 @@ +/******************************************************************************* +* Copyright (c) 2010 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.ast; + +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; + +import org.luaj.vm2.LuaString; + +public class Str { + + private Str() {} + + public static LuaString quoteString(String image) { + String s = image.substring(1, image.length()-1); + byte[] bytes = unquote(s); + return LuaString.valueOf(bytes); + } + + public static LuaString charString(String image) { + String s = image.substring(1, image.length()-1); + byte[] bytes = unquote(s); + return LuaString.valueOf(bytes); + } + + public static LuaString longString(String image) { + int i = image.indexOf('[', image.indexOf('[')+1)+1; + String s = image.substring(i,image.length()-i); + byte[] b = iso88591bytes(s); + return LuaString.valueOf(b); + } + + public static byte[] iso88591bytes( String s ) { + try { + return s.getBytes("ISO8859-1"); + } catch (UnsupportedEncodingException e) { + throw new IllegalStateException("ISO8859-1 not supported"); + } + } + + public static byte[] unquote(String s) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + char[] c = s.toCharArray(); + int n = c.length; + for ( int i=0; i='0' && c[i]<='9'; i++, j++ ) + d = d * 10 + (int) (c[i]-'0'); + baos.write( (byte) d ); + --i; + continue; + case 'a': baos.write( (byte) 7 ); continue; + case 'b': baos.write( (byte) '\b' ); continue; + case 'f': baos.write( (byte) '\f' ); continue; + case 'n': baos.write( (byte) '\n' ); continue; + case 'r': baos.write( (byte) '\r' ); continue; + case 't': baos.write( (byte) '\t' ); continue; + case 'v': baos.write( (byte) 11 ); continue; + case '"': baos.write( (byte) '"' ); continue; + case '\'': baos.write( (byte) '\'' ); continue; + case '\\': baos.write( (byte) '\\' ); continue; + default: baos.write( (byte) c[i] ); break; + } + } else { + baos.write( (byte) c[i] ); + } + } + return baos.toByteArray(); + } +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/ast/TableConstructor.java b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/TableConstructor.java new file mode 100644 index 0000000000..69fd480b71 --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/TableConstructor.java @@ -0,0 +1,32 @@ +/******************************************************************************* +* Copyright (c) 2010 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.ast; + +import java.util.List; + +public class TableConstructor extends Exp { + public List fields; + + public void accept(Visitor visitor) { + visitor.visit(this); + } +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/ast/TableField.java b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/TableField.java new file mode 100644 index 0000000000..7056bac542 --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/TableField.java @@ -0,0 +1,51 @@ +/******************************************************************************* +* Copyright (c) 2010 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.ast; + +public class TableField { + + public final Exp index; + public final String name; + public final Exp rhs; + + public TableField(Exp index, String name, Exp rhs) { + this.index = index; + this.name = name; + this.rhs = rhs; + } + + public static TableField keyedField(Exp index, Exp rhs) { + return new TableField(index, null, rhs); + } + + public static TableField namedField(String name, Exp rhs) { + return new TableField(null, name, rhs); + } + + public static TableField listField(Exp rhs) { + return new TableField(null, null, rhs); + } + + public void accept(Visitor visitor) { + visitor.visit(this); + } +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Variable.java b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Variable.java new file mode 100644 index 0000000000..7405be4203 --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Variable.java @@ -0,0 +1,62 @@ +/******************************************************************************* +* Copyright (c) 2010 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.ast; + +import org.luaj.vm2.LuaValue; + +/** Variable is created lua name scopes, and is a named, lua variable that + * either refers to a lua local, global, or upvalue storage location. + */ +public class Variable { + + /** The name as it appears in lua source code */ + public final String name; + + /** The lua scope in which this variable is defined. */ + public final NameScope definingScope; + + /** true if this variable is an upvalue */ + public boolean isupvalue; + + /** true if there are assignments made to this variable */ + public boolean hasassignments; + + /** When hasassignments == false, and the initial value is a constant, this is the initial value */ + public LuaValue initialValue; + + /** Global is named variable not associated with a defining scope */ + public Variable(String name) { + this.name = name; + this.definingScope = null; + } + public Variable(String name, NameScope definingScope) { + /** Local variable is defined in a particular scope. */ + this.name = name; + this.definingScope = definingScope; + } + public boolean isLocal() { + return this.definingScope != null; + } + public boolean isConstant() { + return ! hasassignments && initialValue != null; + } +} \ No newline at end of file diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Visitor.java b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Visitor.java new file mode 100644 index 0000000000..8687a624bc --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/ast/Visitor.java @@ -0,0 +1,176 @@ +/******************************************************************************* +* Copyright (c) 2010 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.ast; + +import java.util.List; + +import org.luaj.vm2.ast.Exp.VarExp; + +abstract public class Visitor { + public void visit(Chunk chunk) { + chunk.block.accept(this); + }; + public void visit(Block block) { + visit(block.scope); + if ( block.stats != null ) + for ( int i=0, n=block.stats.size(); i vars) { + if ( vars != null ) + for ( int i=0, n=vars.size(); i exps) { + if ( exps != null ) + for ( int i=0, n=exps.size(); i names) { + if ( names != null ) + for ( int i=0, n=names.size(); i + * This class is primarily used by the {@link LuajavaLib}, + * but can also be used directly when working with Java/lua bindings. + *

+ * To coerce scalar types, the various, generally the {@code valueOf(type)} methods + * on {@link LuaValue} may be used: + *

    + *
  • {@link LuaValue#valueOf(boolean)}
  • + *
  • {@link LuaValue#valueOf(byte[])}
  • + *
  • {@link LuaValue#valueOf(double)}
  • + *
  • {@link LuaValue#valueOf(int)}
  • + *
  • {@link LuaValue#valueOf(String)}
  • + *
+ *

+ * To coerce arrays of objects and lists, the {@code listOf(..)} and {@code tableOf(...)} methods + * on {@link LuaValue} may be used: + *

    + *
  • {@link LuaValue#listOf(LuaValue[])}
  • + *
  • {@link LuaValue#listOf(LuaValue[], org.luaj.vm2.Varargs)}
  • + *
  • {@link LuaValue#tableOf(LuaValue[])}
  • + *
  • {@link LuaValue#tableOf(LuaValue[], LuaValue[], org.luaj.vm2.Varargs)}
  • + *
+ * The method {@link CoerceJavaToLua#coerce(Object)} looks as the type and dimesioning + * of the argument and tries to guess the best fit for corrsponding lua scalar, + * table, or table of tables. + * + * @see CoerceJavaToLua#coerce(Object) + * @see LuajavaLib + */ +public class CoerceJavaToLua { + + static interface Coercion { + public LuaValue coerce( Object javaValue ); + }; + + static final Map COERCIONS = new HashMap(); + + static { + Coercion boolCoercion = new Coercion() { + public LuaValue coerce( Object javaValue ) { + Boolean b = (Boolean) javaValue; + return b.booleanValue()? LuaValue.TRUE: LuaValue.FALSE; + } + } ; + Coercion intCoercion = new Coercion() { + public LuaValue coerce( Object javaValue ) { + Number n = (Number) javaValue; + return LuaInteger.valueOf( n.intValue() ); + } + } ; + Coercion charCoercion = new Coercion() { + public LuaValue coerce( Object javaValue ) { + Character c = (Character) javaValue; + return LuaInteger.valueOf( c.charValue() ); + } + } ; + Coercion doubleCoercion = new Coercion() { + public LuaValue coerce( Object javaValue ) { + Number n = (Number) javaValue; + return LuaDouble.valueOf( n.doubleValue() ); + } + } ; + Coercion stringCoercion = new Coercion() { + public LuaValue coerce( Object javaValue ) { + return LuaString.valueOf( javaValue.toString() ); + } + } ; + COERCIONS.put( Boolean.class, boolCoercion ); + COERCIONS.put( Byte.class, intCoercion ); + COERCIONS.put( Character.class, charCoercion ); + COERCIONS.put( Short.class, intCoercion ); + COERCIONS.put( Integer.class, intCoercion ); + COERCIONS.put( Long.class, doubleCoercion ); + COERCIONS.put( Float.class, doubleCoercion ); + COERCIONS.put( Double.class, doubleCoercion ); + COERCIONS.put( String.class, stringCoercion ); + } + + /** + * Coerse a Java object to a corresponding lua value. + *

+ * Integral types {@code boolean}, {@code byte}, {@code char}, and {@code int} + * will become {@link LuaInteger}; + * {@code long}, {@code float}, and {@code double} will become {@link LuaDouble}; + * {@code String} and {@code byte[]} will become {@link LuaString}; + * other types will become {@link LuaUserdata}. + * @param o Java object needing conversion + * @return {@link LuaValue} corresponding to the supplied Java value. + * @see LuaValue + * @see LuaInteger + * @see LuaDouble + * @see LuaString + * @see LuaUserdata + */ + public static LuaValue coerce(Object o) { + if ( o == null ) + return LuaValue.NIL; + Class clazz = o.getClass(); + Coercion c = (Coercion) COERCIONS.get( clazz ); + if ( c == null ) { + c = o instanceof Class? JavaClass.forClass((Class)o): + clazz.isArray()? arrayCoercion: + instanceCoercion; + COERCIONS.put( clazz, c ); + } + return c.coerce(o); + } + + static final Coercion instanceCoercion = new Coercion() { + public LuaValue coerce(Object javaValue) { + return new JavaInstance(javaValue); + } + }; + + // should be userdata? + static final Coercion arrayCoercion = new Coercion() { + public LuaValue coerce(Object javaValue) { + return new JavaArray(javaValue); + } + }; +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/CoerceLuaToJava.java b/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/CoerceLuaToJava.java new file mode 100644 index 0000000000..7191162ecb --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/CoerceLuaToJava.java @@ -0,0 +1,367 @@ +/******************************************************************************* +* Copyright (c) 2009-2011 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.lib.jse; + +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.luaj.vm2.LuaError; +import org.luaj.vm2.LuaString; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; + +/** + * Helper class to coerce values from lua to Java within the luajava library. + *

+ * This class is primarily used by the {@link LuajavaLib}, + * but can also be used directly when working with Java/lua bindings. + *

+ * To coerce to specific Java values, generally the {@code toType()} methods + * on {@link LuaValue} may be used: + *

    + *
  • {@link LuaValue#toboolean()}
  • + *
  • {@link LuaValue#tobyte()}
  • + *
  • {@link LuaValue#tochar()}
  • + *
  • {@link LuaValue#toshort()}
  • + *
  • {@link LuaValue#toint()}
  • + *
  • {@link LuaValue#tofloat()}
  • + *
  • {@link LuaValue#todouble()}
  • + *
  • {@link LuaValue#tojstring()}
  • + *
  • {@link LuaValue#touserdata()}
  • + *
  • {@link LuaValue#touserdata(Class)}
  • + *
+ *

+ * For data in lua tables, the various methods on {@link LuaTable} can be used directly + * to convert data to something more useful. + * + * @see LuajavaLib + * @see CoerceJavaToLua + */ +public class CoerceLuaToJava { + + static int SCORE_NULL_VALUE = 0x10; + static int SCORE_WRONG_TYPE = 0x100; + static int SCORE_UNCOERCIBLE = 0x10000; + + static interface Coercion { + public int score( LuaValue value ); + public Object coerce( LuaValue value ); + }; + + /** + * Coerce a LuaValue value to a specified java class + * @param value LuaValue to coerce + * @param clazz Class to coerce into + * @return Object of type clazz (or a subclass) with the corresponding value. + */ + public static Object coerce(LuaValue value, Class clazz) { + return getCoercion(clazz).coerce(value); + } + + static final Map COERCIONS = Collections.synchronizedMap(new HashMap()); + + static final class BoolCoercion implements Coercion { + public String toString() { + return "BoolCoercion()"; + } + public int score( LuaValue value ) { + switch ( value.type() ) { + case LuaValue.TBOOLEAN: + return 0; + } + return 1; + } + + public Object coerce(LuaValue value) { + return value.toboolean()? Boolean.TRUE: Boolean.FALSE; + } + } + + static final class NumericCoercion implements Coercion { + static final int TARGET_TYPE_BYTE = 0; + static final int TARGET_TYPE_CHAR = 1; + static final int TARGET_TYPE_SHORT = 2; + static final int TARGET_TYPE_INT = 3; + static final int TARGET_TYPE_LONG = 4; + static final int TARGET_TYPE_FLOAT = 5; + static final int TARGET_TYPE_DOUBLE = 6; + static final String[] TYPE_NAMES = { "byte", "char", "short", "int", "long", "float", "double" }; + final int targetType; + public String toString() { + return "NumericCoercion("+TYPE_NAMES[targetType]+")"; + } + NumericCoercion(int targetType) { + this.targetType = targetType; + } + public int score( LuaValue value ) { + if ( value.isint() ) { + switch ( targetType ) { + case TARGET_TYPE_BYTE: { + int i = value.toint(); + return (i==(byte)i)? 0: SCORE_WRONG_TYPE; + } + case TARGET_TYPE_CHAR: { + int i = value.toint(); + return (i==(byte)i)? 1: (i==(char)i)? 0: SCORE_WRONG_TYPE; + } + case TARGET_TYPE_SHORT: { + int i = value.toint(); + return (i==(byte)i)? 1: (i==(short)i)? 0: SCORE_WRONG_TYPE; + } + case TARGET_TYPE_INT: { + int i = value.toint(); + return (i==(byte)i)? 2: ((i==(char)i) || (i==(short)i))? 1: 0; + } + case TARGET_TYPE_FLOAT: return 1; + case TARGET_TYPE_LONG: return 1; + case TARGET_TYPE_DOUBLE: return 2; + default: return SCORE_WRONG_TYPE; + } + } else if ( value.isnumber() ) { + switch ( targetType ) { + case TARGET_TYPE_BYTE: return SCORE_WRONG_TYPE; + case TARGET_TYPE_CHAR: return SCORE_WRONG_TYPE; + case TARGET_TYPE_SHORT: return SCORE_WRONG_TYPE; + case TARGET_TYPE_INT: return SCORE_WRONG_TYPE; + case TARGET_TYPE_LONG: { + double d = value.todouble(); + return (d==(long)d)? 0: SCORE_WRONG_TYPE; + } + case TARGET_TYPE_FLOAT: { + double d = value.todouble(); + return (d==(float)d)? 0: SCORE_WRONG_TYPE; + } + case TARGET_TYPE_DOUBLE: { + double d = value.todouble(); + return ((d==(long)d) || (d==(float)d))? 1: 0; + } + default: return SCORE_WRONG_TYPE; + } + } else { + return SCORE_UNCOERCIBLE; + } + } + + public Object coerce(LuaValue value) { + switch ( targetType ) { + case TARGET_TYPE_BYTE: return new Byte( (byte) value.toint() ); + case TARGET_TYPE_CHAR: return new Character( (char) value.toint() ); + case TARGET_TYPE_SHORT: return new Short( (short) value.toint() ); + case TARGET_TYPE_INT: return new Integer( (int) value.toint() ); + case TARGET_TYPE_LONG: return new Long( (long) value.todouble() ); + case TARGET_TYPE_FLOAT: return new Float( (float) value.todouble() ); + case TARGET_TYPE_DOUBLE: return new Double( (double) value.todouble() ); + default: return null; + } + } + } + + static final class StringCoercion implements Coercion { + public static final int TARGET_TYPE_STRING = 0; + public static final int TARGET_TYPE_BYTES = 1; + final int targetType; + public StringCoercion(int targetType) { + this.targetType = targetType; + } + public String toString() { + return "StringCoercion("+(targetType==TARGET_TYPE_STRING? "String": "byte[]")+")"; + } + public int score(LuaValue value) { + switch ( value.type() ) { + case LuaValue.TSTRING: + return value.checkstring().isValidUtf8()? + (targetType==TARGET_TYPE_STRING? 0: 1): + (targetType==TARGET_TYPE_BYTES? 0: SCORE_WRONG_TYPE); + case LuaValue.TNIL: + return SCORE_NULL_VALUE; + default: + return targetType == TARGET_TYPE_STRING? SCORE_WRONG_TYPE: SCORE_UNCOERCIBLE; + } + } + public Object coerce(LuaValue value) { + if ( value.isnil() ) + return null; + if ( targetType == TARGET_TYPE_STRING ) + return value.tojstring(); + LuaString s = value.checkstring(); + byte[] b = new byte[s.m_length]; + s.copyInto(0, b, 0, b.length); + return b; + } + } + + static final class ArrayCoercion implements Coercion { + final Class componentType; + final Coercion componentCoercion; + public ArrayCoercion(Class componentType) { + this.componentType = componentType; + this.componentCoercion = getCoercion(componentType); + } + public String toString() { + return "ArrayCoercion("+componentType.getName()+")"; + } + public int score(LuaValue value) { + switch ( value.type() ) { + case LuaValue.TTABLE: + return value.length()==0? 0: componentCoercion.score( value.get(1) ); + case LuaValue.TUSERDATA: + return inheritanceLevels( componentType, value.touserdata().getClass().getComponentType() ); + case LuaValue.TNIL: + return SCORE_NULL_VALUE; + default: + return SCORE_UNCOERCIBLE; + } + } + public Object coerce(LuaValue value) { + switch ( value.type() ) { + case LuaValue.TTABLE: { + int n = value.length(); + Object a = Array.newInstance(componentType, n); + for ( int i=0; i + * Can get elements by their integer key index, as well as the length. + *

+ * This class is not used directly. + * It is returned by calls to {@link CoerceJavaToLua#coerce(Object)} + * when an array is supplied. + * @see CoerceJavaToLua + * @see CoerceLuaToJava + */ +class JavaArray extends LuaUserdata { + + static final LuaValue LENGTH = valueOf("length"); + + JavaArray(Object instance) { + super(instance); + } + + public LuaValue get(LuaValue key) { + if ( key.equals(LENGTH) ) + return valueOf(Array.getLength(m_instance)); + if ( key.isint() ) { + int i = key.toint() - 1; + return i>=0 && i=0 && i + * Will respond to get() and set() by returning field values, or java methods. + *

+ * This class is not used directly. + * It is returned by calls to {@link CoerceJavaToLua#coerce(Object)} + * when a Class is supplied. + * @see CoerceJavaToLua + * @see CoerceLuaToJava + */ +class JavaClass extends JavaInstance implements CoerceJavaToLua.Coercion { + + static final Map classes = Collections.synchronizedMap(new HashMap()); + + static final LuaValue NEW = valueOf("new"); + + Map fields; + Map methods; + + static JavaClass forClass(Class c) { + JavaClass j = (JavaClass) classes.get(c); + if ( j == null ) + classes.put( c, j = new JavaClass(c) ); + return j; + } + + JavaClass(Class c) { + super(c); + this.jclass = this; + } + + public LuaValue coerce(Object javaValue) { + return this; + } + + Field getField(LuaValue key) { + if ( fields == null ) { + Map m = new HashMap(); + Field[] f = ((Class)m_instance).getFields(); + for ( int i=0; i + * May be called with arguments to return a JavaInstance + * created by calling the constructor. + *

+ * This class is not used directly. + * It is returned by calls to {@link JavaClass#new(LuaValue key)} + * when the value of key is "new". + * @see CoerceJavaToLua + * @see CoerceLuaToJava + */ +class JavaConstructor extends JavaMember { + + static final Map constructors = Collections.synchronizedMap(new HashMap()); + + static JavaConstructor forConstructor(Constructor c) { + JavaConstructor j = (JavaConstructor) constructors.get(c); + if ( j == null ) + constructors.put( c, j = new JavaConstructor(c) ); + return j; + } + + public static LuaValue forConstructors(JavaConstructor[] array) { + return new Overload(array); + } + + final Constructor constructor; + + private JavaConstructor(Constructor c) { + super( c.getParameterTypes(), c.getModifiers() ); + this.constructor = c; + } + + public Varargs invoke(Varargs args) { + Object[] a = convertArgs(args); + try { + return CoerceJavaToLua.coerce( constructor.newInstance(a) ); + } catch (InvocationTargetException e) { + throw new LuaError(e.getTargetException()); + } catch (Exception e) { + return LuaValue.error("coercion error "+e); + } + } + + /** + * LuaValue that represents an overloaded Java constructor. + *

+ * On invocation, will pick the best method from the list, and invoke it. + *

+ * This class is not used directly. + * It is returned by calls to calls to {@link JavaClass#get(LuaValue key)} + * when key is "new" and there is more than one public constructor. + */ + static class Overload extends VarArgFunction { + final JavaConstructor[] constructors; + public Overload(JavaConstructor[] c) { + this.constructors = c; + } + + public Varargs invoke(Varargs args) { + JavaConstructor best = null; + int score = CoerceLuaToJava.SCORE_UNCOERCIBLE; + for ( int i=0; i + * Will respond to get() and set() by returning field values or methods. + *

+ * This class is not used directly. + * It is returned by calls to {@link CoerceJavaToLua#coerce(Object)} + * when a subclass of Object is supplied. + * @see CoerceJavaToLua + * @see CoerceLuaToJava + */ +class JavaInstance extends LuaUserdata { + + JavaClass jclass; + + JavaInstance(Object instance) { + super(instance); + } + + public LuaValue get(LuaValue key) { + if ( jclass == null ) + jclass = JavaClass.forClass(m_instance.getClass()); + Field f = jclass.getField(key); + if ( f != null ) + try { + return CoerceJavaToLua.coerce(f.get(m_instance)); + } catch (Exception e) { + throw new LuaError(e); + } + LuaValue m = jclass.getMethod(key); + if ( m != null ) + return m; + return super.get(key); + } + + public void set(LuaValue key, LuaValue value) { + if ( jclass == null ) + jclass = JavaClass.forClass(m_instance.getClass()); + Field f = jclass.getField(key); + if ( f != null ) + try { + f.set(m_instance, CoerceLuaToJava.coerce(value, f.getType())); + return; + } catch (Exception e) { + throw new LuaError(e); + } + super.set(key, value); + } + +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JavaMember.java b/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JavaMember.java new file mode 100644 index 0000000000..e4e9b7ed7f --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JavaMember.java @@ -0,0 +1,84 @@ +/******************************************************************************* +* Copyright (c) 2011 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.lib.jse; + +import org.luaj.vm2.Varargs; +import org.luaj.vm2.lib.VarArgFunction; +import org.luaj.vm2.lib.jse.CoerceLuaToJava.Coercion; + +/** + * Java method or constructor. + *

+ * Primarily handles argument coercion for parameter lists including scoring of compatibility and + * java varargs handling. + *

+ * This class is not used directly. + * It is an abstract base class for {@link JavaConstructor} and {@link JavaMethod}. + * @see JavaConstructor + * @see JavaMethod + * @see CoerceJavaToLua + * @see CoerceLuaToJava + */ +abstract +class JavaMember extends VarArgFunction { + + static final int METHOD_MODIFIERS_VARARGS = 0x80; + + final Coercion[] fixedargs; + final Coercion varargs; + + protected JavaMember(Class[] params, int modifiers) { + boolean isvarargs = ((modifiers & METHOD_MODIFIERS_VARARGS) != 0); + fixedargs = new CoerceLuaToJava.Coercion[isvarargs? params.length-1: params.length]; + for ( int i=0; ifixedargs.length? CoerceLuaToJava.SCORE_WRONG_TYPE * (n-fixedargs.length): 0; + for ( int j=0; j + * Can be invoked via call(LuaValue...) and related methods. + *

+ * This class is not used directly. + * It is returned by calls to calls to {@link JavaInstance#get(LuaValue key)} + * when a method is named. + * @see CoerceJavaToLua + * @see CoerceLuaToJava + */ +class JavaMethod extends JavaMember { + + static final Map methods = Collections.synchronizedMap(new HashMap()); + + static JavaMethod forMethod(Method m) { + JavaMethod j = (JavaMethod) methods.get(m); + if ( j == null ) + methods.put( m, j = new JavaMethod(m) ); + return j; + } + + static LuaFunction forMethods(JavaMethod[] m) { + return new Overload(m); + } + + final Method method; + + private JavaMethod(Method m) { + super( m.getParameterTypes(), m.getModifiers() ); + this.method = m; + try { + if (!m.isAccessible()) + m.setAccessible(true); + } catch (SecurityException s) { + } + } + + public LuaValue call() { + return error("method cannot be called without instance"); + } + + public LuaValue call(LuaValue arg) { + return invokeMethod(arg.checkuserdata(), LuaValue.NONE); + } + + public LuaValue call(LuaValue arg1, LuaValue arg2) { + return invokeMethod(arg1.checkuserdata(), arg2); + } + + public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { + return invokeMethod(arg1.checkuserdata(), LuaValue.varargsOf(arg2, arg3)); + } + + public Varargs invoke(Varargs args) { + return invokeMethod(args.checkuserdata(1), args.subargs(2)); + } + + LuaValue invokeMethod(Object instance, Varargs args) { + Object[] a = convertArgs(args); + try { + return CoerceJavaToLua.coerce( method.invoke(instance, a) ); + } catch (InvocationTargetException e) { + throw new LuaError(e.getTargetException()); + } catch (Exception e) { + return LuaValue.error("coercion error "+e); + } + } + + /** + * LuaValue that represents an overloaded Java method. + *

+ * On invocation, will pick the best method from the list, and invoke it. + *

+ * This class is not used directly. + * It is returned by calls to calls to {@link JavaInstance#get(LuaValue key)} + * when an overloaded method is named. + */ + static class Overload extends LuaFunction { + + final JavaMethod[] methods; + + Overload(JavaMethod[] methods) { + this.methods = methods; + } + + public LuaValue call() { + return error("method cannot be called without instance"); + } + + public LuaValue call(LuaValue arg) { + return invokeBestMethod(arg.checkuserdata(), LuaValue.NONE); + } + + public LuaValue call(LuaValue arg1, LuaValue arg2) { + return invokeBestMethod(arg1.checkuserdata(), arg2); + } + + public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { + return invokeBestMethod(arg1.checkuserdata(), LuaValue.varargsOf(arg2, arg3)); + } + + public Varargs invoke(Varargs args) { + return invokeBestMethod(args.checkuserdata(1), args.subargs(2)); + } + + private LuaValue invokeBestMethod(Object instance, Varargs args) { + JavaMethod best = null; + int score = CoerceLuaToJava.SCORE_UNCOERCIBLE; + for ( int i=0; i + * Since JME has no file system by default, {@link BaseLib} implements + * {@link ResourceFinder} using {@link Class#getResource(String)}. + * The {@link JseBaseLib} implements {@link FINDER} by scanning the current directory + * first, then falling back to {@link Class#getResource(String)} if that fails. + * Otherwise, the behavior is the same as that of {@link BaseLib}. + *

+ * Typically, this library is included as part of a call to + * {@link JsePlatform#standardGlobals()} + *

+ * To instantiate and use it directly, + * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: + *

 {@code
+ * LuaTable _G = new LuaTable();
+ * LuaThread.setGlobals(_G);
+ * _G.load(new JseBaseLib());
+ * _G.get("print").call(LuaValue.valueOf("hello, world"));
+ * } 
+ * Doing so will ensure the library is properly initialized + * and loaded into the globals table. + *

+ * This is a direct port of the corresponding library in C. + * @see BaseLib + * @see ResourceFinder + * @see #FINDER + * @see LibFunction + * @see JsePlatform + * @see JmePlatform + * @see http://www.lua.org/manual/5.1/manual.html#5.1 + */ + +public class JseBaseLib extends org.luaj.vm2.lib.BaseLib { + + /** Construct a JSE base library instance */ + public JseBaseLib() { + STDIN = System.in; + } + + /** + * Try to open a file in the current working directory, + * or fall back to base opener if not found. + * + * This implementation attempts to open the file using new File(filename). + * It falls back to the base implementation that looks it up as a resource + * in the class path if not found as a plain file. + * + * @see org.luaj.vm2.lib.BaseLib + * @see org.luaj.vm2.lib.ResourceFinder + * + * @param filename + * @return InputStream, or null if not found. + */ + public InputStream findResource(String filename) { + File f = new File(filename); + if ( ! f.exists() ) + return super.findResource(filename); + try { + return new FileInputStream(f); + } catch ( IOException ioe ) { + return null; + } + } +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JseIoLib.java b/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JseIoLib.java new file mode 100644 index 0000000000..8a86ca8fa3 --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JseIoLib.java @@ -0,0 +1,222 @@ +/******************************************************************************* +* Copyright (c) 2009 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.lib.jse; + + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.RandomAccessFile; + +import org.luaj.vm2.LuaError; +import org.luaj.vm2.LuaString; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.BaseLib; +import org.luaj.vm2.lib.IoLib; +import org.luaj.vm2.lib.LibFunction; + +/** + * Subclass of {@link IoLib} and therefore {@link LibFunction} which implements the lua standard {@code io} + * library for the JSE platform. + *

+ * It uses RandomAccessFile to implement seek on files. + *

+ * Typically, this library is included as part of a call to + * {@link JsePlatform#standardGlobals()} + *

+ * To instantiate and use it directly, + * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: + *

 {@code
+ * LuaTable _G = new LuaTable();
+ * LuaThread.setGlobals(_G);
+ * _G.load(new JseBaseLib());
+ * _G.load(new PackageLib());
+ * _G.load(new JseIoLib());
+ * _G.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
+ * } 
+ * Doing so will ensure the library is properly initialized + * and loaded into the globals table. + *

+ * This has been implemented to match as closely as possible the behavior in the corresponding library in C. + * @see LibFunction + * @see JsePlatform + * @see JmePlatform + * @see IoLib + * @see JmeIoLib + * @see http://www.lua.org/manual/5.1/manual.html#5.7 + */ +public class JseIoLib extends IoLib { + + public JseIoLib() { + super(); + } + + protected File wrapStdin() throws IOException { + return new FileImpl(BaseLib.instance.STDIN); + } + + protected File wrapStdout() throws IOException { + return new FileImpl(BaseLib.instance.STDOUT); + } + + protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException { + RandomAccessFile f = new RandomAccessFile(filename,readMode? "r": "rw"); + if ( appendMode ) { + f.seek(f.length()); + } else { + if ( ! readMode ) + f.setLength(0); + } + return new FileImpl( f ); + } + + protected File openProgram(String prog, String mode) throws IOException { + final Process p = Runtime.getRuntime().exec(prog); + return "w".equals(mode)? + new FileImpl( p.getOutputStream() ): + new FileImpl( p.getInputStream() ); + } + + protected File tmpFile() throws IOException { + java.io.File f = java.io.File.createTempFile(".luaj","bin"); + f.deleteOnExit(); + return new FileImpl( new RandomAccessFile(f,"rw") ); + } + + private static void notimplemented() { + throw new LuaError("not implemented"); + } + + private final class FileImpl extends File { + private final RandomAccessFile file; + private final InputStream is; + private final OutputStream os; + private boolean closed = false; + private boolean nobuffer = false; + private FileImpl( RandomAccessFile file, InputStream is, OutputStream os ) { + this.file = file; + this.is = is!=null? is.markSupported()? is: new BufferedInputStream(is): null; + this.os = os; + } + private FileImpl( RandomAccessFile f ) { + this( f, null, null ); + } + private FileImpl( InputStream i ) { + this( null, i, null ); + } + private FileImpl( OutputStream o ) { + this( null, null, o ); + } + public String tojstring() { + return "file ("+this.hashCode()+")"; + } + public boolean isstdfile() { + return file == null; + } + public void close() throws IOException { + closed = true; + if ( file != null ) { + file.close(); + } + } + public void flush() throws IOException { + if ( os != null ) + os.flush(); + } + public void write(LuaString s) throws IOException { + if ( os != null ) + os.write( s.m_bytes, s.m_offset, s.m_length ); + else if ( file != null ) + file.write( s.m_bytes, s.m_offset, s.m_length ); + else + notimplemented(); + if ( nobuffer ) + flush(); + } + public boolean isclosed() { + return closed; + } + public int seek(String option, int pos) throws IOException { + if ( file != null ) { + if ( "set".equals(option) ) { + file.seek(pos); + } else if ( "end".equals(option) ) { + file.seek(file.length()+pos); + } else { + file.seek(file.getFilePointer()+pos); + } + return (int) file.getFilePointer(); + } + notimplemented(); + return 0; + } + public void setvbuf(String mode, int size) { + nobuffer = "no".equals(mode); + } + + // get length remaining to read + public int remaining() throws IOException { + return file!=null? (int) (file.length()-file.getFilePointer()): -1; + } + + // peek ahead one character + public int peek() throws IOException { + if ( is != null ) { + is.mark(1); + int c = is.read(); + is.reset(); + return c; + } else if ( file != null ) { + long fp = file.getFilePointer(); + int c = file.read(); + file.seek(fp); + return c; + } + notimplemented(); + return 0; + } + + // return char if read, -1 if eof, throw IOException on other exception + public int read() throws IOException { + if ( is != null ) + return is.read(); + else if ( file != null ) { + return file.read(); + } + notimplemented(); + return 0; + } + + // return number of bytes read if positive, -1 if eof, throws IOException + public int read(byte[] bytes, int offset, int length) throws IOException { + if (file!=null) { + return file.read(bytes, offset, length); + } else if (is!=null) { + return is.read(bytes, offset, length); + } else { + notimplemented(); + } + return length; + } + } +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JseMathLib.java b/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JseMathLib.java new file mode 100644 index 0000000000..1f8d2e6957 --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JseMathLib.java @@ -0,0 +1,107 @@ +/******************************************************************************* +* Copyright (c) 2009-2011 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.lib.jse; + +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.LibFunction; +import org.luaj.vm2.lib.OneArgFunction; +import org.luaj.vm2.lib.TwoArgFunction; + +/** + * Subclass of {@link LibFunction} which implements the lua standard {@code math} + * library. + *

+ * It contains all lua math functions, including those not available on the JME platform. + * See {@link org.luaj.lib.MathLib} for the exception list. + *

+ * Typically, this library is included as part of a call to + * {@link JsePlatform#standardGlobals()} + *

+ * To instantiate and use it directly, + * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: + *

 {@code
+ * LuaTable _G = new LuaTable();
+ * LuaThread.setGlobals(_G);
+ * _G.load(new JseBaseLib());
+ * _G.load(new PackageLib());
+ * _G.load(new JseMathLib());
+ * System.out.println( _G.get("math").get("sqrt").call( LuaValue.valueOf(2) ) );
+ * } 
+ * Doing so will ensure the library is properly initialized + * and loaded into the globals table. + *

+ * This has been implemented to match as closely as possible the behavior in the corresponding library in C. + * @see LibFunction + * @see JsePlatform + * @see JmePlatform + * @see JseMathLib + * @see http://www.lua.org/manual/5.1/manual.html#5.6 + */ +public class JseMathLib extends org.luaj.vm2.lib.MathLib { + + public JseMathLib() {} + + public LuaValue call(LuaValue arg) { + LuaValue t = super.call(arg); + bind( t, JseMathLib1.class, new String[] { + "acos", "asin", "atan", "cosh", + "exp", "log", "log10", "sinh", + "tanh" } ); + bind( t, JseMathLib2.class, new String[] { + "atan2", "pow", } ); + return t; + } + + public static final class JseMathLib1 extends OneArgFunction { + public LuaValue call(LuaValue arg) { + switch ( opcode ) { + case 0: return valueOf(Math.acos(arg.checkdouble())); + case 1: return valueOf(Math.asin(arg.checkdouble())); + case 2: return valueOf(Math.atan(arg.checkdouble())); + case 3: return valueOf(Math.cosh(arg.checkdouble())); + case 4: return valueOf(Math.exp(arg.checkdouble())); + case 5: return valueOf(Math.log(arg.checkdouble())); + case 6: return valueOf(Math.log10(arg.checkdouble())); + case 7: return valueOf(Math.sinh(arg.checkdouble())); + case 8: return valueOf(Math.tanh(arg.checkdouble())); + } + return NIL; + } + } + + public static final class JseMathLib2 extends TwoArgFunction { + public LuaValue call(LuaValue arg1, LuaValue arg2) { + switch ( opcode ) { + case 0: return valueOf(Math.atan2(arg1.checkdouble(), arg2.checkdouble())); + case 1: return valueOf(Math.pow(arg1.checkdouble(), arg2.checkdouble())); + } + return NIL; + } + } + + /** Faster, better version of pow() used by arithmetic operator ^ */ + public double dpow_lib(double a, double b) { + return Math.pow(a, b); + } + + +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JseOsLib.java b/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JseOsLib.java new file mode 100644 index 0000000000..9952cd1c73 --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JseOsLib.java @@ -0,0 +1,126 @@ +/******************************************************************************* +* Copyright (c) 2009 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.lib.jse; +import java.io.File; +import java.io.IOException; + +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.LibFunction; + +/** + * Subclass of {@link LibFunction} which implements the standard lua {@code os} library. + *

+ * This contains more complete implementations of the following functions + * using features that are specific to JSE: + *

    + *
  • {@code execute()}
  • + *
  • {@code remove()}
  • + *
  • {@code rename()}
  • + *
  • {@code tmpname()}
  • + *
+ *

+ * Because the nature of the {@code os} library is to encapsulate + * os-specific features, the behavior of these functions varies considerably + * from their counterparts in the C platform. + *

+ * Typically, this library is included as part of a call to either + * {@link JsePlatform#standardGlobals()} + *

+ * To instantiate and use it directly, + * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: + *

 {@code
+ * LuaTable _G = new LuaTable();
+ * LuaThread.setGlobals(_G);
+ * _G.load(new JseBaseLib());
+ * _G.load(new PackageLib());
+ * _G.load(new JseOsLib());
+ * System.out.println( _G.get("os").get("time").call() );
+ * } 
+ * Doing so will ensure the library is properly initialized + * and loaded into the globals table. + *

+ * @see LibFunction + * @see OsLib + * @see JsePlatform + * @see JmePlatform + * @see http://www.lua.org/manual/5.1/manual.html#5.8 + */ +public class JseOsLib extends org.luaj.vm2.lib.OsLib { + + /** return code indicating the execute() threw an I/O exception */ + public static int EXEC_IOEXCEPTION = 1; + + /** return code indicating the execute() was interrupted */ + public static int EXEC_INTERRUPTED = -2; + + /** return code indicating the execute() threw an unknown exception */ + public static int EXEC_ERROR = -3; + + /** public constructor */ + public JseOsLib() { + } + + protected int execute(String command) { + Runtime r = Runtime.getRuntime(); + try { + final Process p = r.exec(command); + try { + p.waitFor(); + return p.exitValue(); + } finally { + p.destroy(); + } + } catch (IOException ioe) { + return EXEC_IOEXCEPTION; + } catch (InterruptedException e) { + return EXEC_INTERRUPTED; + } catch (Throwable t) { + return EXEC_ERROR; + } + } + + protected void remove(String filename) throws IOException { + File f = new File(filename); + if ( ! f.exists() ) + throw new IOException("No such file or directory"); + if ( ! f.delete() ) + throw new IOException("Failed to delete"); + } + + protected void rename(String oldname, String newname) throws IOException { + File f = new File(oldname); + if ( ! f.exists() ) + throw new IOException("No such file or directory"); + if ( ! f.renameTo(new File(newname)) ) + throw new IOException("Failed to delete"); + } + + protected String tmpname() { + try { + java.io.File f = java.io.File.createTempFile(TMP_PREFIX ,TMP_SUFFIX); + return f.getName(); + } catch ( IOException ioe ) { + return super.tmpname(); + } + } + +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JsePlatform.java b/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JsePlatform.java new file mode 100644 index 0000000000..7008280e59 --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JsePlatform.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright (c) 2009-2011 Luaj.org. 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. + ******************************************************************************/ +package org.luaj.vm2.lib.jse; + +import org.luaj.vm2.compiler.LuaC; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaThread; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.CoroutineLib; +import org.luaj.vm2.lib.DebugLib; +import org.luaj.vm2.lib.PackageLib; +import org.luaj.vm2.lib.StringLib; +import org.luaj.vm2.lib.TableLib; + +/** The {@link JsePlatform} class is a convenience class to standardize + * how globals tables are initialized for the JSE platform. + *

+ * It is used to allocate either a set of standard globals using + * {@link #standardGlobals()} or debug globals using {@link #debugGlobals()} + *

+ * A simple example of initializing globals and using them from Java is: + *

 {@code
+ * LuaValue _G = JsePlatform.standardGlobals();
+ * _G.get("print").call(LuaValue.valueOf("hello, world"));
+ * } 
+ *

+ * Once globals are created, a simple way to load and run a script is: + *

 {@code
+ * LoadState.load( new FileInputStream("main.lua"), "main.lua", _G ).call();
+ * } 
+ *

+ * although {@code require} could also be used: + *

 {@code
+ * _G.get("require").call(LuaValue.valueOf("main"));
+ * } 
+ * For this to succeed, the file "main.lua" must be in the current directory or a resource. + * See {@link JseBaseLib} for details on finding scripts using {@link ResourceFinder}. + *

+ * The standard globals will contain all standard libraries plus {@code luajava}: + *

    + *
  • {@link JseBaseLib}
  • + *
  • {@link PackageLib}
  • + *
  • {@link TableLib}
  • + *
  • {@link StringLib}
  • + *
  • {@link CoroutineLib}
  • + *
  • {@link JseMathLib}
  • + *
  • {@link JseIoLib}
  • + *
  • {@link JseOsLib}
  • + *
  • {@link LuajavaLib}
  • + *
+ * In addition, the {@link LuaC} compiler is installed so lua files may be loaded in their source form. + *

+ * The debug globals are simply the standard globals plus the {@code debug} library {@link DebugLib}. + *

+ * The class ensures that initialization is done in the correct order, + * and that linkage is made to {@link LuaThread#setGlobals(LuaValue)}. + * @see JmePlatform + */ +public class JsePlatform { + + /** + * Create a standard set of globals for JSE including all the libraries. + * + * @return Table of globals initialized with the standard JSE libraries + * @see #debugGlobals() + * @see JsePlatform + * @see JmePlatform + */ + public static LuaTable standardGlobals() { + LuaTable _G = new LuaTable(); + _G.load(new JseBaseLib()); + _G.load(new PackageLib()); + _G.load(new TableLib()); + _G.load(new StringLib()); + _G.load(new CoroutineLib()); + _G.load(new JseMathLib()); + _G.load(new JseIoLib()); + _G.load(new JseOsLib()); + _G.load(new LuajavaLib()); + LuaThread.setGlobals(_G); + LuaC.install(); + return _G; + } + + /** Create standard globals including the {@link debug} library. + * + * @return Table of globals initialized with the standard JSE and debug libraries + * @see #standardGlobals() + * @see JsePlatform + * @see JmePlatform + * @see DebugLib + */ + public static LuaTable debugGlobals() { + LuaTable _G = standardGlobals(); + _G.load(new DebugLib()); + return _G; + } +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JseProcess.java b/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JseProcess.java new file mode 100644 index 0000000000..c24b6d587c --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/JseProcess.java @@ -0,0 +1,116 @@ +/******************************************************************************* +* Copyright (c) 2013 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.lib.jse; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** Analog of Process that pipes input and output to client-specified streams. + */ +public class JseProcess { + + final Process process; + final Thread input,output,error; + + /** Construct a process around a command, with specified streams to redirect input and output to. + * + * @param cmd The command to execute, including arguments, if any + * @param stdin Optional InputStream to read from as process input, or null if input is not needed. + * @param stdout Optional OutputStream to copy process output to, or null if output is ignored. + * @param stderr Optinoal OutputStream to copy process stderr output to, or null if output is ignored. + * @throws IOException If the system process could not be created. + * @see Process + */ + public JseProcess(String[] cmd, InputStream stdin, OutputStream stdout, OutputStream stderr) throws IOException { + this(Runtime.getRuntime().exec(cmd), stdin, stdout, stderr); + } + + /** Construct a process around a command, with specified streams to redirect input and output to. + * + * @param cmd The command to execute, including arguments, if any + * @param stdin Optional InputStream to read from as process input, or null if input is not needed. + * @param stdout Optional OutputStream to copy process output to, or null if output is ignored. + * @param stderr Optinoal OutputStream to copy process stderr output to, or null if output is ignored. + * @throws IOException If the system process could not be created. + * @see Process + */ + public JseProcess(String cmd, InputStream stdin, OutputStream stdout, OutputStream stderr) throws IOException { + this(Runtime.getRuntime().exec(cmd), stdin, stdout, stderr); + } + + private JseProcess(Process process, InputStream stdin, OutputStream stdout, OutputStream stderr) { + this.process = process; + input = stdin == null? null: copyBytes(stdin, process.getOutputStream(), null, process.getOutputStream()); + output = stdout == null? null: copyBytes(process.getInputStream(), stdout, process.getInputStream(), null); + error = stderr == null? null: copyBytes(process.getErrorStream(), stderr, process.getErrorStream(), null); + } + + /** Get the exit value of the process. */ + public int exitValue() { + return process.exitValue(); + } + + /** Wait for the process to complete, and all pending output to finish. + * @return The exit status. + * @throws InterruptedException + */ + public int waitFor() throws InterruptedException { + int r = process.waitFor(); + if (input != null) + input.join(); + if (output != null) + output.join(); + if (error != null) + error.join(); + process.destroy(); + return r; + } + + /** Create a thread to copy bytes from input to output. */ + private Thread copyBytes(final InputStream input, + final OutputStream output, final InputStream ownedInput, + final OutputStream ownedOutput) { + Thread t = (new Thread() { + public void run() { + try { + byte[] buf = new byte[1024]; + int r; + try { + while ((r = input.read(buf)) >= 0) { + output.write(buf, 0, r); + } + } finally { + if (ownedInput != null) + ownedInput.close(); + if (ownedOutput != null) + ownedOutput.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + t.start(); + return t; + } +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/LuajavaLib.java b/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/LuajavaLib.java new file mode 100644 index 0000000000..47de379260 --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/lib/jse/LuajavaLib.java @@ -0,0 +1,195 @@ +/******************************************************************************* +* Copyright (c) 2009 Luaj.org. 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. +******************************************************************************/ +package org.luaj.vm2.lib.jse; + + +import java.lang.reflect.Array; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import org.luaj.vm2.LuaError; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; +import org.luaj.vm2.compiler.LuaC; +import org.luaj.vm2.lib.LibFunction; +import org.luaj.vm2.lib.PackageLib; +import org.luaj.vm2.lib.VarArgFunction; + +/** + * Subclass of {@link LibFunction} which implements the features of the luajava package. + *

+ * Luajava is an approach to mixing lua and java using simple functions that bind + * java classes and methods to lua dynamically. The API is documented on the + * luajava documentation pages. + *

+ * Typically, this library is included as part of a call to either + * {@link JsePlatform#standardGlobals()} + *

+ * To instantiate and use it directly, + * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: + *

 {@code
+ * LuaTable _G = new LuaTable();
+ * LuaThread.setGlobals(_G);
+ * LuaC.install();
+ * _G.load(new BaseLib());
+ * _G.load(new PackageLib());
+ * _G.load(new LuajavaLib());
+ * _G.get("loadstring").call( LuaValue.valueOf( 
+ * 		"sys = luajava.bindClass('java.lang.System')\n"+
+ * 		"print ( sys:currentTimeMillis() )\n" ) ).call(); 
+ * } 
+ * This example is not intended to be realistic - only to show how the {@link LuajavaLib} + * may be initialized by hand. In practice, the {@code luajava} library is available + * on all JSE platforms via the call to {@link JsePlatform#standardGlobals()} + * and the luajava api's are simply invoked from lua. + *

+ * This has been implemented to match as closely as possible the behavior in the corresponding library in C. + * @see LibFunction + * @see org.luaj.vm2.lib.jse.JsePlatform + * @see org.luaj.vm2.lib.jme.JmePlatform + * @see LuaC + * @see http://www.keplerproject.org/luajava/manual.html#luareference + */ +public class LuajavaLib extends VarArgFunction { + + static final int INIT = 0; + static final int BINDCLASS = 1; + static final int NEWINSTANCE = 2; + static final int NEW = 3; + static final int CREATEPROXY = 4; + static final int LOADLIB = 5; + + static final String[] NAMES = { + "bindClass", + "newInstance", + "new", + "createProxy", + "loadLib", + }; + + static final int METHOD_MODIFIERS_VARARGS = 0x80; + + public LuajavaLib() { + } + + public Varargs invoke(Varargs args) { + try { + switch ( opcode ) { + case INIT: { + LuaTable t = new LuaTable(); + bind( t, LuajavaLib.class, NAMES, BINDCLASS ); + env.set("luajava", t); + PackageLib.instance.LOADED.set("luajava", t); + return t; + } + case BINDCLASS: { + final Class clazz = classForName(args.checkjstring(1)); + return JavaClass.forClass(clazz); + } + case NEWINSTANCE: + case NEW: { + // get constructor + final LuaValue c = args.checkvalue(1); + final Class clazz = (opcode==NEWINSTANCE? classForName(c.tojstring()): (Class) c.checkuserdata(Class.class)); + final Varargs consargs = args.subargs(2); + return JavaClass.forClass(clazz).getConstructor().invoke(consargs); + } + + case CREATEPROXY: { + final int niface = args.narg()-1; + if ( niface <= 0 ) + throw new LuaError("no interfaces"); + final LuaValue lobj = args.checktable(niface+1); + + // get the interfaces + final Class[] ifaces = new Class[niface]; + for ( int i=0; i constantDeclarations = new ArrayList(); + Map stringConstants = new HashMap(); + Map numberConstants = new HashMap(); + + + String indent = ""; + void addindent() { + indent+=" "; + } + void subindent() { + indent = indent.substring(3); + } + void out(String s) { + try { + writer.write(s); + } catch (IOException e) { + throw new RuntimeException("write failed: "+e, e); + } + } + void outi(String s) { + out( indent ); + out( s ); + } + void outl(String s) { + outi( s ); + out( "\n" ); + } + void outr(String s) { + out( s ); + out( "\n" ); + } + void outb(String s) { + outl( s ); + addindent(); + } + void oute(String s) { + subindent(); + outl( s ); + } + + public void visit(Chunk chunk) { + if ( packagename != null ) + outl("package "+packagename+";"); + outl("import org.luaj.vm2.*;"); + outl("import org.luaj.vm2.lib.*;"); + outb("public class "+classname+" extends VarArgFunction {"); + outl("public Varargs onInvoke(Varargs $arg) {"); + addindent(); + javascope = JavaScope.newJavaScope( chunk ); + writeBodyBlock(chunk.block); + oute("}"); + for ( int i=0, n=constantDeclarations.size(); i names = stat.names; + List values = stat.values; + int n = names.size(); + int m = values != null? values.size(): 0; + boolean isvarlist = m>0 && m values) { + int n = values!=null? values.size(): 0; + switch ( n ) { + case 0: return "NONE"; + case 1: return evalVarargs((Exp) values.get(0)); + default: + case 2: case 3: + Writer x = pushWriter(); + out( n>3? "varargsOf(new LuaValue[] {":"varargsOf(" ); + for ( int i=1; i3 ) + out( "}," ); + out( evalVarargs((Exp) values.get(n-1))+")" ); + return popWriter(x); + } + } + + Map callerExpects = new HashMap(); + + public String evalLuaValue(Exp exp) { + Writer x = pushWriter(); + callerExpects.put(exp,Integer.valueOf(1)); + exp.accept(this); + return popWriter(x); + } + + public String evalVarargs(Exp exp) { + Writer x = pushWriter(); + callerExpects.put(exp,Integer.valueOf(-1)); + exp.accept(this); + return popWriter(x); + } + + public String evalBoolean(Exp exp) { + Writer x = pushWriter(); + exp.accept(new Visitor() { + public void visit(UnopExp exp) { + switch ( exp.op ) { + case Lua.OP_NOT: + String rhs = evalBoolean( exp.rhs ); + out( "true".equals(rhs)? "false": + "false".equals(rhs)? "true": + "(!"+rhs+")"); + break; + default: out(evalLuaValue(exp)+".toboolean()"); break; + } + } + public void visit(BinopExp exp) { + switch ( exp.op ) { + case Lua.OP_AND: out("("+evalBoolean(exp.lhs)+"&&"+evalBoolean(exp.rhs)+")"); return; + case Lua.OP_OR: out("("+evalBoolean(exp.lhs)+"||"+evalBoolean(exp.rhs)+")"); return; + case Lua.OP_GT: out(evalLuaValue(exp.lhs)+".gt_b("+evalLuaValue(exp.rhs)+")"); return; + case Lua.OP_GE: out(evalLuaValue(exp.lhs)+".gteq_b("+evalLuaValue(exp.rhs)+")"); return; + case Lua.OP_LT: out(evalLuaValue(exp.lhs)+".lt_b("+evalLuaValue(exp.rhs)+")"); return; + case Lua.OP_LE: out(evalLuaValue(exp.lhs)+".lteq_b("+evalLuaValue(exp.rhs)+")"); return; + case Lua.OP_EQ: out(evalLuaValue(exp.lhs)+".eq_b("+evalLuaValue(exp.rhs)+")"); return; + case Lua.OP_NEQ: out(evalLuaValue(exp.lhs)+".neq_b("+evalLuaValue(exp.rhs)+")"); return; + default: out(evalLuaValue(exp)+".toboolean()"); return; + } + } + public void visit(Constant exp) { + switch ( exp.value.type() ) { + case LuaValue.TBOOLEAN: + out(exp.value.toboolean()? "true": "false"); + break; + default: + out(evalLuaValue(exp)+".toboolean()"); + break; + } + } + public void visit(ParensExp exp) { + out(evalBoolean(exp.exp)); + } + public void visit(VarargsExp exp) { + out(evalLuaValue(exp)+".toboolean()"); + } + public void visit(FieldExp exp) { + out(evalLuaValue(exp)+".toboolean()"); + } + public void visit(IndexExp exp) { + out(evalLuaValue(exp)+".toboolean()"); + } + public void visit(NameExp exp) { + if ( exp.name.variable.isConstant() ) { + out ( exp.name.variable.initialValue.toboolean()? "true": "false"); + return; + } + out(evalLuaValue(exp)+".toboolean()"); + } + public void visit(FuncCall exp) { + out(evalLuaValue(exp)+".toboolean()"); + } + public void visit(MethodCall exp) { + out(evalLuaValue(exp)+".toboolean()"); + } + public void visit(TableConstructor exp) { + out(evalLuaValue(exp)+".toboolean()"); + } + }); + return popWriter(x); + } + + public String evalNumber(Exp exp) { + Writer x = pushWriter(); + exp.accept(new Visitor() { + public void visit(UnopExp exp) { + switch ( exp.op ) { + case Lua.OP_LEN: out(evalLuaValue(exp.rhs)+".length()"); break; + case Lua.OP_UNM: out("(-"+evalNumber(exp.rhs)+")"); break; + default: out(evalLuaValue(exp)+".checkdouble()"); break; + } + } + public void visit(BinopExp exp) { + String op; + switch ( exp.op ) { + case Lua.OP_ADD: + case Lua.OP_SUB: + case Lua.OP_MUL: + op = (exp.op==Lua.OP_ADD? "+": exp.op==Lua.OP_SUB? "-": "*"); + out("("+evalNumber(exp.lhs)+op+evalNumber(exp.rhs)+")"); + break; + case Lua.OP_POW: out("MathLib.dpow_d("+evalNumber(exp.lhs)+","+evalNumber(exp.rhs)+")"); break; + case Lua.OP_DIV: out("LuaDouble.ddiv_d("+evalNumber(exp.lhs)+","+evalNumber(exp.rhs)+")"); break; + case Lua.OP_MOD: out("LuaDouble.dmod_d("+evalNumber(exp.lhs)+","+evalNumber(exp.rhs)+")"); break; + default: out(evalLuaValue(exp)+".checkdouble()"); break; + } + } + public void visit(Constant exp) { + switch ( exp.value.type() ) { + case LuaValue.TNUMBER: + out( evalNumberLiteral(exp.value.checkdouble()) ); + break; + default: + out(evalLuaValue(exp)+".checkdouble()"); + break; + } + } + public void visit(ParensExp exp) { + out(evalNumber(exp.exp)); + } + public void visit(VarargsExp exp) { + out(evalLuaValue(exp)+".checkdouble()"); + } + public void visit(FieldExp exp) { + out(evalLuaValue(exp)+".checkdouble()"); + } + public void visit(IndexExp exp) { + out(evalLuaValue(exp)+".checkdouble()"); + } + public void visit(NameExp exp) { + if ( exp.name.variable.isConstant() ) { + if ( exp.name.variable.initialValue.isnumber() ) { + out( evalNumberLiteral(exp.name.variable.initialValue.checkdouble()) ); + return; + } + } + out(evalLuaValue(exp)+".checkdouble()"); + } + public void visit(FuncCall exp) { + out(evalLuaValue(exp)+".checkdouble()"); + } + public void visit(MethodCall exp) { + out(evalLuaValue(exp)+".checkdouble()"); + } + public void visit(TableConstructor exp) { + out(evalLuaValue(exp)+".checkdouble()"); + } + }); + return popWriter(x); + } + + public void visit(FuncCallStat stat) { + outi(""); + stat.funccall.accept(this); + outr(";"); + } + + public void visit(BinopExp exp) { + switch ( exp.op ) { + case Lua.OP_AND: + case Lua.OP_OR: + String not = (exp.op==Lua.OP_AND? "!": ""); + out("("+not+"($b="+evalLuaValue(exp.lhs)+").toboolean()?$b:"+evalLuaValue(exp.rhs)+")"); + return; + } + switch ( exp.op ) { + case Lua.OP_ADD: out("valueOf("+evalNumber(exp.lhs)+"+"+evalNumber(exp.rhs)+")"); return; + case Lua.OP_SUB: out("valueOf("+evalNumber(exp.lhs)+"-"+evalNumber(exp.rhs)+")"); return; + case Lua.OP_MUL: out("valueOf("+evalNumber(exp.lhs)+"*"+evalNumber(exp.rhs)+")"); return; + case Lua.OP_POW: out("MathLib.dpow("+evalNumber(exp.lhs)+","+evalNumber(exp.rhs)+")"); return; + case Lua.OP_DIV: out("LuaDouble.ddiv("+evalNumber(exp.lhs)+","+evalNumber(exp.rhs)+")"); return; + case Lua.OP_MOD: out("LuaDouble.dmod("+evalNumber(exp.lhs)+","+evalNumber(exp.rhs)+")"); return; + case Lua.OP_GT: out(evalLuaValue(exp.lhs)+".gt("+evalLuaValue(exp.rhs)+")"); return; + case Lua.OP_GE: out(evalLuaValue(exp.lhs)+".gteq("+evalLuaValue(exp.rhs)+")"); return; + case Lua.OP_LT: out(evalLuaValue(exp.lhs)+".lt("+evalLuaValue(exp.rhs)+")"); return; + case Lua.OP_LE: out(evalLuaValue(exp.lhs)+".lteq("+evalLuaValue(exp.rhs)+")"); return; + case Lua.OP_EQ: out(evalLuaValue(exp.lhs)+".eq("+evalLuaValue(exp.rhs)+")"); return; + case Lua.OP_NEQ: out(evalLuaValue(exp.lhs)+".neq("+evalLuaValue(exp.rhs)+")"); return; + case Lua.OP_CONCAT: + if ( isConcatExp(exp.rhs) ) { + out( evalLuaValue(exp.lhs) ); + Exp e = exp.rhs; + String close = ""; + for ( ; isConcatExp(e); e=((BinopExp)e).rhs ) { + out( ".concat("+evalLuaValue(((BinopExp)e).lhs) ); + close += ')'; + } + out( ".concat("+evalLuaValue(e)+".buffer())" ); + out( close ); + out( ".value()" ); + } else { + out(evalLuaValue(exp.lhs)+".concat("+evalLuaValue(exp.rhs)+")"); + } + return; + default: throw new IllegalStateException("unknown bin op:"+exp.op); + } + } + + private boolean isConcatExp(Exp e) { + return (e instanceof BinopExp) && (((BinopExp)e).op == Lua.OP_CONCAT); + } + + public void visit(UnopExp exp) { + exp.rhs.accept(this); + switch ( exp.op ) { + case Lua.OP_NOT: out(".not()"); break; + case Lua.OP_LEN: out(".len()"); break; + case Lua.OP_UNM: out(".neg()"); break; + } + } + + public void visit(Constant exp) { + out( evalConstant(exp.value) ); + } + + protected String evalConstant(LuaValue value) { + switch ( value.type() ) { + case LuaValue.TSTRING: + return evalLuaStringConstant(value.checkstring()); + case LuaValue.TNIL: + return "NIL"; + case LuaValue.TBOOLEAN: + return value.toboolean()? "TRUE": "FALSE"; + case LuaValue.TNUMBER: + return evalNumberConstant(value.todouble()); + default: + throw new IllegalStateException("unknown constant type: "+value.typename()); + } + } + + private String evalStringConstant(String str) { + return evalLuaStringConstant( LuaValue.valueOf(str) ); + } + + private String evalLuaStringConstant(LuaString str) { + if ( stringConstants.containsKey(str) ) + return (String) stringConstants.get(str); + String declvalue = quotedStringInitializer(str); + String javaname = javascope.createConstantName(str.tojstring()); + constantDeclarations.add( "static final LuaValue "+javaname+" = valueOf("+declvalue+");" ); + stringConstants.put(str,javaname); + return javaname; + } + + private String evalNumberConstant(double value) { + if ( value == 0 ) return "ZERO"; + if ( value == -1 ) return "MINUSONE"; + if ( value == 1 ) return "ONE"; + if ( numberConstants.containsKey(Double.valueOf(value)) ) + return (String) numberConstants.get(Double.valueOf(value)); + String declvalue = evalNumberLiteral(value); + String javaname = javascope.createConstantName(declvalue); + constantDeclarations.add( "static final LuaValue "+javaname+" = valueOf("+declvalue+");" ); + numberConstants.put(Double.valueOf(value),javaname); + return javaname; + } + + private String evalNumberLiteral(double value) { + int ivalue = (int) value; + String svalue = value==ivalue? String.valueOf(ivalue): String.valueOf(value); + return (value < 0? "("+svalue+")": svalue); + } + + public void visit(FieldExp exp) { + exp.lhs.accept(this); + out(".get("+evalStringConstant(exp.name.name)+")"); + } + + public void visit(IndexExp exp) { + exp.lhs.accept(this); + out(".get("); + exp.exp.accept(this); + out(")"); + } + + public void visit(NameExp exp) { + singleReference( exp.name ); + } + + public void visit(ParensExp exp) { + if ( exp.exp.isvarargexp() ) + out( evalLuaValue(exp.exp) ); + else + exp.exp.accept(this); + } + + public void visit(VarargsExp exp) { + int c = callerExpects.containsKey(exp)? ((Integer)callerExpects.get(exp)).intValue(): 0; + out( c==1? "$arg.arg1()": "$arg" ); + } + + public void visit(MethodCall exp) { + List e = exp.args.exps; + int n = e != null? e.size(): 0; + int c = callerExpects.containsKey(exp)? ((Integer)callerExpects.get(exp)).intValue(): 0; + if ( c == -1 ) + n = -1; + out( evalLuaValue(exp.lhs) ); + switch ( n ) { + case 0: + out(".method("+evalStringConstant(exp.name)+")"); + break; + case 1: case 2: + out(".method("+evalStringConstant(exp.name)+","); + exp.args.accept(this); + out(")"); + break; + default: + out(".invokemethod("+evalStringConstant(exp.name) + +((e==null||e.size()==0)? "": ","+evalListAsVarargs(exp.args.exps))+")"); + if ( c == 1 ) + out(".arg1()"); + break; + } + } + + public void visit(FuncCall exp) { + List e = exp.args.exps; + int n = e != null? e.size(): 0; + if ( n > 0 && ((Exp)e.get(n-1)).isvarargexp() ) + n = -1; + int c = callerExpects.containsKey(exp)? ((Integer)callerExpects.get(exp)).intValue(): 0; + if ( c == -1 ) + n = -1; + out( evalLuaValue(exp.lhs) ); + switch ( n ) { + case 0: case 1: case 2: case 3: + out(".call("); + exp.args.accept(this); + out(")"); + break; + default: + out(".invoke("+((e==null||e.size()==0)? "": evalListAsVarargs(e))+")"); + if ( c == 1 ) + out(".arg1()"); + break; + } + } + + public void tailCall( Exp e ) { + if ( e instanceof MethodCall ) { + MethodCall mc = (MethodCall) e; + outl("return new TailcallVarargs("+evalLuaValue(mc.lhs)+","+evalStringConstant(mc.name)+","+evalListAsVarargs(mc.args.exps)+");"); + } else if ( e instanceof FuncCall ) { + FuncCall fc = (FuncCall) e; + outl("return new TailcallVarargs("+evalLuaValue(fc.lhs)+","+evalListAsVarargs(fc.args.exps)+");"); + } else { + throw new IllegalArgumentException("can't tail call "+e); + } + } + + public void visit(FuncArgs args) { + if ( args.exps != null ) { + int n = args.exps.size(); + if ( n > 0 ) { + for ( int i=1; i=0 && n<=1 && m<=3 && ! body.parlist.isvararg ) { + switch ( m ) { + case 0: + outr("new ZeroArgFunction(env) {"); + addindent(); + outb("public LuaValue call() {"); + break; + case 1: + outr("new OneArgFunction(env) {"); + addindent(); + outb("public LuaValue call(" + +declareArg((Name) body.parlist.names.get(0))+") {"); + assignArg((Name) body.parlist.names.get(0)); + break; + case 2: + outr("new TwoArgFunction(env) {"); + addindent(); + outb("public LuaValue call(" + +declareArg((Name) body.parlist.names.get(0))+"," + +declareArg((Name) body.parlist.names.get(1))+") {"); + assignArg((Name) body.parlist.names.get(0)); + assignArg((Name) body.parlist.names.get(1)); + break; + case 3: + outr("new ThreeArgFunction(env) {"); + addindent(); + outb("public LuaValue call(" + +declareArg((Name) body.parlist.names.get(0))+"," + +declareArg((Name) body.parlist.names.get(1))+"," + +declareArg((Name) body.parlist.names.get(2))+") {"); + assignArg((Name) body.parlist.names.get(0)); + assignArg((Name) body.parlist.names.get(1)); + assignArg((Name) body.parlist.names.get(2)); + break; + } + } else { + outr("new VarArgFunction(env) {"); + addindent(); + outb("public Varargs invoke(Varargs $arg) {"); + for ( int i=0; i0? "$arg.arg("+(i+1)+")": "$arg.arg1()"; + singleLocalDeclareAssign( name, value ); + } + if ( body.parlist.isvararg ) { + Variable arg = body.scope.find("arg"); + javascope.setJavaName(arg,"arg"); + if ( m > 0 ) + outl( "$arg = $arg.subargs("+(m+1)+");" ); + String value = (javascope.usesvarargs? "NIL": "LuaValue.tableOf($arg,1)"); + singleLocalDeclareAssign( arg, value ); + } + } + writeBodyBlock(body.block); + oute("}"); + subindent(); + outi("}"); + javascope = javascope.popJavaScope(); + } + + private String declareArg(Name name) { + String argname = javascope.getJavaName(name.variable); + return "LuaValue "+argname+(name.variable.isupvalue? "$0": ""); + } + + private void assignArg(Name name) { + if ( name.variable.isupvalue ) { + String argname = javascope.getJavaName(name.variable); + singleLocalDeclareAssign(name, argname+"$0"); + } + } + + public void visit(FuncDef stat) { + Writer x = pushWriter(); + stat.body.accept(this); + String value = popWriter(x); + int n = stat.name.dots!=null? stat.name.dots.size(): 0; + boolean m = stat.name.method != null; + if ( n>0 && !m && stat.name.name.variable.isLocal() ) + singleAssign( stat.name.name, value ); + else if ( n==0 && !m ) { + singleAssign( stat.name.name, value ); + } else { + singleReference( stat.name.name ); + for ( int i=0; i0? ("+i+"<="+j+"$limit): ("+i+">="+j+"$limit);" ); + outr( " "+i+"+="+j+"$step ) {" ); + } + addindent(); + singleLocalDeclareAssign(stat.name, "valueOf("+i+")"); + super.visit(stat.block); + oute( "}" ); + } + + private Name tmpJavaVar(String s) { + Name n = new Name(s); + n.variable = javascope.define(s); + return n; + } + + public void visit(GenericFor stat) { + Name f = tmpJavaVar("f"); + Name s = tmpJavaVar("s"); + Name var = tmpJavaVar("var"); + Name v = tmpJavaVar("v"); + String javaf = javascope.getJavaName(f.variable); + String javas = javascope.getJavaName(s.variable); + String javavar = javascope.getJavaName(var.variable); + String javav = javascope.getJavaName(v.variable); + outl("LuaValue "+javaf+","+javas+","+javavar+";"); + outl("Varargs "+javav+";"); + List fsvar = new ArrayList(); + fsvar.add(f); + fsvar.add(s); + fsvar.add(var); + multiAssign(fsvar, stat.exps); + + outb("while (true) {"); + outl( javav+" = "+javaf+".invoke(varargsOf("+javas+","+javavar+"));"); + outl( "if (("+javavar+"="+javav+".arg1()).isnil()) break;"); + singleLocalDeclareAssign((Name) stat.names.get(0),javavar); + for ( int i=1, n=stat.names.size(); i keyed = new ArrayList(); + List list = new ArrayList(); + for ( int i=0; i exps) { + super.visitExps(exps); + } + + public void visitNames(List names) { + super.visitNames(names); + } + + public void visitVars(List vars) { + super.visitVars(vars); + } + } + + private static String quotedStringInitializer(LuaString s) { + byte[] bytes = s.m_bytes; + int o = s.m_offset; + int n = s.m_length; + StringBuffer sb = new StringBuffer(n+2); + + // check for bytes not encodable as utf8 + if ( ! s.isValidUtf8() ) { + sb.append( "new byte[]{" ); + for ( int j=0; j0 ) sb.append(","); + byte b = bytes[o+j]; + switch ( b ) { + case '\n': sb.append( "'\\n'" ); break; + case '\r': sb.append( "'\\r'" ); break; + case '\t': sb.append( "'\\t'" ); break; + case '\\': sb.append( "'\\\\'" ); break; + default: + if ( b >= ' ' ) { + sb.append( '\''); + sb.append( (char) b ); + sb.append( '\''); + } else { + sb.append( String.valueOf((int)b) ); + } + break; + } + } + sb.append( "}" ); + return sb.toString(); + } + + sb.append('"'); + for ( int i=0; i= ' ' ) { + sb.append( (char) b ); break; + } else { + // convert from UTF-8 + int u = 0xff & (int) b; + if ( u>=0xc0 && i+1=0xe0 && i+2 SPECIALS = new HashSet(); + + private static final String[] specials = { + // keywords used by our code generator + "name", "opcode", "env", // "arg", + + // java keywords + "abstract", "continue", "for", "new", "switch", + "assert", "default", "goto", "package", "synchronized", + "boolean", "do", "if", "private", "this", + "break", "double", "implements", "protected", "throw", + "byte", "else", "import", "public", "throws", + "case", "enum", "instanceof", "return", "transient", + "catch", "extends", "int", "short", "try", + "char", "final", "interface", "static", "void", + "class", "finally", "long", "strictfp", "volatile", + "const", "float", "native", "super", "while", + + // java literals + "false", "null", "true", + }; + + static { + for ( int i=0; i staticnames; + final Set javanames = new HashSet(); + final Map astele2javaname = new HashMap(); + + private JavaScope(Set staticnames, JavaScope outerScope) { + super(outerScope); + this.staticnames = staticnames; + } + + public static JavaScope newJavaScope(Chunk chunk) { + return new JavaScope(new HashSet(), null).initialize(chunk.block, -1); + } + + public JavaScope pushJavaScope(FuncBody body) { + return new JavaScope(staticnames, this).initialize(body.block, 0); + } + + public JavaScope popJavaScope() { + return (JavaScope) outerScope; + } + + final String getJavaName(Variable nv) { + for ( JavaScope s = this; s != null; s = (JavaScope) s.outerScope ) + if ( s.astele2javaname.containsKey(nv) ) + return (String) s.astele2javaname.get(nv); + return allocateJavaName( nv, nv.name ); + } + + final private String allocateJavaName(Object astele, String proposal) { + for ( int i=0; true; i++ ) { + String jname = proposal+(i==0? "": "$"+i); + if ( ! isJavanameInScope(jname) && ! SPECIALS.contains(jname) && !staticnames.contains(jname) ) { + javanames.add(jname); + astele2javaname.put(astele,jname); + return jname; + } + } + } + + public void setJavaName(Variable astele, String javaname) { + javanames.add(javaname); + astele2javaname.put(astele,javaname); + } + + private boolean isJavanameInScope(String javaname) { + for ( JavaScope s = this; s != null; s = (JavaScope) s.outerScope ) + if ( s.javanames.contains(javaname) ) + return true; + return false; + } + + public String createConstantName(String proposal) { + proposal = toLegalJavaName(proposal); + for ( int i=0; true; i++ ) { + String jname = proposal+(i==0? "": "$"+i); + if ( ! isJavanameInScope(jname) && ! SPECIALS.contains(jname) && !staticnames.contains(jname) ) { + javanames.add(jname); + staticnames.add(jname); + return jname; + } + } + } + + public static String toLegalJavaName(String string) { + String better = string.replaceAll("[^\\w]", "_"); + if ( better.length() > MAX_CONSTNAME_LEN ) + better = better.substring(0,MAX_CONSTNAME_LEN); + if ( better.length() == 0 || !Character.isJavaIdentifierStart( better.charAt(0) ) ) + better = "_"+better; + return better; + } + + private JavaScope initialize(Block block, int nreturns) { + NewScopeVisitor v = new NewScopeVisitor(nreturns); + block.accept( v ); + this.nreturns = v.nreturns; + this.needsbinoptmp = v.needsbinoptmp; + this.usesvarargs = v.usesvarargs; + return this; + } + + class NewScopeVisitor extends Visitor { + int nreturns = 0; + boolean needsbinoptmp = false; + boolean usesvarargs = false; + NewScopeVisitor(int nreturns) { + this.nreturns = nreturns; + } + public void visit(FuncBody body) {} + public void visit(Return s) { + int n = s.nreturns(); + nreturns = (nreturns<0||n<0? -1: Math.max(n,nreturns)); + super.visit(s); + } + public void visit(BinopExp exp) { + switch ( exp.op ) { + case Lua.OP_AND: case Lua.OP_OR: + needsbinoptmp = true; + break; + } + super.visit(exp); + } + public void visit(VarargsExp exp) { + usesvarargs = true; + } + + } + +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/lua2java/Lua2Java.java b/luaj-2.0.3/src/jse/org/luaj/vm2/lua2java/Lua2Java.java new file mode 100644 index 0000000000..c3083a435e --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/lua2java/Lua2Java.java @@ -0,0 +1,166 @@ +package org.luaj.vm2.lua2java; + +import java.io.BufferedInputStream; +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.Arrays; + +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; +import javax.tools.JavaCompiler.CompilationTask; + +import org.luaj.vm2.LoadState; +import org.luaj.vm2.LuaFunction; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.LoadState.LuaCompiler; +import org.luaj.vm2.ast.Chunk; +import org.luaj.vm2.compiler.LuaC; +import org.luaj.vm2.parser.LuaParser; + +public class Lua2Java implements LuaCompiler { + + public static final Lua2Java instance = new Lua2Java(); + + public static final void install() { + LoadState.compiler = instance; + } + + private Lua2Java() { + } + + public LuaFunction load(InputStream stream, String filename, LuaValue env) throws IOException { + + // get first byte + if ( ! stream.markSupported() ) + stream = new BufferedInputStream( stream ); + stream.mark( 1 ); + int firstByte = stream.read(); + stream.reset(); + + // we can only sompile sources + if ( firstByte != '\033' ) { + final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) + LuaValue.error("no java compiler"); + + // break into package and class + if ( filename.endsWith( ".lua") ) + filename = filename.substring(0, filename.length()-4); + String s = filename.replace('\\', '/').replace('/','.').replaceAll("[^\\w]", "_"); + int p = s.lastIndexOf('.'); + final String packageName = p>=0? s.substring(0,p): null; + final String className = toClassname( s.substring(p+1) ); + + // open output file + final String pkgSubdir = (packageName!=null? packageName.replace('.','/'): ""); + final String srcDirRoot = "lua2java/src"; + final String binDirRoot = "lua2java/classes"; + final String srcDirname = srcDirRoot+"/"+pkgSubdir; + final String binDirname = binDirRoot+"/"+pkgSubdir; + final String srcFilename = srcDirname + "/" + className + ".java"; + + // make directories + new File(srcDirname).mkdirs(); + new File(binDirname).mkdirs(); + + // generate java source + try { + LuaParser parser = new LuaParser(stream,"ISO8859-1"); + Chunk chunk = parser.Chunk(); + File source = new File(srcFilename); + Writer writer = new OutputStreamWriter( new FileOutputStream(source) ); + new JavaCodeGen(chunk,writer,packageName,className); + writer.close(); + + // set up output location + StandardJavaFileManager fm = compiler.getStandardFileManager( null, null, null); + fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File[] { new File(binDirRoot) })); + + // compile the file + CompilationTask task = compiler.getTask(null, fm, null, null, null, fm.getJavaFileObjects(source)); + boolean success = task.call().booleanValue(); + + // instantiate, config and return + if (success) { + // create instance + ClassLoader cl = new ClassLoader() { + public Class findClass(String classname) throws ClassNotFoundException { + if ( classname.startsWith(className) ) { + File f = new File( binDirname+"/"+classname+".class"); + long n = f.length(); + byte[] b = new byte[(int) n]; + try { + DataInputStream dis = new DataInputStream( new FileInputStream(f) ); + dis.readFully(b); + } catch ( Exception e ) { + throw new RuntimeException("failed to read class bytes: "+e ); + } + return defineClass(classname, b, 0, b.length); + } + return super.findClass(classname); + } + }; + Class clazz = cl.loadClass(className); + Object instance = clazz.newInstance(); + LuaFunction value = (LuaFunction) instance; + value.setfenv( env ); + return value; + } else { + } + } catch ( Exception e ) { + LuaValue.error("compile task failed: "+e); + } + + // report compilation error + LuaValue.error("compile task failed:"); + return null; + } + + // fall back to plain compiler + return LuaC.instance.load( stream, filename, env); + } + + /** Convert lua filename to valid class name */ + public static final String toClassname( String filename ) { + int n=filename.length(); + int j=n; + if ( filename.endsWith(".lua") ) + j -= 4; + for ( int k=0; k='a'&&c<='z') || (c>='A'&&c<='Z') || (c>='0'&&c<='9') ) + return true; + switch ( c ) { + case '.': + case '$': + case '_': + return true; + default: + return false; + } + } +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/luajc/BasicBlock.java b/luaj-2.0.3/src/jse/org/luaj/vm2/luajc/BasicBlock.java new file mode 100644 index 0000000000..130f794721 --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/luajc/BasicBlock.java @@ -0,0 +1,180 @@ +/** + * + */ +package org.luaj.vm2.luajc; + +import java.util.Vector; + +import org.luaj.vm2.Lua; +import org.luaj.vm2.Prototype; + +public class BasicBlock { + int pc0,pc1; // range of program counter values for the block + BasicBlock[] prev; // previous basic blocks (0-n of these) + BasicBlock[] next; // next basic blocks (0, 1, or 2 of these) + boolean islive; // true if this block is used + + public BasicBlock(Prototype p, int pc0) { + this.pc0 = this.pc1 = pc0; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append( (pc0+1)+"-"+(pc1+1) + +(prev!=null? " prv: "+str(prev,1): "") + +(next!=null? " nxt: "+str(next,0): "") + +"\n" ); + return sb.toString(); + } + + private String str(BasicBlock[] b, int p) { + if ( b == null ) + return ""; + StringBuffer sb = new StringBuffer(); + sb.append("("); + for ( int i=0, n=b.length; i 0 ) + sb.append( "," ); + sb.append( String.valueOf( p==1? b[i].pc1+1: b[i].pc0+1 ) ); + } + sb.append(")"); + return sb.toString(); + } + + public static BasicBlock[] findBasicBlocks(Prototype p) { + + // mark beginnings, endings + final int n = p.code.length; + final boolean[] isbeg = new boolean[n]; + final boolean[] isend = new boolean[n]; + isbeg[0] = true; + BranchVisitor bv = new BranchVisitor(isbeg) { + public void visitBranch(int pc0, int pc1) { + isend[pc0] = true; + isbeg[pc1] = true; + } + public void visitReturn(int pc) { + isend[pc] = true; + } + }; + visitBranches(p, bv); // 1st time to mark branches + visitBranches(p, bv); // 2nd time to catch merges + + // create basic blocks + final BasicBlock[] blocks = new BasicBlock[n]; + for ( int i=0; i= SUPERTYPE_VARARGS ) + superclassType = SUPERTYPE_VARARGS; + for ( int i=0, n=p.code.length; i 2)) ) { + superclassType = SUPERTYPE_VARARGS; + break; + } + } + + // create class generator + cg = new ClassGen(classname, SUPER_NAME_N[superclassType], filename, + Constants.ACC_PUBLIC | Constants.ACC_SUPER, null); + cp = cg.getConstantPool(); // cg creates constant pool + + // main instruction lists + factory = new InstructionFactory(cg); + init = new InstructionList(); + main = new InstructionList(); + + // create the fields + for ( int i=0; i 0 ) { + append(new ALOAD(1)); + append(new PUSH(cp, 1 + p.numparams)); + append(factory.createInvoke(STR_VARARGS, "subargs", TYPE_VARARGS, ARG_TYPES_INT, Constants.INVOKEVIRTUAL)); + append(new ASTORE(1)); + } + } else { + // fixed arg function between 0 and 3 arguments + for ( slot=0; slot", + cg.getClassName(), init, cg.getConstantPool()); + init.append(InstructionConstants.RETURN); + mg.setMaxStack(); + cg.addMethod(mg.getMethod()); + init.dispose(); + } + + // add default constructor + cg.addEmptyConstructor(Constants.ACC_PUBLIC); + + // gen method + resolveBranches(); + mg.setMaxStack(); + cg.addMethod(mg.getMethod()); + main.dispose(); + + // convert to class bytes + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + cg.getJavaClass().dump(baos); + return baos.toByteArray(); + } catch ( IOException ioe ) { + throw new RuntimeException("JavaClass.dump() threw "+ioe); + } + } + + public void dup() { + append(InstructionConstants.DUP); + } + + public void pop() { + append(InstructionConstants.POP); + } + + public void loadNil() { + append(factory.createFieldAccess(STR_LUAVALUE, "NIL", TYPE_LUAVALUE, Constants.GETSTATIC)); + } + + public void loadNone() { + append(factory.createFieldAccess(STR_LUAVALUE, "NONE", TYPE_LUAVALUE, Constants.GETSTATIC)); + } + + public void loadBoolean(boolean b) { + String field = (b? "TRUE": "FALSE"); + append(factory.createFieldAccess(STR_LUAVALUE, field, TYPE_LUABOOLEAN, Constants.GETSTATIC)); + } + + private Map plainSlotVars = new HashMap(); + private Map upvalueSlotVars = new HashMap(); + private int findSlot( int slot, Map map, String prefix, Type type ) { + Integer islot = Integer.valueOf(slot); + if ( map.containsKey(islot) ) + return ((Integer)map.get(islot)).intValue(); + String name = prefix+slot; + LocalVariableGen local = mg.addLocalVariable(name, type, null, null); + int index = local.getIndex(); + map.put(islot, Integer.valueOf(index)); + return index; + } + private int findSlotIndex( int slot, boolean isupvalue ) { + return isupvalue? + findSlot( slot, upvalueSlotVars, PREFIX_UPVALUE_SLOT, TYPE_LOCALUPVALUE ): + findSlot( slot, plainSlotVars, PREFIX_PLAIN_SLOT, TYPE_LUAVALUE ); + } + + public void loadLocal(int pc, int slot) { + boolean isupval = pi.isUpvalueRefer(pc, slot); + int index = findSlotIndex( slot, isupval ); + append(new ALOAD(index)); + if (isupval) { + append(new PUSH(cp, 0)); + append(InstructionConstants.AALOAD); + } + } + + public void storeLocal(int pc, int slot) { + boolean isupval = pi.isUpvalueAssign(pc, slot); + int index = findSlotIndex( slot, isupval ); + if (isupval) { + boolean isupcreate = pi.isUpvalueCreate(pc, slot); + if ( isupcreate ) { + append(factory.createInvoke(classname, "newupe", TYPE_LOCALUPVALUE, ARG_TYPES_NONE, Constants.INVOKESTATIC)); + append(InstructionConstants.DUP); + append(new ASTORE(index)); + } else { + append(new ALOAD(index)); + } + append(InstructionConstants.SWAP); + append(new PUSH(cp, 0)); + append(InstructionConstants.SWAP); + append(InstructionConstants.AASTORE); + } else { + append(new ASTORE(index)); + } + } + + public void createUpvalues(int pc, int firstslot, int numslots) { + for ( int i=0; i", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); + append(InstructionConstants.DUP); + loadEnv(); + append(factory.createInvoke(STR_LUAVALUE, "setfenv", Type.VOID, ARG_TYPES_LUAVALUE, Constants.INVOKEVIRTUAL)); + } + + public void closureInitUpvalueFromUpvalue(String protoname, int newup, int upindex) { + boolean isrw = pi.isReadWriteUpvalue( pi.upvals[upindex] ); + Type uptype = isrw? (Type) TYPE_LOCALUPVALUE: (Type) TYPE_LUAVALUE; + String srcname = upvalueName(upindex); + String destname = upvalueName(newup); + append(InstructionConstants.THIS); + append(factory.createFieldAccess(classname, srcname, uptype, Constants.GETFIELD)); + append(factory.createFieldAccess(protoname, destname, uptype, Constants.PUTFIELD)); + } + + public void closureInitUpvalueFromLocal(String protoname, int newup, int pc, int srcslot) { + boolean isrw = pi.isReadWriteUpvalue( pi.vars[srcslot][pc].upvalue ); + Type uptype = isrw? (Type) TYPE_LOCALUPVALUE: (Type) TYPE_LUAVALUE; + String destname = upvalueName(newup); + int index = findSlotIndex( srcslot, isrw ); + append(new ALOAD(index)); + append(factory.createFieldAccess(protoname, destname, uptype, Constants.PUTFIELD)); + } + + private Map constants = new HashMap(); + + public void loadConstant(LuaValue value) { + switch ( value.type() ) { + case LuaValue.TNIL: + loadNil(); + break; + case LuaValue.TBOOLEAN: + loadBoolean( value.toboolean() ); + break; + case LuaValue.TNUMBER: + case LuaValue.TSTRING: + String name = (String) constants.get(value); + if ( name == null ) { + name = value.type() == LuaValue.TNUMBER? + value.isinttype()? + createLuaIntegerField(value.checkint()): + createLuaDoubleField(value.checkdouble()): + createLuaStringField(value.checkstring()); + constants.put(value, name); + } + append(factory.createGetStatic(classname, name, TYPE_LUAVALUE)); + break; + default: + throw new IllegalArgumentException("bad constant type: "+value.type()); + } + } + + private String createLuaIntegerField(int value) { + String name = PREFIX_CONSTANT+constants.size(); + FieldGen fg = new FieldGen(Constants.ACC_STATIC | Constants.ACC_FINAL, + TYPE_LUAVALUE, name, cp); + cg.addField(fg.getField()); + init.append(new PUSH(cp, value)); + init.append(factory.createInvoke(STR_LUAVALUE, "valueOf", + TYPE_LUAINTEGER, ARG_TYPES_INT, Constants.INVOKESTATIC)); + init.append(factory.createPutStatic(classname, name, TYPE_LUAVALUE)); + return name; + } + + private String createLuaDoubleField(double value) { + String name = PREFIX_CONSTANT+constants.size(); + FieldGen fg = new FieldGen(Constants.ACC_STATIC | Constants.ACC_FINAL, + TYPE_LUAVALUE, name, cp); + cg.addField(fg.getField()); + init.append(new PUSH(cp, value)); + init.append(factory.createInvoke(STR_LUAVALUE, "valueOf", + TYPE_LUANUMBER, ARG_TYPES_DOUBLE, Constants.INVOKESTATIC)); + init.append(factory.createPutStatic(classname, name, TYPE_LUAVALUE)); + return name; + } + + private String createLuaStringField(LuaString value) { + String name = PREFIX_CONSTANT+constants.size(); + FieldGen fg = new FieldGen(Constants.ACC_STATIC | Constants.ACC_FINAL, + TYPE_LUAVALUE, name, cp); + cg.addField(fg.getField()); + LuaString ls = value.checkstring(); + if ( ls.isValidUtf8() ) { + init.append(new PUSH(cp, value.tojstring())); + init.append(factory.createInvoke(STR_LUASTRING, "valueOf", + TYPE_LUASTRING, ARG_TYPES_STRING, Constants.INVOKESTATIC)); + } else { + char[] c = new char[ls.m_length]; + for ( int j=0; j= branchDestHandles.length ) + throw new IllegalArgumentException("no target at or after "+targets[pc]+" op="+Lua.GET_OPCODE(p.code[targets[pc]])); + branches[pc].setTarget(branchDestHandles[t]); + } + } + } + + public void setlistStack(int pc, int a0, int index0, int nvals) { + for ( int i=0; i b+1 ) { + builder.tobuffer(); + for ( int k=c; --k>=b; ) + builder.concatbuffer(); + builder.tovalue(); + } else { + builder.concatvalue(); + } + builder.storeLocal(pc, a); + break; + + case Lua.OP_LOADBOOL:/* A B C R(A):= (Bool)B: if (C) pc++ */ + builder.loadBoolean( b!=0 ); + builder.storeLocal( pc, a ); + if ( c!=0 ) + builder.addBranch(pc, JavaBuilder.BRANCH_GOTO, pc+2); + break; + + case Lua.OP_JMP: /* sBx pc+=sBx */ + builder.addBranch(pc, JavaBuilder.BRANCH_GOTO, pc+1+sbx); + break; + + case Lua.OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ + case Lua.OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ + case Lua.OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ + loadLocalOrConstant( p, builder, pc, b ); + loadLocalOrConstant( p, builder, pc, c ); + builder.compareop(o); + builder.addBranch(pc, (a!=0? JavaBuilder.BRANCH_IFEQ: JavaBuilder.BRANCH_IFNE), pc+2); + break; + + case Lua.OP_TEST: /* A C if not (R(A) <=> C) then pc++ */ + builder.loadLocal( pc, a ); + builder.toBoolean(); + builder.addBranch(pc, (c!=0? JavaBuilder.BRANCH_IFEQ: JavaBuilder.BRANCH_IFNE), pc+2); + break; + + case Lua.OP_TESTSET: /* A B C if (R(B) <=> C) then R(A):= R(B) else pc++ */ + builder.loadLocal( pc, b ); + builder.toBoolean(); + builder.addBranch(pc, (c!=0? JavaBuilder.BRANCH_IFEQ: JavaBuilder.BRANCH_IFNE), pc+2); + builder.loadLocal( pc, b ); + builder.storeLocal( pc, a ); + break; + + case Lua.OP_CALL: /* A B C R(A), ... ,R(A+C-2):= R(A)(R(A+1), ... ,R(A+B-1)) */ + + // load function + builder.loadLocal(pc, a); + + // load args + int narg = b - 1; + switch ( narg ) { + case 0: case 1: case 2: case 3: + for ( int i=1; i 3 + builder.newVarargs( pc, a+1, b-1 ); + narg = -1; + break; + case -1: // prev vararg result + loadVarargResults( builder, pc, a+1, vresultbase ); + narg = -1; + break; + } + + // call or invoke + boolean useinvoke = narg<0 || c<1 || c>2; + if ( useinvoke ) + builder.invoke(narg); + else + builder.call(narg); + + // handle results + switch ( c ) { + case 1: + builder.pop(); + break; + case 2: + if ( useinvoke ) + builder.arg( 1 ); + builder.storeLocal(pc, a); + break; + default: // fixed result count - unpack args + for ( int i=1; i 1 + builder.newVarargs( pc, a+1, b-1 ); + break; + case 0: // prev vararg result + loadVarargResults( builder, pc, a+1, vresultbase ); + break; + } + builder.newTailcallVarargs(); + builder.areturn(); + break; + + case Lua.OP_RETURN: /* A B return R(A), ... ,R(A+B-2) (see note) */ + if ( c == 1 ) { + builder.loadNone(); + } else { + switch ( b ) { + case 0: loadVarargResults( builder, pc, a, vresultbase ); break; + case 1: builder.loadNone(); break; + case 2: builder.loadLocal(pc, a); break; + default: builder.newVarargs(pc, a, b-1); break; + } + } + builder.areturn(); + break; + + case Lua.OP_FORPREP: /* A sBx R(A)-=R(A+2): pc+=sBx */ + builder.loadLocal(pc, a); + builder.loadLocal(pc, a+2); + builder.binaryop( Lua.OP_SUB ); + builder.storeLocal(pc, a); + builder.addBranch(pc, JavaBuilder.BRANCH_GOTO, pc+1+sbx); + break; + + case Lua.OP_FORLOOP: /* A sBx R(A)+=R(A+2): if R(A) =2) + builder.dup(); + builder.arg( 1 ); + builder.dup(); + builder.storeLocal(pc, a+2); + builder.storeLocal(pc, a+3); + + // v[2]..v[c], use varargs from stack + for ( int j=2; j<=c; j++ ) { + if ( j 0 ) { + builder.setlistStack( pc, a+1, index0, nstack ); + index0 += nstack; + } + builder.setlistVarargs( index0, vresultbase ); + } else { + builder.setlistStack( pc, a+1, index0, b ); + builder.pop(); + } + break; + + case Lua.OP_CLOSE: /* A close all variables in the stack up to (>=) R(A)*/ + break; + + case Lua.OP_CLOSURE: /* A Bx R(A):= closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ + { + Prototype newp = p.p[bx]; + String protoname = closureName(classname, bx); + int nup = newp.nups; + builder.closureCreate( protoname ); + if ( nup > 0 ) + builder.dup(); + builder.storeLocal( pc, a ); + if ( nup > 0 ) { + for ( int up=0; up unloaded = new HashMap(); + + public JavaLoader( LuaValue env ) { + this.env = env; + } + + public LuaFunction load( Prototype p, String classname, String filename ) { + JavaGen jg = new JavaGen( p, classname, filename ); + return load( jg ); + } + + public LuaFunction load( JavaGen jg ) { + include( jg ); + return load( jg.classname ); + } + + public LuaFunction load(String classname) { + try { + Class c = loadClass( classname ); + LuaFunction v = (LuaFunction) c.newInstance(); + v.setfenv(env); + return v; + } catch ( Exception e ) { + e.printStackTrace(); + throw new IllegalStateException("bad class gen: "+e); + } + } + + public void include( JavaGen jg ) { + unloaded.put( jg.classname, jg.bytecode ); + for ( int i=0, n=jg.inners!=null? jg.inners.length: 0; i + * This requires the bcel library to be on the class path to work as expected. + * If the library is not found, the default {@link LuaC} lua-to-lua-bytecode + * compiler will be used. + *

+ * The compiler should be installed as part of globals initialization, + * and before any scripts or lua code is executed. + * A typical example is to install it following the globals creation, + * as in the following: + *

 {@code
+ * LuaValue _G = JsePlatform.standardGlobals();
+ * LuaJC.install();
+ * LoadState.load( new ByteArrayInputStream("print 'hello'".getBytes()), "main.lua", _G ).call();
+ * } 
+ * @see LuaCompiler + * @see LuaC + * @see JsePlatform + * @see JmePlatform + * @see BaseLib + * @see LuaValue + */ +public class LuaJC implements LuaCompiler { + + private static final String NON_IDENTIFIER = "[^a-zA-Z0-9_$/.\\-]"; + + private static LuaJC instance; + + public static LuaJC getInstance() { + if ( instance == null ) + instance = new LuaJC(); + return instance; + } + + /** + * Install the compiler as the main compiler to use. + * Will fall back to the LuaC prototype compiler. + */ + public static final void install() { + LoadState.compiler = getInstance(); + } + + public LuaJC() { + } + + public Hashtable compileAll(InputStream script, String chunkname, String filename) throws IOException { + String classname = toStandardJavaClassName( chunkname ); + String luaname = toStandardLuaFileName( filename ); + Hashtable h = new Hashtable(); + Prototype p = LuaC.instance.compile(script, classname); + JavaGen gen = new JavaGen(p, classname, luaname); + insert( h, gen ); + return h; + } + + private void insert(Hashtable h, JavaGen gen) { + h.put(gen.classname, gen.bytecode); + for ( int i=0, n=gen.inners!=null? gen.inners.length: 0; i0? new ProtoInfo[p.p.length]: null; + + // find basic blocks + this.blocks = BasicBlock.findBasicBlocks(p); + this.blocklist = BasicBlock.findLiveBlocks(blocks); + + // params are inputs to first block + this.params = new VarInfo[p.maxstacksize]; + for ( int slot=0; slot b0.pc0 ) + propogateVars( v, pc-1, pc ); + + int a,b,c,nups; + int ins = prototype.code[pc]; + int op = Lua.GET_OPCODE(ins); + + // account for assignments, references and invalidations + switch ( op ) { + case Lua.OP_LOADK:/* A Bx R(A) := Kst(Bx) */ + case Lua.OP_LOADBOOL:/* A B C R(A) := (Bool)B; if (C) pc++ */ + case Lua.OP_GETUPVAL: /* A B R(A) := UpValue[B] */ + case Lua.OP_GETGLOBAL: /* A Bx R(A) := Gbl[Kst(Bx)] */ + case Lua.OP_NEWTABLE: /* A B C R(A) := {} (size = B,C) */ + a = Lua.GETARG_A( ins ); + v[a][pc] = new VarInfo(a,pc); + break; + + case Lua.OP_MOVE:/* A B R(A) := R(B) */ + case Lua.OP_UNM: /* A B R(A) := -R(B) */ + case Lua.OP_NOT: /* A B R(A) := not R(B) */ + case Lua.OP_LEN: /* A B R(A) := length of R(B) */ + case Lua.OP_TESTSET: /* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ + a = Lua.GETARG_A( ins ); + b = Lua.GETARG_B( ins ); + v[b][pc].isreferenced = true; + v[a][pc] = new VarInfo(a,pc); + break; + + case Lua.OP_ADD: /* A B C R(A) := RK(B) + RK(C) */ + case Lua.OP_SUB: /* A B C R(A) := RK(B) - RK(C) */ + case Lua.OP_MUL: /* A B C R(A) := RK(B) * RK(C) */ + case Lua.OP_DIV: /* A B C R(A) := RK(B) / RK(C) */ + case Lua.OP_MOD: /* A B C R(A) := RK(B) % RK(C) */ + case Lua.OP_POW: /* A B C R(A) := RK(B) ^ RK(C) */ + a = Lua.GETARG_A( ins ); + b = Lua.GETARG_B( ins ); + c = Lua.GETARG_C( ins ); + if (!Lua.ISK(b)) v[b][pc].isreferenced = true; + if (!Lua.ISK(c)) v[c][pc].isreferenced = true; + v[a][pc] = new VarInfo(a,pc); + break; + + case Lua.OP_SETTABLE: /* A B C R(A)[RK(B)]:= RK(C) */ + a = Lua.GETARG_A( ins ); + b = Lua.GETARG_B( ins ); + c = Lua.GETARG_C( ins ); + v[a][pc].isreferenced = true; + if (!Lua.ISK(b)) v[b][pc].isreferenced = true; + if (!Lua.ISK(c)) v[c][pc].isreferenced = true; + break; + + case Lua.OP_CONCAT: /* A B C R(A) := R(B).. ... ..R(C) */ + a = Lua.GETARG_A( ins ); + b = Lua.GETARG_B( ins ); + c = Lua.GETARG_C( ins ); + for ( ; b<=c; b++ ) + v[b][pc].isreferenced = true; + v[a][pc] = new VarInfo(a,pc); + break; + + case Lua.OP_FORPREP: /* A sBx R(A)-=R(A+2); pc+=sBx */ + a = Lua.GETARG_A( ins ); + v[a+2][pc].isreferenced = true; + v[a][pc] = new VarInfo(a,pc); + break; + + case Lua.OP_GETTABLE: /* A B C R(A) := R(B)[RK(C)] */ + a = Lua.GETARG_A( ins ); + b = Lua.GETARG_B( ins ); + c = Lua.GETARG_C( ins ); + v[b][pc].isreferenced = true; + if (!Lua.ISK(c)) v[c][pc].isreferenced = true; + v[a][pc] = new VarInfo(a,pc); + break; + + case Lua.OP_SELF: /* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */ + a = Lua.GETARG_A( ins ); + b = Lua.GETARG_B( ins ); + c = Lua.GETARG_C( ins ); + v[b][pc].isreferenced = true; + if (!Lua.ISK(c)) v[c][pc].isreferenced = true; + v[a][pc] = new VarInfo(a,pc); + v[a+1][pc] = new VarInfo(a+1,pc); + break; + + case Lua.OP_FORLOOP: /* A sBx R(A)+=R(A+2); + if R(A) =) R(A)*/ + a = Lua.GETARG_A( ins ); + for ( ; a C) then pc++ */ + a = Lua.GETARG_A( ins ); + v[a][pc].isreferenced = true; + break; + + case Lua.OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ + case Lua.OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ + case Lua.OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ + b = Lua.GETARG_B( ins ); + c = Lua.GETARG_C( ins ); + if (!Lua.ISK(b)) v[b][pc].isreferenced = true; + if (!Lua.ISK(c)) v[c][pc].isreferenced = true; + break; + + case Lua.OP_JMP: /* sBx pc+=sBx */ + break; + + default: + throw new IllegalStateException("unhandled opcode: "+ins); + } + } + } + return v; + } + + private static void propogateVars(VarInfo[][] v, int pcfrom, int pcto) { + for ( int j=0, m=v.length; j0? new UpvalInfo[newp.nups]: null; + String newname = name + "$" + bx; + for ( int j=0; j 0 && vars[slot][pc] != null && vars[slot][pc].pc == pc && vars[slot][pc-1] != null ) + pc -= 1; + VarInfo v = pc<0? params[slot]: vars[slot][pc]; + return v != null && v.upvalue != null && v.upvalue.rw; + } + + public boolean isInitialValueUsed(int slot) { + VarInfo v = params[slot]; + return v.isreferenced; + } + + public boolean isReadWriteUpvalue(UpvalInfo u) { + return u.rw; + } +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/luajc/UpvalInfo.java b/luaj-2.0.3/src/jse/org/luaj/vm2/luajc/UpvalInfo.java new file mode 100644 index 0000000000..c73ec22998 --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/luajc/UpvalInfo.java @@ -0,0 +1,144 @@ +/** + * + */ +package org.luaj.vm2.luajc; + +import org.luaj.vm2.Lua; + +public class UpvalInfo { + ProtoInfo pi; // where defined + int slot; // where defined + int nvars; // number of vars involved + VarInfo var[]; // list of vars + boolean rw; // read-write + + public UpvalInfo(ProtoInfo pi, int pc, int slot) { + this.pi = pi; + this.slot = slot; + this.nvars = 0; + this.var = null; + includeVarAndPosteriorVars( pi.vars[slot][pc] ); + for ( int i=0; i 1; + } + + private boolean includeVarAndPosteriorVars( VarInfo var ) { + if ( var == null || var == VarInfo.INVALID ) + return false; + if ( var.upvalue == this ) + return true; + var.upvalue = this; + appendVar( var ); + if ( isLoopVariable( var ) ) + return false; + boolean loopDetected = includePosteriorVarsCheckLoops( var ); + if ( loopDetected ) + includePriorVarsIgnoreLoops( var ); + return loopDetected; + } + + private boolean isLoopVariable(VarInfo var) { + if ( var.pc >= 0 ) { + switch ( Lua.GET_OPCODE(pi.prototype.code[var.pc]) ) { + case Lua.OP_TFORLOOP: + case Lua.OP_FORLOOP: + return true; + } + } + return false; + } + + private boolean includePosteriorVarsCheckLoops( VarInfo prior ) { + boolean loopDetected = false; + for ( int i=0, n=pi.blocklist.length; i=b.pc0; pc-- ) { + if ( pi.vars[slot][pc] == prior ) { + loopDetected |= includeVarAndPosteriorVars( pi.vars[slot][pc+1] ); + break; + } + } + } + } + return loopDetected; + } + + private void includePriorVarsIgnoreLoops(VarInfo poster) { + for ( int i=0, n=pi.blocklist.length; i= var.length ) { + VarInfo[] s = var; + var = new VarInfo[nvars*2+1]; + System.arraycopy(s, 0, var, 0, nvars); + } + var[nvars++] = v; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append( pi.name ); + for ( int i=0; i0? ",": " " ); + sb.append( String.valueOf(var[i])); + } + if ( rw ) + sb.append( "(rw)" ); + return sb.toString(); + } + + private boolean testIsAllocUpvalue(VarInfo v) { + if ( v.pc < 0 ) + return true; + BasicBlock b = pi.blocks[v.pc]; + if ( v.pc > b.pc0 ) + return pi.vars[slot][v.pc-1].upvalue != this; + if ( b.prev == null ) { + v = pi.params[slot]; + if ( v != null && v.upvalue != this ) + return true; + } else { + for ( int i=0, n=b.prev.length; i0 ) + sb.append( "," ); + sb.append(String.valueOf(values[i])); + } + sb.append("}"); + return sb.toString(); + } + + public VarInfo resolvePhiVariableValues() { + Set visitedBlocks = new HashSet(); + Set vars = new HashSet(); + this.collectUniqueValues(visitedBlocks, vars); + if (vars.contains(INVALID)) + return INVALID; + int n = vars.size(); + Iterator it = vars.iterator(); + if (n == 1) { + VarInfo v = (VarInfo) it.next(); + v.isreferenced |= this.isreferenced; + return v; + } + this.values = new VarInfo[n]; + for ( int i=0; i nl; + List el=null; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case DO: + jj_consume_token(DO); + b = Block(); + jj_consume_token(END); + {if (true) return Stat.block(b);} + break; + case WHILE: + jj_consume_token(WHILE); + e = Exp(); + jj_consume_token(DO); + b = Block(); + jj_consume_token(END); + {if (true) return Stat.whiledo(e,b);} + break; + case REPEAT: + jj_consume_token(REPEAT); + b = Block(); + jj_consume_token(UNTIL); + e = Exp(); + {if (true) return Stat.repeatuntil(b,e);} + break; + case IF: + s = IfThenElse(); + {if (true) return s;} + break; + default: + jj_la1[6] = jj_gen; + if (jj_2_1(3)) { + jj_consume_token(FOR); + n = jj_consume_token(NAME); + jj_consume_token(65); + e = Exp(); + jj_consume_token(66); + e2 = Exp(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case 66: + jj_consume_token(66); + e3 = Exp(); + break; + default: + jj_la1[4] = jj_gen; + ; + } + jj_consume_token(DO); + b = Block(); + jj_consume_token(END); + {if (true) return Stat.fornumeric(n.image,e,e2,e3,b);} + } else { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case FOR: + jj_consume_token(FOR); + nl = NameList(); + jj_consume_token(IN); + el = ExpList(); + jj_consume_token(DO); + b = Block(); + jj_consume_token(END); + {if (true) return Stat.forgeneric(nl,el,b);} + break; + case FUNCTION: + jj_consume_token(FUNCTION); + fn = FuncName(); + fb = FuncBody(); + {if (true) return Stat.functiondef(fn,fb);} + break; + default: + jj_la1[7] = jj_gen; + if (jj_2_2(2)) { + jj_consume_token(LOCAL); + jj_consume_token(FUNCTION); + n = jj_consume_token(NAME); + fb = FuncBody(); + {if (true) return Stat.localfunctiondef(n.image,fb);} + } else { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LOCAL: + jj_consume_token(LOCAL); + nl = NameList(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case 65: + jj_consume_token(65); + el = ExpList(); + break; + default: + jj_la1[5] = jj_gen; + ; + } + {if (true) return Stat.localassignment(nl,el);} + break; + case NAME: + case 69: + s = ExprStat(); + {if (true) return s;} + break; + default: + jj_la1[8] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + } + } + } + throw new Error("Missing return statement in function"); + } + + final public Stat IfThenElse() throws ParseException { + Block b,b2,b3=null; + Exp e,e2; + List el=null; + List bl=null; + jj_consume_token(IF); + e = Exp(); + jj_consume_token(THEN); + b = Block(); + label_2: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case ELSEIF: + ; + break; + default: + jj_la1[9] = jj_gen; + break label_2; + } + jj_consume_token(ELSEIF); + e2 = Exp(); + jj_consume_token(THEN); + b2 = Block(); + if (el==null) el=new ArrayList(); + if (bl==null) bl=new ArrayList(); + el.add(e2); + bl.add(b2); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case ELSE: + jj_consume_token(ELSE); + b3 = Block(); + break; + default: + jj_la1[10] = jj_gen; + ; + } + jj_consume_token(END); + {if (true) return Stat.ifthenelse(e,b,el,bl,b3);} + throw new Error("Missing return statement in function"); + } + + final public Stat LastStat() throws ParseException { + List el=null; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case BREAK: + jj_consume_token(BREAK); + {if (true) return Stat.breakstat();} + break; + case RETURN: + jj_consume_token(RETURN); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LONGSTRING0: + case LONGSTRING1: + case LONGSTRING2: + case LONGSTRING3: + case LONGSTRINGN: + case FALSE: + case FUNCTION: + case NIL: + case NOT: + case TRUE: + case NAME: + case NUMBER: + case STRING: + case CHARSTRING: + case 69: + case 73: + case 74: + case 77: + case 89: + el = ExpList(); + break; + default: + jj_la1[11] = jj_gen; + ; + } + {if (true) return Stat.returnstat(el);} + break; + default: + jj_la1[12] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + throw new Error("Missing return statement in function"); + } + + final public Stat ExprStat() throws ParseException { + Exp.PrimaryExp pe; + Stat as=null; + pe = PrimaryExp(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case 65: + case 66: + as = Assign(assertvarexp(pe)); + break; + default: + jj_la1[13] = jj_gen; + ; + } + {if (true) return as==null? Stat.functioncall(assertfunccall(pe)): as;} + throw new Error("Missing return statement in function"); + } + + final public Stat Assign(Exp.VarExp v0) throws ParseException { + List vl = new ArrayList(); + vl.add(v0); + Exp.VarExp ve; + List el; + label_3: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case 66: + ; + break; + default: + jj_la1[14] = jj_gen; + break label_3; + } + jj_consume_token(66); + ve = VarExp(); + vl.add(ve); + } + jj_consume_token(65); + el = ExpList(); + {if (true) return Stat.assignment(vl,el);} + throw new Error("Missing return statement in function"); + } + + final public Exp.VarExp VarExp() throws ParseException { + Exp.PrimaryExp pe; + pe = PrimaryExp(); + {if (true) return assertvarexp(pe);} + throw new Error("Missing return statement in function"); + } + + final public FuncName FuncName() throws ParseException { + FuncName fn; + Token n; + n = jj_consume_token(NAME); + fn=new FuncName(n.image); + label_4: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case 67: + ; + break; + default: + jj_la1[15] = jj_gen; + break label_4; + } + jj_consume_token(67); + n = jj_consume_token(NAME); + fn.adddot(n.image); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case 68: + jj_consume_token(68); + n = jj_consume_token(NAME); + fn.method=n.image; + break; + default: + jj_la1[16] = jj_gen; + ; + } + {if (true) return fn;} + throw new Error("Missing return statement in function"); + } + + final public Exp.PrimaryExp PrefixExp() throws ParseException { + Token n; + Exp e; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case NAME: + n = jj_consume_token(NAME); + {if (true) return Exp.nameprefix(n.image);} + break; + case 69: + jj_consume_token(69); + e = Exp(); + jj_consume_token(70); + {if (true) return Exp.parensprefix(e);} + break; + default: + jj_la1[17] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + throw new Error("Missing return statement in function"); + } + + final public Exp.PrimaryExp PrimaryExp() throws ParseException { + Exp.PrimaryExp pe; + pe = PrefixExp(); + label_5: + while (true) { + if (jj_2_3(2)) { + ; + } else { + break label_5; + } + pe = PostfixOp(pe); + } + {if (true) return pe;} + throw new Error("Missing return statement in function"); + } + + final public Exp.PrimaryExp PostfixOp(Exp.PrimaryExp lhs) throws ParseException { + Token n; + Exp e; + FuncArgs a; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case 67: + jj_consume_token(67); + n = jj_consume_token(NAME); + {if (true) return Exp.fieldop(lhs, n.image);} + break; + case 71: + jj_consume_token(71); + e = Exp(); + jj_consume_token(72); + {if (true) return Exp.indexop(lhs, e);} + break; + case 68: + jj_consume_token(68); + n = jj_consume_token(NAME); + a = FuncArgs(); + {if (true) return Exp.methodop(lhs, n.image,a);} + break; + case LONGSTRING0: + case LONGSTRING1: + case LONGSTRING2: + case LONGSTRING3: + case LONGSTRINGN: + case STRING: + case CHARSTRING: + case 69: + case 74: + a = FuncArgs(); + {if (true) return Exp.functionop(lhs, a);} + break; + default: + jj_la1[18] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + throw new Error("Missing return statement in function"); + } + + final public FuncArgs FuncArgs() throws ParseException { + List el=null; + TableConstructor tc; + LuaString s; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case 69: + jj_consume_token(69); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LONGSTRING0: + case LONGSTRING1: + case LONGSTRING2: + case LONGSTRING3: + case LONGSTRINGN: + case FALSE: + case FUNCTION: + case NIL: + case NOT: + case TRUE: + case NAME: + case NUMBER: + case STRING: + case CHARSTRING: + case 69: + case 73: + case 74: + case 77: + case 89: + el = ExpList(); + break; + default: + jj_la1[19] = jj_gen; + ; + } + jj_consume_token(70); + {if (true) return FuncArgs.explist(el);} + break; + case 74: + tc = TableConstructor(); + {if (true) return FuncArgs.tableconstructor(tc);} + break; + case LONGSTRING0: + case LONGSTRING1: + case LONGSTRING2: + case LONGSTRING3: + case LONGSTRINGN: + case STRING: + case CHARSTRING: + s = Str(); + {if (true) return FuncArgs.string(s);} + break; + default: + jj_la1[20] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + throw new Error("Missing return statement in function"); + } + + final public List NameList() throws ParseException { + List nl = new ArrayList(); + Token name; + name = jj_consume_token(NAME); + nl.add(new Name(name.image)); + label_6: + while (true) { + if (jj_2_4(2)) { + ; + } else { + break label_6; + } + jj_consume_token(66); + name = jj_consume_token(NAME); + nl.add(new Name(name.image)); + } + {if (true) return nl;} + throw new Error("Missing return statement in function"); + } + + final public List ExpList() throws ParseException { + List el = new ArrayList(); + Exp e; + e = Exp(); + el.add(e); + label_7: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case 66: + ; + break; + default: + jj_la1[21] = jj_gen; + break label_7; + } + jj_consume_token(66); + e = Exp(); + el.add(e); + } + {if (true) return el;} + throw new Error("Missing return statement in function"); + } + + final public Exp SimpleExp() throws ParseException { + Token n; + LuaString s; + Exp e; + TableConstructor tc; + FuncBody fb; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case NIL: + jj_consume_token(NIL); + {if (true) return Exp.constant(LuaValue.NIL);} + break; + case TRUE: + jj_consume_token(TRUE); + {if (true) return Exp.constant(LuaValue.TRUE);} + break; + case FALSE: + jj_consume_token(FALSE); + {if (true) return Exp.constant(LuaValue.FALSE);} + break; + case NUMBER: + n = jj_consume_token(NUMBER); + {if (true) return Exp.numberconstant(n.image);} + break; + case LONGSTRING0: + case LONGSTRING1: + case LONGSTRING2: + case LONGSTRING3: + case LONGSTRINGN: + case STRING: + case CHARSTRING: + s = Str(); + {if (true) return Exp.constant(s);} + break; + case 73: + jj_consume_token(73); + {if (true) return Exp.varargs();} + break; + case 74: + tc = TableConstructor(); + {if (true) return Exp.tableconstructor(tc);} + break; + case FUNCTION: + fb = Function(); + {if (true) return Exp.anonymousfunction(fb);} + break; + case NAME: + case 69: + e = PrimaryExp(); + {if (true) return e;} + break; + default: + jj_la1[22] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + throw new Error("Missing return statement in function"); + } + + final public LuaString Str() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case STRING: + jj_consume_token(STRING); + {if (true) return Str.quoteString(token.image);} + break; + case CHARSTRING: + jj_consume_token(CHARSTRING); + {if (true) return Str.charString(token.image);} + break; + case LONGSTRING0: + jj_consume_token(LONGSTRING0); + {if (true) return Str.longString(token.image);} + break; + case LONGSTRING1: + jj_consume_token(LONGSTRING1); + {if (true) return Str.longString(token.image);} + break; + case LONGSTRING2: + jj_consume_token(LONGSTRING2); + {if (true) return Str.longString(token.image);} + break; + case LONGSTRING3: + jj_consume_token(LONGSTRING3); + {if (true) return Str.longString(token.image);} + break; + case LONGSTRINGN: + jj_consume_token(LONGSTRINGN); + {if (true) return Str.longString(token.image);} + break; + default: + jj_la1[23] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + throw new Error("Missing return statement in function"); + } + + final public Exp Exp() throws ParseException { + Exp e,s; + int op; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LONGSTRING0: + case LONGSTRING1: + case LONGSTRING2: + case LONGSTRING3: + case LONGSTRINGN: + case FALSE: + case FUNCTION: + case NIL: + case TRUE: + case NAME: + case NUMBER: + case STRING: + case CHARSTRING: + case 69: + case 73: + case 74: + e = SimpleExp(); + break; + case NOT: + case 77: + case 89: + op = Unop(); + s = Exp(); + e=Exp.unaryexp(op,s); + break; + default: + jj_la1[24] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + label_8: + while (true) { + if (jj_2_5(2)) { + ; + } else { + break label_8; + } + op = Binop(); + s = Exp(); + e=Exp.binaryexp(e,op,s); + } + {if (true) return e;} + throw new Error("Missing return statement in function"); + } + + final public FuncBody Function() throws ParseException { + FuncBody fb; + jj_consume_token(FUNCTION); + fb = FuncBody(); + {if (true) return fb;} + throw new Error("Missing return statement in function"); + } + + final public FuncBody FuncBody() throws ParseException { + ParList pl=null; + Block b; + jj_consume_token(69); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case NAME: + case 73: + pl = ParList(); + break; + default: + jj_la1[25] = jj_gen; + ; + } + jj_consume_token(70); + b = Block(); + jj_consume_token(END); + {if (true) return new FuncBody(pl,b);} + throw new Error("Missing return statement in function"); + } + + final public ParList ParList() throws ParseException { + List nl=null; + boolean v=false; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case NAME: + nl = NameList(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case 66: + jj_consume_token(66); + jj_consume_token(73); + v=true; + break; + default: + jj_la1[26] = jj_gen; + ; + } + {if (true) return new ParList(nl,v);} + break; + case 73: + jj_consume_token(73); + {if (true) return new ParList(null,true);} ; + break; + default: + jj_la1[27] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + throw new Error("Missing return statement in function"); + } + + final public TableConstructor TableConstructor() throws ParseException { + TableConstructor tc = new TableConstructor(); + List fl = null; + jj_consume_token(74); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LONGSTRING0: + case LONGSTRING1: + case LONGSTRING2: + case LONGSTRING3: + case LONGSTRINGN: + case FALSE: + case FUNCTION: + case NIL: + case NOT: + case TRUE: + case NAME: + case NUMBER: + case STRING: + case CHARSTRING: + case 69: + case 71: + case 73: + case 74: + case 77: + case 89: + fl = FieldList(); + tc.fields=fl; + break; + default: + jj_la1[28] = jj_gen; + ; + } + jj_consume_token(75); + {if (true) return tc;} + throw new Error("Missing return statement in function"); + } + + final public List FieldList() throws ParseException { + List fl = new ArrayList(); + TableField f; + f = Field(); + fl.add(f); + label_9: + while (true) { + if (jj_2_6(2)) { + ; + } else { + break label_9; + } + FieldSep(); + f = Field(); + fl.add(f); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case 64: + case 66: + FieldSep(); + break; + default: + jj_la1[29] = jj_gen; + ; + } + {if (true) return fl;} + throw new Error("Missing return statement in function"); + } + + final public TableField Field() throws ParseException { + Token name; + Exp exp,rhs; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case 71: + jj_consume_token(71); + exp = Exp(); + jj_consume_token(72); + jj_consume_token(65); + rhs = Exp(); + {if (true) return TableField.keyedField(exp,rhs);} + break; + default: + jj_la1[30] = jj_gen; + if (jj_2_7(2)) { + name = jj_consume_token(NAME); + jj_consume_token(65); + rhs = Exp(); + {if (true) return TableField.namedField(name.image,rhs);} + } else { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LONGSTRING0: + case LONGSTRING1: + case LONGSTRING2: + case LONGSTRING3: + case LONGSTRINGN: + case FALSE: + case FUNCTION: + case NIL: + case NOT: + case TRUE: + case NAME: + case NUMBER: + case STRING: + case CHARSTRING: + case 69: + case 73: + case 74: + case 77: + case 89: + rhs = Exp(); + {if (true) return TableField.listField(rhs);} + break; + default: + jj_la1[31] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + } + throw new Error("Missing return statement in function"); + } + + final public void FieldSep() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case 66: + jj_consume_token(66); + break; + case 64: + jj_consume_token(64); + break; + default: + jj_la1[32] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + + final public int Binop() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case 76: + jj_consume_token(76); + {if (true) return Lua.OP_ADD;} + break; + case 77: + jj_consume_token(77); + {if (true) return Lua.OP_SUB;} + break; + case 78: + jj_consume_token(78); + {if (true) return Lua.OP_MUL;} + break; + case 79: + jj_consume_token(79); + {if (true) return Lua.OP_DIV;} + break; + case 80: + jj_consume_token(80); + {if (true) return Lua.OP_POW;} + break; + case 81: + jj_consume_token(81); + {if (true) return Lua.OP_MOD;} + break; + case 82: + jj_consume_token(82); + {if (true) return Lua.OP_CONCAT;} + break; + case 83: + jj_consume_token(83); + {if (true) return Lua.OP_LT;} + break; + case 84: + jj_consume_token(84); + {if (true) return Lua.OP_LE;} + break; + case 85: + jj_consume_token(85); + {if (true) return Lua.OP_GT;} + break; + case 86: + jj_consume_token(86); + {if (true) return Lua.OP_GE;} + break; + case 87: + jj_consume_token(87); + {if (true) return Lua.OP_EQ;} + break; + case 88: + jj_consume_token(88); + {if (true) return Lua.OP_NEQ;} + break; + case AND: + jj_consume_token(AND); + {if (true) return Lua.OP_AND;} + break; + case OR: + jj_consume_token(OR); + {if (true) return Lua.OP_OR;} + break; + default: + jj_la1[33] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + throw new Error("Missing return statement in function"); + } + + final public int Unop() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case 77: + jj_consume_token(77); + {if (true) return Lua.OP_UNM;} + break; + case NOT: + jj_consume_token(NOT); + {if (true) return Lua.OP_NOT;} + break; + case 89: + jj_consume_token(89); + {if (true) return Lua.OP_LEN;} + break; + default: + jj_la1[34] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + throw new Error("Missing return statement in function"); + } + + private boolean jj_2_1(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + try { return !jj_3_1(); } + catch(LookaheadSuccess ls) { return true; } + finally { jj_save(0, xla); } + } + + private boolean jj_2_2(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + try { return !jj_3_2(); } + catch(LookaheadSuccess ls) { return true; } + finally { jj_save(1, xla); } + } + + private boolean jj_2_3(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + try { return !jj_3_3(); } + catch(LookaheadSuccess ls) { return true; } + finally { jj_save(2, xla); } + } + + private boolean jj_2_4(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + try { return !jj_3_4(); } + catch(LookaheadSuccess ls) { return true; } + finally { jj_save(3, xla); } + } + + private boolean jj_2_5(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + try { return !jj_3_5(); } + catch(LookaheadSuccess ls) { return true; } + finally { jj_save(4, xla); } + } + + private boolean jj_2_6(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + try { return !jj_3_6(); } + catch(LookaheadSuccess ls) { return true; } + finally { jj_save(5, xla); } + } + + private boolean jj_2_7(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + try { return !jj_3_7(); } + catch(LookaheadSuccess ls) { return true; } + finally { jj_save(6, xla); } + } + + private boolean jj_3R_54() { + if (jj_scan_token(NOT)) return true; + return false; + } + + private boolean jj_3R_53() { + if (jj_scan_token(77)) return true; + return false; + } + + private boolean jj_3R_40() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_53()) { + jj_scanpos = xsp; + if (jj_3R_54()) { + jj_scanpos = xsp; + if (jj_3R_55()) return true; + } + } + return false; + } + + private boolean jj_3R_69() { + if (jj_scan_token(LONGSTRINGN)) return true; + return false; + } + + private boolean jj_3R_68() { + if (jj_scan_token(LONGSTRING3)) return true; + return false; + } + + private boolean jj_3R_67() { + if (jj_scan_token(LONGSTRING2)) return true; + return false; + } + + private boolean jj_3R_66() { + if (jj_scan_token(LONGSTRING1)) return true; + return false; + } + + private boolean jj_3R_33() { + if (jj_scan_token(OR)) return true; + return false; + } + + private boolean jj_3R_65() { + if (jj_scan_token(LONGSTRING0)) return true; + return false; + } + + private boolean jj_3R_32() { + if (jj_scan_token(AND)) return true; + return false; + } + + private boolean jj_3R_64() { + if (jj_scan_token(CHARSTRING)) return true; + return false; + } + + private boolean jj_3R_31() { + if (jj_scan_token(88)) return true; + return false; + } + + private boolean jj_3R_63() { + if (jj_scan_token(STRING)) return true; + return false; + } + + private boolean jj_3R_58() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_63()) { + jj_scanpos = xsp; + if (jj_3R_64()) { + jj_scanpos = xsp; + if (jj_3R_65()) { + jj_scanpos = xsp; + if (jj_3R_66()) { + jj_scanpos = xsp; + if (jj_3R_67()) { + jj_scanpos = xsp; + if (jj_3R_68()) { + jj_scanpos = xsp; + if (jj_3R_69()) return true; + } + } + } + } + } + } + return false; + } + + private boolean jj_3R_30() { + if (jj_scan_token(87)) return true; + return false; + } + + private boolean jj_3R_29() { + if (jj_scan_token(86)) return true; + return false; + } + + private boolean jj_3R_28() { + if (jj_scan_token(85)) return true; + return false; + } + + private boolean jj_3R_27() { + if (jj_scan_token(84)) return true; + return false; + } + + private boolean jj_3R_26() { + if (jj_scan_token(83)) return true; + return false; + } + + private boolean jj_3R_25() { + if (jj_scan_token(82)) return true; + return false; + } + + private boolean jj_3R_52() { + if (jj_3R_60()) return true; + return false; + } + + private boolean jj_3R_24() { + if (jj_scan_token(81)) return true; + return false; + } + + private boolean jj_3R_51() { + if (jj_3R_59()) return true; + return false; + } + + private boolean jj_3R_23() { + if (jj_scan_token(80)) return true; + return false; + } + + private boolean jj_3R_50() { + if (jj_3R_57()) return true; + return false; + } + + private boolean jj_3R_22() { + if (jj_scan_token(79)) return true; + return false; + } + + private boolean jj_3R_49() { + if (jj_scan_token(73)) return true; + return false; + } + + private boolean jj_3R_21() { + if (jj_scan_token(78)) return true; + return false; + } + + private boolean jj_3R_48() { + if (jj_3R_58()) return true; + return false; + } + + private boolean jj_3_6() { + if (jj_3R_13()) return true; + if (jj_3R_14()) return true; + return false; + } + + private boolean jj_3R_20() { + if (jj_scan_token(77)) return true; + return false; + } + + private boolean jj_3R_47() { + if (jj_scan_token(NUMBER)) return true; + return false; + } + + private boolean jj_3R_19() { + if (jj_scan_token(76)) return true; + return false; + } + + private boolean jj_3R_11() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_19()) { + jj_scanpos = xsp; + if (jj_3R_20()) { + jj_scanpos = xsp; + if (jj_3R_21()) { + jj_scanpos = xsp; + if (jj_3R_22()) { + jj_scanpos = xsp; + if (jj_3R_23()) { + jj_scanpos = xsp; + if (jj_3R_24()) { + jj_scanpos = xsp; + if (jj_3R_25()) { + jj_scanpos = xsp; + if (jj_3R_26()) { + jj_scanpos = xsp; + if (jj_3R_27()) { + jj_scanpos = xsp; + if (jj_3R_28()) { + jj_scanpos = xsp; + if (jj_3R_29()) { + jj_scanpos = xsp; + if (jj_3R_30()) { + jj_scanpos = xsp; + if (jj_3R_31()) { + jj_scanpos = xsp; + if (jj_3R_32()) { + jj_scanpos = xsp; + if (jj_3R_33()) return true; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + return false; + } + + private boolean jj_3R_46() { + if (jj_scan_token(FALSE)) return true; + return false; + } + + private boolean jj_3R_45() { + if (jj_scan_token(TRUE)) return true; + return false; + } + + private boolean jj_3R_44() { + if (jj_scan_token(NIL)) return true; + return false; + } + + private boolean jj_3R_39() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_44()) { + jj_scanpos = xsp; + if (jj_3R_45()) { + jj_scanpos = xsp; + if (jj_3R_46()) { + jj_scanpos = xsp; + if (jj_3R_47()) { + jj_scanpos = xsp; + if (jj_3R_48()) { + jj_scanpos = xsp; + if (jj_3R_49()) { + jj_scanpos = xsp; + if (jj_3R_50()) { + jj_scanpos = xsp; + if (jj_3R_51()) { + jj_scanpos = xsp; + if (jj_3R_52()) return true; + } + } + } + } + } + } + } + } + return false; + } + + private boolean jj_3R_13() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(66)) { + jj_scanpos = xsp; + if (jj_scan_token(64)) return true; + } + return false; + } + + private boolean jj_3R_37() { + if (jj_3R_12()) return true; + return false; + } + + private boolean jj_3_7() { + if (jj_scan_token(NAME)) return true; + if (jj_scan_token(65)) return true; + return false; + } + + private boolean jj_3R_14() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_36()) { + jj_scanpos = xsp; + if (jj_3_7()) { + jj_scanpos = xsp; + if (jj_3R_37()) return true; + } + } + return false; + } + + private boolean jj_3R_36() { + if (jj_scan_token(71)) return true; + return false; + } + + private boolean jj_3R_61() { + if (jj_3R_12()) return true; + return false; + } + + private boolean jj_3R_71() { + if (jj_3R_14()) return true; + return false; + } + + private boolean jj_3R_62() { + if (jj_3R_71()) return true; + return false; + } + + private boolean jj_3R_56() { + if (jj_3R_61()) return true; + return false; + } + + private boolean jj_3R_57() { + if (jj_scan_token(74)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_62()) jj_scanpos = xsp; + if (jj_scan_token(75)) return true; + return false; + } + + private boolean jj_3R_43() { + if (jj_3R_58()) return true; + return false; + } + + private boolean jj_3R_42() { + if (jj_3R_57()) return true; + return false; + } + + private boolean jj_3R_41() { + if (jj_scan_token(69)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_56()) jj_scanpos = xsp; + if (jj_scan_token(70)) return true; + return false; + } + + private boolean jj_3R_38() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_41()) { + jj_scanpos = xsp; + if (jj_3R_42()) { + jj_scanpos = xsp; + if (jj_3R_43()) return true; + } + } + return false; + } + + private boolean jj_3_3() { + if (jj_3R_10()) return true; + return false; + } + + private boolean jj_3R_18() { + if (jj_3R_38()) return true; + return false; + } + + private boolean jj_3R_17() { + if (jj_scan_token(68)) return true; + if (jj_scan_token(NAME)) return true; + return false; + } + + private boolean jj_3R_16() { + if (jj_scan_token(71)) return true; + if (jj_3R_12()) return true; + return false; + } + + private boolean jj_3R_15() { + if (jj_scan_token(67)) return true; + if (jj_scan_token(NAME)) return true; + return false; + } + + private boolean jj_3R_10() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_15()) { + jj_scanpos = xsp; + if (jj_3R_16()) { + jj_scanpos = xsp; + if (jj_3R_17()) { + jj_scanpos = xsp; + if (jj_3R_18()) return true; + } + } + } + return false; + } + + private boolean jj_3R_35() { + if (jj_3R_40()) return true; + return false; + } + + private boolean jj_3_2() { + if (jj_scan_token(LOCAL)) return true; + if (jj_scan_token(FUNCTION)) return true; + return false; + } + + private boolean jj_3_1() { + if (jj_scan_token(FOR)) return true; + if (jj_scan_token(NAME)) return true; + if (jj_scan_token(65)) return true; + return false; + } + + private boolean jj_3R_60() { + if (jj_3R_70()) return true; + return false; + } + + private boolean jj_3_5() { + if (jj_3R_11()) return true; + if (jj_3R_12()) return true; + return false; + } + + private boolean jj_3R_59() { + if (jj_scan_token(FUNCTION)) return true; + return false; + } + + private boolean jj_3R_73() { + if (jj_scan_token(69)) return true; + return false; + } + + private boolean jj_3R_72() { + if (jj_scan_token(NAME)) return true; + return false; + } + + private boolean jj_3R_70() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_72()) { + jj_scanpos = xsp; + if (jj_3R_73()) return true; + } + return false; + } + + private boolean jj_3R_34() { + if (jj_3R_39()) return true; + return false; + } + + private boolean jj_3R_12() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_34()) { + jj_scanpos = xsp; + if (jj_3R_35()) return true; + } + return false; + } + + private boolean jj_3R_55() { + if (jj_scan_token(89)) return true; + return false; + } + + private boolean jj_3_4() { + if (jj_scan_token(66)) return true; + if (jj_scan_token(NAME)) return true; + return false; + } + + /** Generated Token Manager. */ + public LuaParserTokenManager token_source; + SimpleCharStream jj_input_stream; + /** Current token. */ + public Token token; + /** Next token. */ + public Token jj_nt; + private int jj_ntk; + private Token jj_scanpos, jj_lastpos; + private int jj_la; + private int jj_gen; + final private int[] jj_la1 = new int[35]; + static private int[] jj_la1_0; + static private int[] jj_la1_1; + static private int[] jj_la1_2; + static { + jj_la1_init_0(); + jj_la1_init_1(); + jj_la1_init_2(); + } + private static void jj_la1_init_0() { + jj_la1_0 = new int[] {0x80000000,0x0,0x0,0x40000000,0x0,0x0,0x80000000,0x0,0x0,0x0,0x0,0xf800000,0x40000000,0x0,0x0,0x0,0x0,0x0,0xf800000,0xf800000,0xf800000,0x0,0xf800000,0xf800000,0xf800000,0x0,0x0,0x0,0xf800000,0x0,0x0,0xf800000,0x0,0x20000000,0x0,}; + } + private static void jj_la1_init_1() { + jj_la1_1 = new int[] {0x62170,0x0,0x0,0x1000,0x0,0x0,0x22040,0x30,0x40100,0x2,0x1,0x60c8628,0x1000,0x0,0x0,0x0,0x0,0x40000,0x6000000,0x60c8628,0x6000000,0x0,0x60c8228,0x6000000,0x60c8628,0x40000,0x0,0x40000,0x60c8628,0x0,0x0,0x60c8628,0x0,0x800,0x400,}; + } + private static void jj_la1_init_2() { + jj_la1_2 = new int[] {0x20,0x1,0x1,0x0,0x4,0x2,0x0,0x0,0x20,0x0,0x0,0x2002620,0x0,0x6,0x4,0x8,0x10,0x20,0x4b8,0x2002620,0x420,0x4,0x620,0x0,0x2002620,0x200,0x4,0x200,0x20026a0,0x5,0x80,0x2002620,0x5,0x1fff000,0x2002000,}; + } + final private JJCalls[] jj_2_rtns = new JJCalls[7]; + private boolean jj_rescan = false; + private int jj_gc = 0; + + /** Constructor with InputStream. */ + public LuaParser(java.io.InputStream stream) { + this(stream, null); + } + /** Constructor with InputStream and supplied encoding */ + public LuaParser(java.io.InputStream stream, String encoding) { + try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e.getMessage()); } + token_source = new LuaParserTokenManager(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 35; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + /** Reinitialise. */ + public void ReInit(java.io.InputStream stream) { + ReInit(stream, null); + } + /** Reinitialise. */ + public void ReInit(java.io.InputStream stream, String encoding) { + try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e.getMessage()); } + token_source.ReInit(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 35; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + /** Constructor. */ + public LuaParser(java.io.Reader stream) { + jj_input_stream = new SimpleCharStream(stream, 1, 1); + token_source = new LuaParserTokenManager(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 35; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + /** Reinitialise. */ + public void ReInit(java.io.Reader stream) { + jj_input_stream.ReInit(stream, 1, 1); + token_source.ReInit(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 35; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + /** Constructor with generated Token Manager. */ + public LuaParser(LuaParserTokenManager tm) { + token_source = tm; + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 35; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + /** Reinitialise. */ + public void ReInit(LuaParserTokenManager tm) { + token_source = tm; + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 35; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + private Token jj_consume_token(int kind) throws ParseException { + Token oldToken; + if ((oldToken = token).next != null) token = token.next; + else token = token.next = token_source.getNextToken(); + jj_ntk = -1; + if (token.kind == kind) { + jj_gen++; + if (++jj_gc > 100) { + jj_gc = 0; + for (int i = 0; i < jj_2_rtns.length; i++) { + JJCalls c = jj_2_rtns[i]; + while (c != null) { + if (c.gen < jj_gen) c.first = null; + c = c.next; + } + } + } + return token; + } + token = oldToken; + jj_kind = kind; + throw generateParseException(); + } + + static private final class LookaheadSuccess extends java.lang.Error { } + final private LookaheadSuccess jj_ls = new LookaheadSuccess(); + private boolean jj_scan_token(int kind) { + if (jj_scanpos == jj_lastpos) { + jj_la--; + if (jj_scanpos.next == null) { + jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken(); + } else { + jj_lastpos = jj_scanpos = jj_scanpos.next; + } + } else { + jj_scanpos = jj_scanpos.next; + } + if (jj_rescan) { + int i = 0; Token tok = token; + while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; } + if (tok != null) jj_add_error_token(kind, i); + } + if (jj_scanpos.kind != kind) return true; + if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls; + return false; + } + + +/** Get the next Token. */ + final public Token getNextToken() { + if (token.next != null) token = token.next; + else token = token.next = token_source.getNextToken(); + jj_ntk = -1; + jj_gen++; + return token; + } + +/** Get the specific Token. */ + final public Token getToken(int index) { + Token t = token; + for (int i = 0; i < index; i++) { + if (t.next != null) t = t.next; + else t = t.next = token_source.getNextToken(); + } + return t; + } + + private int jj_ntk() { + if ((jj_nt=token.next) == null) + return (jj_ntk = (token.next=token_source.getNextToken()).kind); + else + return (jj_ntk = jj_nt.kind); + } + + private java.util.List jj_expentries = new java.util.ArrayList(); + private int[] jj_expentry; + private int jj_kind = -1; + private int[] jj_lasttokens = new int[100]; + private int jj_endpos; + + private void jj_add_error_token(int kind, int pos) { + if (pos >= 100) return; + if (pos == jj_endpos + 1) { + jj_lasttokens[jj_endpos++] = kind; + } else if (jj_endpos != 0) { + jj_expentry = new int[jj_endpos]; + for (int i = 0; i < jj_endpos; i++) { + jj_expentry[i] = jj_lasttokens[i]; + } + jj_entries_loop: for (java.util.Iterator it = jj_expentries.iterator(); it.hasNext();) { + int[] oldentry = (int[])(it.next()); + if (oldentry.length == jj_expentry.length) { + for (int i = 0; i < jj_expentry.length; i++) { + if (oldentry[i] != jj_expentry[i]) { + continue jj_entries_loop; + } + } + jj_expentries.add(jj_expentry); + break jj_entries_loop; + } + } + if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind; + } + } + + /** Generate ParseException. */ + public ParseException generateParseException() { + jj_expentries.clear(); + boolean[] la1tokens = new boolean[90]; + if (jj_kind >= 0) { + la1tokens[jj_kind] = true; + jj_kind = -1; + } + for (int i = 0; i < 35; i++) { + if (jj_la1[i] == jj_gen) { + for (int j = 0; j < 32; j++) { + if ((jj_la1_0[i] & (1< jj_gen) { + jj_la = p.arg; jj_lastpos = jj_scanpos = p.first; + switch (i) { + case 0: jj_3_1(); break; + case 1: jj_3_2(); break; + case 2: jj_3_3(); break; + case 3: jj_3_4(); break; + case 4: jj_3_5(); break; + case 5: jj_3_6(); break; + case 6: jj_3_7(); break; + } + } + p = p.next; + } while (p != null); + } catch(LookaheadSuccess ls) { } + } + jj_rescan = false; + } + + private void jj_save(int index, int xla) { + JJCalls p = jj_2_rtns[index]; + while (p.gen > jj_gen) { + if (p.next == null) { p = p.next = new JJCalls(); break; } + p = p.next; + } + p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla; + } + + static final class JJCalls { + int gen; + Token first; + int arg; + JJCalls next; + } + +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/parser/LuaParserConstants.java b/luaj-2.0.3/src/jse/org/luaj/vm2/parser/LuaParserConstants.java new file mode 100644 index 0000000000..05405af76e --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/parser/LuaParserConstants.java @@ -0,0 +1,225 @@ +/* Generated By:JavaCC: Do not edit this line. LuaParserConstants.java */ +package org.luaj.vm2.parser; + + +/** + * Token literal values and constants. + * Generated by org.javacc.parser.OtherFilesGen#start() + */ +public interface LuaParserConstants { + + /** End of File. */ + int EOF = 0; + /** RegularExpression Id. */ + int COMMENT = 17; + /** RegularExpression Id. */ + int LONGCOMMENT0 = 18; + /** RegularExpression Id. */ + int LONGCOMMENT1 = 19; + /** RegularExpression Id. */ + int LONGCOMMENT2 = 20; + /** RegularExpression Id. */ + int LONGCOMMENT3 = 21; + /** RegularExpression Id. */ + int LONGCOMMENTN = 22; + /** RegularExpression Id. */ + int LONGSTRING0 = 23; + /** RegularExpression Id. */ + int LONGSTRING1 = 24; + /** RegularExpression Id. */ + int LONGSTRING2 = 25; + /** RegularExpression Id. */ + int LONGSTRING3 = 26; + /** RegularExpression Id. */ + int LONGSTRINGN = 27; + /** RegularExpression Id. */ + int AND = 29; + /** RegularExpression Id. */ + int BREAK = 30; + /** RegularExpression Id. */ + int DO = 31; + /** RegularExpression Id. */ + int ELSE = 32; + /** RegularExpression Id. */ + int ELSEIF = 33; + /** RegularExpression Id. */ + int END = 34; + /** RegularExpression Id. */ + int FALSE = 35; + /** RegularExpression Id. */ + int FOR = 36; + /** RegularExpression Id. */ + int FUNCTION = 37; + /** RegularExpression Id. */ + int IF = 38; + /** RegularExpression Id. */ + int IN = 39; + /** RegularExpression Id. */ + int LOCAL = 40; + /** RegularExpression Id. */ + int NIL = 41; + /** RegularExpression Id. */ + int NOT = 42; + /** RegularExpression Id. */ + int OR = 43; + /** RegularExpression Id. */ + int RETURN = 44; + /** RegularExpression Id. */ + int REPEAT = 45; + /** RegularExpression Id. */ + int THEN = 46; + /** RegularExpression Id. */ + int TRUE = 47; + /** RegularExpression Id. */ + int UNTIL = 48; + /** RegularExpression Id. */ + int WHILE = 49; + /** RegularExpression Id. */ + int NAME = 50; + /** RegularExpression Id. */ + int NUMBER = 51; + /** RegularExpression Id. */ + int FLOAT = 52; + /** RegularExpression Id. */ + int DIGIT = 53; + /** RegularExpression Id. */ + int EXP = 54; + /** RegularExpression Id. */ + int HEX = 55; + /** RegularExpression Id. */ + int HEXDIGIT = 56; + /** RegularExpression Id. */ + int STRING = 57; + /** RegularExpression Id. */ + int CHARSTRING = 58; + /** RegularExpression Id. */ + int QUOTED = 59; + /** RegularExpression Id. */ + int DECIMAL = 60; + /** RegularExpression Id. */ + int UNICODE = 61; + /** RegularExpression Id. */ + int CHAR = 62; + /** RegularExpression Id. */ + int LF = 63; + + /** Lexical state. */ + int DEFAULT = 0; + /** Lexical state. */ + int IN_COMMENT = 1; + /** Lexical state. */ + int IN_LC0 = 2; + /** Lexical state. */ + int IN_LC1 = 3; + /** Lexical state. */ + int IN_LC2 = 4; + /** Lexical state. */ + int IN_LC3 = 5; + /** Lexical state. */ + int IN_LCN = 6; + /** Lexical state. */ + int IN_LS0 = 7; + /** Lexical state. */ + int IN_LS1 = 8; + /** Lexical state. */ + int IN_LS2 = 9; + /** Lexical state. */ + int IN_LS3 = 10; + /** Lexical state. */ + int IN_LSN = 11; + + /** Literal token values. */ + String[] tokenImage = { + "", + "\" \"", + "\"\\t\"", + "\"\\n\"", + "\"\\r\"", + "\"\\f\"", + "\"--[[\"", + "\"--[=[\"", + "\"--[==[\"", + "\"--[===[\"", + "", + "\"[[\"", + "\"[=[\"", + "\"[==[\"", + "\"[===[\"", + "", + "\"--\"", + "", + "\"]]\"", + "\"]=]\"", + "\"]==]\"", + "\"]===]\"", + "", + "\"]]\"", + "\"]=]\"", + "\"]==]\"", + "\"]===]\"", + "", + "", + "\"and\"", + "\"break\"", + "\"do\"", + "\"else\"", + "\"elseif\"", + "\"end\"", + "\"false\"", + "\"for\"", + "\"function\"", + "\"if\"", + "\"in\"", + "\"local\"", + "\"nil\"", + "\"not\"", + "\"or\"", + "\"return\"", + "\"repeat\"", + "\"then\"", + "\"true\"", + "\"until\"", + "\"while\"", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\";\"", + "\"=\"", + "\",\"", + "\".\"", + "\":\"", + "\"(\"", + "\")\"", + "\"[\"", + "\"]\"", + "\"...\"", + "\"{\"", + "\"}\"", + "\"+\"", + "\"-\"", + "\"*\"", + "\"/\"", + "\"^\"", + "\"%\"", + "\"..\"", + "\"<\"", + "\"<=\"", + "\">\"", + "\">=\"", + "\"==\"", + "\"~=\"", + "\"#\"", + }; + +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/parser/LuaParserTokenManager.java b/luaj-2.0.3/src/jse/org/luaj/vm2/parser/LuaParserTokenManager.java new file mode 100644 index 0000000000..1537982884 --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/parser/LuaParserTokenManager.java @@ -0,0 +1,2045 @@ +/* Generated By:JavaCC: Do not edit this line. LuaParserTokenManager.java */ +package org.luaj.vm2.parser; +import org.luaj.vm2.*; +import org.luaj.vm2.ast.*; +import java.util.*; + +/** Token Manager. */ +public class LuaParserTokenManager implements LuaParserConstants +{ + + /** Debug output. */ + public java.io.PrintStream debugStream = System.out; + /** Set debug output. */ + public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; } +private int jjStopAtPos(int pos, int kind) +{ + jjmatchedKind = kind; + jjmatchedPos = pos; + return pos + 1; +} +private int jjMoveStringLiteralDfa0_2() +{ + switch(curChar) + { + case 93: + return jjMoveStringLiteralDfa1_2(0x40000L); + default : + return 1; + } +} +private int jjMoveStringLiteralDfa1_2(long active0) +{ + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 1; + } + switch(curChar) + { + case 93: + if ((active0 & 0x40000L) != 0L) + return jjStopAtPos(1, 18); + break; + default : + return 2; + } + return 2; +} +private int jjMoveStringLiteralDfa0_11() +{ + return jjMoveNfa_11(6, 0); +} +private int jjMoveNfa_11(int startState, int curPos) +{ + int startsAt = 0; + jjnewStateCnt = 7; + int i = 1; + jjstateSet[0] = startState; + int kind = 0x7fffffff; + for (;;) + { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) + { + long l = 1L << curChar; + do + { + switch(jjstateSet[--i]) + { + case 0: + case 1: + if (curChar == 61) + jjCheckNAddTwoStates(1, 2); + break; + case 3: + if (curChar == 61) + jjstateSet[jjnewStateCnt++] = 0; + break; + case 4: + if (curChar == 61) + jjstateSet[jjnewStateCnt++] = 3; + break; + case 5: + if (curChar == 61) + jjstateSet[jjnewStateCnt++] = 4; + break; + default : break; + } + } while(i != startsAt); + } + else if (curChar < 128) + { + long l = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + case 2: + if (curChar == 93 && kind > 27) + kind = 27; + break; + case 6: + if (curChar == 93) + jjstateSet[jjnewStateCnt++] = 5; + break; + default : break; + } + } while(i != startsAt); + } + else + { + int hiByte = (int)(curChar >> 8); + int i1 = hiByte >> 6; + long l1 = 1L << (hiByte & 077); + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + default : break; + } + } while(i != startsAt); + } + if (kind != 0x7fffffff) + { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 7 - (jjnewStateCnt = startsAt))) + return curPos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return curPos; } + } +} +private int jjMoveStringLiteralDfa0_10() +{ + switch(curChar) + { + case 93: + return jjMoveStringLiteralDfa1_10(0x4000000L); + default : + return 1; + } +} +private int jjMoveStringLiteralDfa1_10(long active0) +{ + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 1; + } + switch(curChar) + { + case 61: + return jjMoveStringLiteralDfa2_10(active0, 0x4000000L); + default : + return 2; + } +} +private int jjMoveStringLiteralDfa2_10(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return 2; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 2; + } + switch(curChar) + { + case 61: + return jjMoveStringLiteralDfa3_10(active0, 0x4000000L); + default : + return 3; + } +} +private int jjMoveStringLiteralDfa3_10(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return 3; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 3; + } + switch(curChar) + { + case 61: + return jjMoveStringLiteralDfa4_10(active0, 0x4000000L); + default : + return 4; + } +} +private int jjMoveStringLiteralDfa4_10(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return 4; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 4; + } + switch(curChar) + { + case 93: + if ((active0 & 0x4000000L) != 0L) + return jjStopAtPos(4, 26); + break; + default : + return 5; + } + return 5; +} +private int jjMoveStringLiteralDfa0_9() +{ + switch(curChar) + { + case 93: + return jjMoveStringLiteralDfa1_9(0x2000000L); + default : + return 1; + } +} +private int jjMoveStringLiteralDfa1_9(long active0) +{ + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 1; + } + switch(curChar) + { + case 61: + return jjMoveStringLiteralDfa2_9(active0, 0x2000000L); + default : + return 2; + } +} +private int jjMoveStringLiteralDfa2_9(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return 2; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 2; + } + switch(curChar) + { + case 61: + return jjMoveStringLiteralDfa3_9(active0, 0x2000000L); + default : + return 3; + } +} +private int jjMoveStringLiteralDfa3_9(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return 3; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 3; + } + switch(curChar) + { + case 93: + if ((active0 & 0x2000000L) != 0L) + return jjStopAtPos(3, 25); + break; + default : + return 4; + } + return 4; +} +private int jjMoveStringLiteralDfa0_8() +{ + switch(curChar) + { + case 93: + return jjMoveStringLiteralDfa1_8(0x1000000L); + default : + return 1; + } +} +private int jjMoveStringLiteralDfa1_8(long active0) +{ + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 1; + } + switch(curChar) + { + case 61: + return jjMoveStringLiteralDfa2_8(active0, 0x1000000L); + default : + return 2; + } +} +private int jjMoveStringLiteralDfa2_8(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return 2; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 2; + } + switch(curChar) + { + case 93: + if ((active0 & 0x1000000L) != 0L) + return jjStopAtPos(2, 24); + break; + default : + return 3; + } + return 3; +} +private int jjMoveStringLiteralDfa0_7() +{ + switch(curChar) + { + case 93: + return jjMoveStringLiteralDfa1_7(0x800000L); + default : + return 1; + } +} +private int jjMoveStringLiteralDfa1_7(long active0) +{ + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 1; + } + switch(curChar) + { + case 93: + if ((active0 & 0x800000L) != 0L) + return jjStopAtPos(1, 23); + break; + default : + return 2; + } + return 2; +} +private final int jjStopStringLiteralDfa_0(int pos, long active0, long active1) +{ + switch (pos) + { + case 0: + if ((active1 & 0x40208L) != 0L) + return 22; + if ((active0 & 0x7800L) != 0L || (active1 & 0x80L) != 0L) + return 14; + if ((active0 & 0x3ffffe0000000L) != 0L) + { + jjmatchedKind = 50; + return 17; + } + if ((active0 & 0x103c0L) != 0L || (active1 & 0x2000L) != 0L) + return 7; + return -1; + case 1: + if ((active0 & 0x103c0L) != 0L) + return 6; + if ((active0 & 0x7000L) != 0L) + return 13; + if ((active0 & 0x8c080000000L) != 0L) + return 17; + if ((active0 & 0x3f73f60000000L) != 0L) + { + if (jjmatchedPos != 1) + { + jjmatchedKind = 50; + jjmatchedPos = 1; + } + return 17; + } + return -1; + case 2: + if ((active0 & 0x3f12b40000000L) != 0L) + { + jjmatchedKind = 50; + jjmatchedPos = 2; + return 17; + } + if ((active0 & 0x6000L) != 0L) + return 12; + if ((active0 & 0x3c0L) != 0L) + return 5; + if ((active0 & 0x61420000000L) != 0L) + return 17; + return -1; + case 3: + if ((active0 & 0x380L) != 0L) + return 4; + if ((active0 & 0x3312840000000L) != 0L) + { + if (jjmatchedPos != 3) + { + jjmatchedKind = 50; + jjmatchedPos = 3; + } + return 17; + } + if ((active0 & 0xc00300000000L) != 0L) + return 17; + if ((active0 & 0x4000L) != 0L) + return 9; + return -1; + case 4: + if ((active0 & 0x300L) != 0L) + return 3; + if ((active0 & 0x302200000000L) != 0L) + { + jjmatchedKind = 50; + jjmatchedPos = 4; + return 17; + } + if ((active0 & 0x3010840000000L) != 0L) + return 17; + return -1; + case 5: + if ((active0 & 0x200L) != 0L) + return 0; + if ((active0 & 0x2000000000L) != 0L) + { + jjmatchedKind = 50; + jjmatchedPos = 5; + return 17; + } + if ((active0 & 0x300200000000L) != 0L) + return 17; + return -1; + case 6: + if ((active0 & 0x2000000000L) != 0L) + { + jjmatchedKind = 50; + jjmatchedPos = 6; + return 17; + } + return -1; + default : + return -1; + } +} +private final int jjStartNfa_0(int pos, long active0, long active1) +{ + return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0, active1), pos + 1); +} +private int jjMoveStringLiteralDfa0_0() +{ + switch(curChar) + { + case 35: + return jjStopAtPos(0, 89); + case 37: + return jjStopAtPos(0, 81); + case 40: + return jjStopAtPos(0, 69); + case 41: + return jjStopAtPos(0, 70); + case 42: + return jjStopAtPos(0, 78); + case 43: + return jjStopAtPos(0, 76); + case 44: + return jjStopAtPos(0, 66); + case 45: + jjmatchedKind = 77; + return jjMoveStringLiteralDfa1_0(0x103c0L, 0x0L); + case 46: + jjmatchedKind = 67; + return jjMoveStringLiteralDfa1_0(0x0L, 0x40200L); + case 47: + return jjStopAtPos(0, 79); + case 58: + return jjStopAtPos(0, 68); + case 59: + return jjStopAtPos(0, 64); + case 60: + jjmatchedKind = 83; + return jjMoveStringLiteralDfa1_0(0x0L, 0x100000L); + case 61: + jjmatchedKind = 65; + return jjMoveStringLiteralDfa1_0(0x0L, 0x800000L); + case 62: + jjmatchedKind = 85; + return jjMoveStringLiteralDfa1_0(0x0L, 0x400000L); + case 91: + jjmatchedKind = 71; + return jjMoveStringLiteralDfa1_0(0x7800L, 0x0L); + case 93: + return jjStopAtPos(0, 72); + case 94: + return jjStopAtPos(0, 80); + case 97: + return jjMoveStringLiteralDfa1_0(0x20000000L, 0x0L); + case 98: + return jjMoveStringLiteralDfa1_0(0x40000000L, 0x0L); + case 100: + return jjMoveStringLiteralDfa1_0(0x80000000L, 0x0L); + case 101: + return jjMoveStringLiteralDfa1_0(0x700000000L, 0x0L); + case 102: + return jjMoveStringLiteralDfa1_0(0x3800000000L, 0x0L); + case 105: + return jjMoveStringLiteralDfa1_0(0xc000000000L, 0x0L); + case 108: + return jjMoveStringLiteralDfa1_0(0x10000000000L, 0x0L); + case 110: + return jjMoveStringLiteralDfa1_0(0x60000000000L, 0x0L); + case 111: + return jjMoveStringLiteralDfa1_0(0x80000000000L, 0x0L); + case 114: + return jjMoveStringLiteralDfa1_0(0x300000000000L, 0x0L); + case 116: + return jjMoveStringLiteralDfa1_0(0xc00000000000L, 0x0L); + case 117: + return jjMoveStringLiteralDfa1_0(0x1000000000000L, 0x0L); + case 119: + return jjMoveStringLiteralDfa1_0(0x2000000000000L, 0x0L); + case 123: + return jjStopAtPos(0, 74); + case 125: + return jjStopAtPos(0, 75); + case 126: + return jjMoveStringLiteralDfa1_0(0x0L, 0x1000000L); + default : + return jjMoveNfa_0(8, 0); + } +} +private int jjMoveStringLiteralDfa1_0(long active0, long active1) +{ + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(0, active0, active1); + return 1; + } + switch(curChar) + { + case 45: + if ((active0 & 0x10000L) != 0L) + { + jjmatchedKind = 16; + jjmatchedPos = 1; + } + return jjMoveStringLiteralDfa2_0(active0, 0x3c0L, active1, 0L); + case 46: + if ((active1 & 0x40000L) != 0L) + { + jjmatchedKind = 82; + jjmatchedPos = 1; + } + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x200L); + case 61: + if ((active1 & 0x100000L) != 0L) + return jjStopAtPos(1, 84); + else if ((active1 & 0x400000L) != 0L) + return jjStopAtPos(1, 86); + else if ((active1 & 0x800000L) != 0L) + return jjStopAtPos(1, 87); + else if ((active1 & 0x1000000L) != 0L) + return jjStopAtPos(1, 88); + return jjMoveStringLiteralDfa2_0(active0, 0x7000L, active1, 0L); + case 91: + if ((active0 & 0x800L) != 0L) + return jjStopAtPos(1, 11); + break; + case 97: + return jjMoveStringLiteralDfa2_0(active0, 0x800000000L, active1, 0L); + case 101: + return jjMoveStringLiteralDfa2_0(active0, 0x300000000000L, active1, 0L); + case 102: + if ((active0 & 0x4000000000L) != 0L) + return jjStartNfaWithStates_0(1, 38, 17); + break; + case 104: + return jjMoveStringLiteralDfa2_0(active0, 0x2400000000000L, active1, 0L); + case 105: + return jjMoveStringLiteralDfa2_0(active0, 0x20000000000L, active1, 0L); + case 108: + return jjMoveStringLiteralDfa2_0(active0, 0x300000000L, active1, 0L); + case 110: + if ((active0 & 0x8000000000L) != 0L) + return jjStartNfaWithStates_0(1, 39, 17); + return jjMoveStringLiteralDfa2_0(active0, 0x1000420000000L, active1, 0L); + case 111: + if ((active0 & 0x80000000L) != 0L) + return jjStartNfaWithStates_0(1, 31, 17); + return jjMoveStringLiteralDfa2_0(active0, 0x51000000000L, active1, 0L); + case 114: + if ((active0 & 0x80000000000L) != 0L) + return jjStartNfaWithStates_0(1, 43, 17); + return jjMoveStringLiteralDfa2_0(active0, 0x800040000000L, active1, 0L); + case 117: + return jjMoveStringLiteralDfa2_0(active0, 0x2000000000L, active1, 0L); + default : + break; + } + return jjStartNfa_0(0, active0, active1); +} +private int jjMoveStringLiteralDfa2_0(long old0, long active0, long old1, long active1) +{ + if (((active0 &= old0) | (active1 &= old1)) == 0L) + return jjStartNfa_0(0, old0, old1); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(1, active0, active1); + return 2; + } + switch(curChar) + { + case 46: + if ((active1 & 0x200L) != 0L) + return jjStopAtPos(2, 73); + break; + case 61: + return jjMoveStringLiteralDfa3_0(active0, 0x6000L, active1, 0L); + case 91: + if ((active0 & 0x1000L) != 0L) + return jjStopAtPos(2, 12); + return jjMoveStringLiteralDfa3_0(active0, 0x3c0L, active1, 0L); + case 99: + return jjMoveStringLiteralDfa3_0(active0, 0x10000000000L, active1, 0L); + case 100: + if ((active0 & 0x20000000L) != 0L) + return jjStartNfaWithStates_0(2, 29, 17); + else if ((active0 & 0x400000000L) != 0L) + return jjStartNfaWithStates_0(2, 34, 17); + break; + case 101: + return jjMoveStringLiteralDfa3_0(active0, 0x400040000000L, active1, 0L); + case 105: + return jjMoveStringLiteralDfa3_0(active0, 0x2000000000000L, active1, 0L); + case 108: + if ((active0 & 0x20000000000L) != 0L) + return jjStartNfaWithStates_0(2, 41, 17); + return jjMoveStringLiteralDfa3_0(active0, 0x800000000L, active1, 0L); + case 110: + return jjMoveStringLiteralDfa3_0(active0, 0x2000000000L, active1, 0L); + case 112: + return jjMoveStringLiteralDfa3_0(active0, 0x200000000000L, active1, 0L); + case 114: + if ((active0 & 0x1000000000L) != 0L) + return jjStartNfaWithStates_0(2, 36, 17); + break; + case 115: + return jjMoveStringLiteralDfa3_0(active0, 0x300000000L, active1, 0L); + case 116: + if ((active0 & 0x40000000000L) != 0L) + return jjStartNfaWithStates_0(2, 42, 17); + return jjMoveStringLiteralDfa3_0(active0, 0x1100000000000L, active1, 0L); + case 117: + return jjMoveStringLiteralDfa3_0(active0, 0x800000000000L, active1, 0L); + default : + break; + } + return jjStartNfa_0(1, active0, active1); +} +private int jjMoveStringLiteralDfa3_0(long old0, long active0, long old1, long active1) +{ + if (((active0 &= old0) | (active1 &= old1)) == 0L) + return jjStartNfa_0(1, old0, old1); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(2, active0, 0L); + return 3; + } + switch(curChar) + { + case 61: + return jjMoveStringLiteralDfa4_0(active0, 0x4380L); + case 91: + if ((active0 & 0x40L) != 0L) + return jjStopAtPos(3, 6); + else if ((active0 & 0x2000L) != 0L) + return jjStopAtPos(3, 13); + break; + case 97: + return jjMoveStringLiteralDfa4_0(active0, 0x10040000000L); + case 99: + return jjMoveStringLiteralDfa4_0(active0, 0x2000000000L); + case 101: + if ((active0 & 0x100000000L) != 0L) + { + jjmatchedKind = 32; + jjmatchedPos = 3; + } + else if ((active0 & 0x800000000000L) != 0L) + return jjStartNfaWithStates_0(3, 47, 17); + return jjMoveStringLiteralDfa4_0(active0, 0x200200000000L); + case 105: + return jjMoveStringLiteralDfa4_0(active0, 0x1000000000000L); + case 108: + return jjMoveStringLiteralDfa4_0(active0, 0x2000000000000L); + case 110: + if ((active0 & 0x400000000000L) != 0L) + return jjStartNfaWithStates_0(3, 46, 17); + break; + case 115: + return jjMoveStringLiteralDfa4_0(active0, 0x800000000L); + case 117: + return jjMoveStringLiteralDfa4_0(active0, 0x100000000000L); + default : + break; + } + return jjStartNfa_0(2, active0, 0L); +} +private int jjMoveStringLiteralDfa4_0(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return jjStartNfa_0(2, old0, 0L); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(3, active0, 0L); + return 4; + } + switch(curChar) + { + case 61: + return jjMoveStringLiteralDfa5_0(active0, 0x300L); + case 91: + if ((active0 & 0x80L) != 0L) + return jjStopAtPos(4, 7); + else if ((active0 & 0x4000L) != 0L) + return jjStopAtPos(4, 14); + break; + case 97: + return jjMoveStringLiteralDfa5_0(active0, 0x200000000000L); + case 101: + if ((active0 & 0x800000000L) != 0L) + return jjStartNfaWithStates_0(4, 35, 17); + else if ((active0 & 0x2000000000000L) != 0L) + return jjStartNfaWithStates_0(4, 49, 17); + break; + case 105: + return jjMoveStringLiteralDfa5_0(active0, 0x200000000L); + case 107: + if ((active0 & 0x40000000L) != 0L) + return jjStartNfaWithStates_0(4, 30, 17); + break; + case 108: + if ((active0 & 0x10000000000L) != 0L) + return jjStartNfaWithStates_0(4, 40, 17); + else if ((active0 & 0x1000000000000L) != 0L) + return jjStartNfaWithStates_0(4, 48, 17); + break; + case 114: + return jjMoveStringLiteralDfa5_0(active0, 0x100000000000L); + case 116: + return jjMoveStringLiteralDfa5_0(active0, 0x2000000000L); + default : + break; + } + return jjStartNfa_0(3, active0, 0L); +} +private int jjMoveStringLiteralDfa5_0(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return jjStartNfa_0(3, old0, 0L); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(4, active0, 0L); + return 5; + } + switch(curChar) + { + case 61: + return jjMoveStringLiteralDfa6_0(active0, 0x200L); + case 91: + if ((active0 & 0x100L) != 0L) + return jjStopAtPos(5, 8); + break; + case 102: + if ((active0 & 0x200000000L) != 0L) + return jjStartNfaWithStates_0(5, 33, 17); + break; + case 105: + return jjMoveStringLiteralDfa6_0(active0, 0x2000000000L); + case 110: + if ((active0 & 0x100000000000L) != 0L) + return jjStartNfaWithStates_0(5, 44, 17); + break; + case 116: + if ((active0 & 0x200000000000L) != 0L) + return jjStartNfaWithStates_0(5, 45, 17); + break; + default : + break; + } + return jjStartNfa_0(4, active0, 0L); +} +private int jjMoveStringLiteralDfa6_0(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return jjStartNfa_0(4, old0, 0L); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(5, active0, 0L); + return 6; + } + switch(curChar) + { + case 91: + if ((active0 & 0x200L) != 0L) + return jjStopAtPos(6, 9); + break; + case 111: + return jjMoveStringLiteralDfa7_0(active0, 0x2000000000L); + default : + break; + } + return jjStartNfa_0(5, active0, 0L); +} +private int jjMoveStringLiteralDfa7_0(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return jjStartNfa_0(5, old0, 0L); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(6, active0, 0L); + return 7; + } + switch(curChar) + { + case 110: + if ((active0 & 0x2000000000L) != 0L) + return jjStartNfaWithStates_0(7, 37, 17); + break; + default : + break; + } + return jjStartNfa_0(6, active0, 0L); +} +private int jjStartNfaWithStates_0(int pos, int kind, int state) +{ + jjmatchedKind = kind; + jjmatchedPos = pos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return pos + 1; } + return jjMoveNfa_0(state, pos + 1); +} +static final long[] jjbitVec0 = { + 0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL +}; +static final long[] jjbitVec2 = { + 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL +}; +private int jjMoveNfa_0(int startState, int curPos) +{ + int startsAt = 0; + jjnewStateCnt = 63; + int i = 1; + jjstateSet[0] = startState; + int kind = 0x7fffffff; + for (;;) + { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) + { + long l = 1L << curChar; + do + { + switch(jjstateSet[--i]) + { + case 8: + if ((0x3ff000000000000L & l) != 0L) + { + if (kind > 51) + kind = 51; + jjCheckNAddStates(0, 3); + } + else if (curChar == 39) + jjCheckNAddStates(4, 6); + else if (curChar == 34) + jjCheckNAddStates(7, 9); + else if (curChar == 46) + jjCheckNAdd(22); + else if (curChar == 45) + jjstateSet[jjnewStateCnt++] = 7; + if (curChar == 48) + jjstateSet[jjnewStateCnt++] = 19; + break; + case 0: + case 1: + if (curChar == 61) + jjCheckNAddTwoStates(1, 2); + break; + case 3: + if (curChar == 61) + jjstateSet[jjnewStateCnt++] = 0; + break; + case 4: + if (curChar == 61) + jjstateSet[jjnewStateCnt++] = 3; + break; + case 5: + if (curChar == 61) + jjstateSet[jjnewStateCnt++] = 4; + break; + case 7: + if (curChar == 45) + jjstateSet[jjnewStateCnt++] = 6; + break; + case 9: + case 10: + if (curChar == 61) + jjCheckNAddTwoStates(10, 11); + break; + case 12: + if (curChar == 61) + jjstateSet[jjnewStateCnt++] = 9; + break; + case 13: + if (curChar == 61) + jjstateSet[jjnewStateCnt++] = 12; + break; + case 14: + if (curChar == 61) + jjstateSet[jjnewStateCnt++] = 13; + break; + case 17: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 50) + kind = 50; + jjstateSet[jjnewStateCnt++] = 17; + break; + case 18: + if (curChar == 48) + jjstateSet[jjnewStateCnt++] = 19; + break; + case 20: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 51) + kind = 51; + jjstateSet[jjnewStateCnt++] = 20; + break; + case 21: + if (curChar == 46) + jjCheckNAdd(22); + break; + case 22: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 51) + kind = 51; + jjCheckNAddTwoStates(22, 23); + break; + case 24: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(25); + break; + case 25: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 51) + kind = 51; + jjCheckNAdd(25); + break; + case 26: + if (curChar == 34) + jjCheckNAddStates(7, 9); + break; + case 27: + if ((0xfffffffbffffffffL & l) != 0L) + jjCheckNAddStates(7, 9); + break; + case 28: + if (curChar == 34 && kind > 57) + kind = 57; + break; + case 30: + jjCheckNAddStates(7, 9); + break; + case 32: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 33; + break; + case 33: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 34; + break; + case 34: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 35; + break; + case 35: + case 38: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(7, 9); + break; + case 36: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(10, 13); + break; + case 37: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(14, 17); + break; + case 39: + if (curChar == 39) + jjCheckNAddStates(4, 6); + break; + case 40: + if ((0xffffff7fffffffffL & l) != 0L) + jjCheckNAddStates(4, 6); + break; + case 41: + if (curChar == 39 && kind > 58) + kind = 58; + break; + case 43: + jjCheckNAddStates(4, 6); + break; + case 45: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 46; + break; + case 46: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 47; + break; + case 47: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 48; + break; + case 48: + case 51: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(4, 6); + break; + case 49: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(18, 21); + break; + case 50: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(22, 25); + break; + case 52: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 51) + kind = 51; + jjCheckNAddStates(0, 3); + break; + case 53: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 51) + kind = 51; + jjCheckNAddTwoStates(53, 54); + break; + case 55: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(56); + break; + case 56: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 51) + kind = 51; + jjCheckNAdd(56); + break; + case 57: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(57, 58); + break; + case 58: + if (curChar != 46) + break; + if (kind > 51) + kind = 51; + jjCheckNAddTwoStates(59, 60); + break; + case 59: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 51) + kind = 51; + jjCheckNAddTwoStates(59, 60); + break; + case 61: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(62); + break; + case 62: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 51) + kind = 51; + jjCheckNAdd(62); + break; + default : break; + } + } while(i != startsAt); + } + else if (curChar < 128) + { + long l = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + case 8: + if ((0x7fffffe87fffffeL & l) != 0L) + { + if (kind > 50) + kind = 50; + jjCheckNAdd(17); + } + else if (curChar == 91) + jjstateSet[jjnewStateCnt++] = 14; + break; + case 2: + if (curChar == 91 && kind > 10) + kind = 10; + break; + case 6: + if (curChar == 91) + jjstateSet[jjnewStateCnt++] = 5; + break; + case 11: + if (curChar == 91 && kind > 15) + kind = 15; + break; + case 15: + if (curChar == 91) + jjstateSet[jjnewStateCnt++] = 14; + break; + case 16: + case 17: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 50) + kind = 50; + jjCheckNAdd(17); + break; + case 19: + if ((0x100000001000000L & l) != 0L) + jjCheckNAdd(20); + break; + case 20: + if ((0x7e0000007eL & l) == 0L) + break; + if (kind > 51) + kind = 51; + jjCheckNAdd(20); + break; + case 23: + if ((0x2000000020L & l) != 0L) + jjAddStates(26, 27); + break; + case 27: + if ((0xffffffffefffffffL & l) != 0L) + jjCheckNAddStates(7, 9); + break; + case 29: + if (curChar == 92) + jjAddStates(28, 30); + break; + case 30: + jjCheckNAddStates(7, 9); + break; + case 31: + if (curChar == 117) + jjstateSet[jjnewStateCnt++] = 32; + break; + case 32: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 33; + break; + case 33: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 34; + break; + case 34: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 35; + break; + case 35: + if ((0x7e0000007eL & l) != 0L) + jjCheckNAddStates(7, 9); + break; + case 40: + if ((0xffffffffefffffffL & l) != 0L) + jjCheckNAddStates(4, 6); + break; + case 42: + if (curChar == 92) + jjAddStates(31, 33); + break; + case 43: + jjCheckNAddStates(4, 6); + break; + case 44: + if (curChar == 117) + jjstateSet[jjnewStateCnt++] = 45; + break; + case 45: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 46; + break; + case 46: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 47; + break; + case 47: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 48; + break; + case 48: + if ((0x7e0000007eL & l) != 0L) + jjCheckNAddStates(4, 6); + break; + case 54: + if ((0x2000000020L & l) != 0L) + jjAddStates(34, 35); + break; + case 60: + if ((0x2000000020L & l) != 0L) + jjAddStates(36, 37); + break; + default : break; + } + } while(i != startsAt); + } + else + { + int hiByte = (int)(curChar >> 8); + int i1 = hiByte >> 6; + long l1 = 1L << (hiByte & 077); + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + case 27: + case 30: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) + jjCheckNAddStates(7, 9); + break; + case 40: + case 43: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) + jjCheckNAddStates(4, 6); + break; + default : break; + } + } while(i != startsAt); + } + if (kind != 0x7fffffff) + { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 63 - (jjnewStateCnt = startsAt))) + return curPos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return curPos; } + } +} +private int jjMoveStringLiteralDfa0_1() +{ + return jjMoveNfa_1(4, 0); +} +private int jjMoveNfa_1(int startState, int curPos) +{ + int startsAt = 0; + jjnewStateCnt = 4; + int i = 1; + jjstateSet[0] = startState; + int kind = 0x7fffffff; + for (;;) + { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) + { + long l = 1L << curChar; + do + { + switch(jjstateSet[--i]) + { + case 4: + if ((0xffffffffffffdbffL & l) != 0L) + { + if (kind > 17) + kind = 17; + jjCheckNAddStates(38, 40); + } + else if ((0x2400L & l) != 0L) + { + if (kind > 17) + kind = 17; + } + if (curChar == 13) + jjstateSet[jjnewStateCnt++] = 2; + break; + case 0: + if ((0xffffffffffffdbffL & l) == 0L) + break; + kind = 17; + jjCheckNAddStates(38, 40); + break; + case 1: + if ((0x2400L & l) != 0L && kind > 17) + kind = 17; + break; + case 2: + if (curChar == 10 && kind > 17) + kind = 17; + break; + case 3: + if (curChar == 13) + jjstateSet[jjnewStateCnt++] = 2; + break; + default : break; + } + } while(i != startsAt); + } + else if (curChar < 128) + { + long l = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + case 4: + case 0: + kind = 17; + jjCheckNAddStates(38, 40); + break; + default : break; + } + } while(i != startsAt); + } + else + { + int hiByte = (int)(curChar >> 8); + int i1 = hiByte >> 6; + long l1 = 1L << (hiByte & 077); + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + case 4: + case 0: + if (!jjCanMove_0(hiByte, i1, i2, l1, l2)) + break; + if (kind > 17) + kind = 17; + jjCheckNAddStates(38, 40); + break; + default : break; + } + } while(i != startsAt); + } + if (kind != 0x7fffffff) + { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 4 - (jjnewStateCnt = startsAt))) + return curPos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return curPos; } + } +} +private int jjMoveStringLiteralDfa0_6() +{ + return jjMoveNfa_6(6, 0); +} +private int jjMoveNfa_6(int startState, int curPos) +{ + int startsAt = 0; + jjnewStateCnt = 7; + int i = 1; + jjstateSet[0] = startState; + int kind = 0x7fffffff; + for (;;) + { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) + { + long l = 1L << curChar; + do + { + switch(jjstateSet[--i]) + { + case 0: + case 1: + if (curChar == 61) + jjCheckNAddTwoStates(1, 2); + break; + case 3: + if (curChar == 61) + jjstateSet[jjnewStateCnt++] = 0; + break; + case 4: + if (curChar == 61) + jjstateSet[jjnewStateCnt++] = 3; + break; + case 5: + if (curChar == 61) + jjstateSet[jjnewStateCnt++] = 4; + break; + default : break; + } + } while(i != startsAt); + } + else if (curChar < 128) + { + long l = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + case 2: + if (curChar == 93 && kind > 22) + kind = 22; + break; + case 6: + if (curChar == 93) + jjstateSet[jjnewStateCnt++] = 5; + break; + default : break; + } + } while(i != startsAt); + } + else + { + int hiByte = (int)(curChar >> 8); + int i1 = hiByte >> 6; + long l1 = 1L << (hiByte & 077); + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + default : break; + } + } while(i != startsAt); + } + if (kind != 0x7fffffff) + { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 7 - (jjnewStateCnt = startsAt))) + return curPos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return curPos; } + } +} +private int jjMoveStringLiteralDfa0_5() +{ + switch(curChar) + { + case 93: + return jjMoveStringLiteralDfa1_5(0x200000L); + default : + return 1; + } +} +private int jjMoveStringLiteralDfa1_5(long active0) +{ + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 1; + } + switch(curChar) + { + case 61: + return jjMoveStringLiteralDfa2_5(active0, 0x200000L); + default : + return 2; + } +} +private int jjMoveStringLiteralDfa2_5(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return 2; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 2; + } + switch(curChar) + { + case 61: + return jjMoveStringLiteralDfa3_5(active0, 0x200000L); + default : + return 3; + } +} +private int jjMoveStringLiteralDfa3_5(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return 3; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 3; + } + switch(curChar) + { + case 61: + return jjMoveStringLiteralDfa4_5(active0, 0x200000L); + default : + return 4; + } +} +private int jjMoveStringLiteralDfa4_5(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return 4; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 4; + } + switch(curChar) + { + case 93: + if ((active0 & 0x200000L) != 0L) + return jjStopAtPos(4, 21); + break; + default : + return 5; + } + return 5; +} +private int jjMoveStringLiteralDfa0_4() +{ + switch(curChar) + { + case 93: + return jjMoveStringLiteralDfa1_4(0x100000L); + default : + return 1; + } +} +private int jjMoveStringLiteralDfa1_4(long active0) +{ + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 1; + } + switch(curChar) + { + case 61: + return jjMoveStringLiteralDfa2_4(active0, 0x100000L); + default : + return 2; + } +} +private int jjMoveStringLiteralDfa2_4(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return 2; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 2; + } + switch(curChar) + { + case 61: + return jjMoveStringLiteralDfa3_4(active0, 0x100000L); + default : + return 3; + } +} +private int jjMoveStringLiteralDfa3_4(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return 3; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 3; + } + switch(curChar) + { + case 93: + if ((active0 & 0x100000L) != 0L) + return jjStopAtPos(3, 20); + break; + default : + return 4; + } + return 4; +} +private int jjMoveStringLiteralDfa0_3() +{ + switch(curChar) + { + case 93: + return jjMoveStringLiteralDfa1_3(0x80000L); + default : + return 1; + } +} +private int jjMoveStringLiteralDfa1_3(long active0) +{ + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 1; + } + switch(curChar) + { + case 61: + return jjMoveStringLiteralDfa2_3(active0, 0x80000L); + default : + return 2; + } +} +private int jjMoveStringLiteralDfa2_3(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return 2; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 2; + } + switch(curChar) + { + case 93: + if ((active0 & 0x80000L) != 0L) + return jjStopAtPos(2, 19); + break; + default : + return 3; + } + return 3; +} +static final int[] jjnextStates = { + 53, 54, 57, 58, 40, 41, 42, 27, 28, 29, 27, 28, 29, 37, 27, 38, + 28, 29, 40, 41, 42, 50, 40, 51, 41, 42, 24, 25, 30, 31, 36, 43, + 44, 49, 55, 56, 61, 62, 0, 1, 3, +}; +private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2) +{ + switch(hiByte) + { + case 0: + return ((jjbitVec2[i2] & l2) != 0L); + default : + if ((jjbitVec0[i1] & l1) != 0L) + return true; + return false; + } +} + +/** Token literal values. */ +public static final String[] jjstrLiteralImages = { +"", null, null, null, null, null, null, null, null, null, null, null, null, +null, null, null, null, null, null, null, null, null, null, null, null, null, null, +null, null, "\141\156\144", "\142\162\145\141\153", "\144\157", "\145\154\163\145", +"\145\154\163\145\151\146", "\145\156\144", "\146\141\154\163\145", "\146\157\162", +"\146\165\156\143\164\151\157\156", "\151\146", "\151\156", "\154\157\143\141\154", "\156\151\154", +"\156\157\164", "\157\162", "\162\145\164\165\162\156", "\162\145\160\145\141\164", +"\164\150\145\156", "\164\162\165\145", "\165\156\164\151\154", "\167\150\151\154\145", null, null, +null, null, null, null, null, null, null, null, null, null, null, null, "\73", +"\75", "\54", "\56", "\72", "\50", "\51", "\133", "\135", "\56\56\56", "\173", +"\175", "\53", "\55", "\52", "\57", "\136", "\45", "\56\56", "\74", "\74\75", "\76", +"\76\75", "\75\75", "\176\75", "\43", }; + +/** Lexer state names. */ +public static final String[] lexStateNames = { + "DEFAULT", + "IN_COMMENT", + "IN_LC0", + "IN_LC1", + "IN_LC2", + "IN_LC3", + "IN_LCN", + "IN_LS0", + "IN_LS1", + "IN_LS2", + "IN_LS3", + "IN_LSN", +}; + +/** Lex State array. */ +public static final int[] jjnewLexState = { + -1, -1, -1, -1, -1, -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, +}; +static final long[] jjtoToken = { + 0x60fffffef800001L, 0x3ffffffL, +}; +static final long[] jjtoSkip = { + 0x7e003eL, 0x0L, +}; +static final long[] jjtoSpecial = { + 0x7e0000L, 0x0L, +}; +static final long[] jjtoMore = { + 0x1001ffc0L, 0x0L, +}; +protected SimpleCharStream input_stream; +private final int[] jjrounds = new int[63]; +private final int[] jjstateSet = new int[126]; +private final StringBuffer jjimage = new StringBuffer(); +private StringBuffer image = jjimage; +private int jjimageLen; +private int lengthOfMatch; +protected char curChar; +/** Constructor. */ +public LuaParserTokenManager(SimpleCharStream stream){ + if (SimpleCharStream.staticFlag) + throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer."); + input_stream = stream; +} + +/** Constructor. */ +public LuaParserTokenManager(SimpleCharStream stream, int lexState){ + this(stream); + SwitchTo(lexState); +} + +/** Reinitialise parser. */ +public void ReInit(SimpleCharStream stream) +{ + jjmatchedPos = jjnewStateCnt = 0; + curLexState = defaultLexState; + input_stream = stream; + ReInitRounds(); +} +private void ReInitRounds() +{ + int i; + jjround = 0x80000001; + for (i = 63; i-- > 0;) + jjrounds[i] = 0x80000000; +} + +/** Reinitialise parser. */ +public void ReInit(SimpleCharStream stream, int lexState) +{ + ReInit(stream); + SwitchTo(lexState); +} + +/** Switch to specified lex state. */ +public void SwitchTo(int lexState) +{ + if (lexState >= 12 || lexState < 0) + throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); + else + curLexState = lexState; +} + +protected Token jjFillToken() +{ + final Token t; + final String curTokenImage; + final int beginLine; + final int endLine; + final int beginColumn; + final int endColumn; + if (jjmatchedPos < 0) + { + if (image == null) + curTokenImage = ""; + else + curTokenImage = image.toString(); + beginLine = endLine = input_stream.getBeginLine(); + beginColumn = endColumn = input_stream.getBeginColumn(); + } + else + { + String im = jjstrLiteralImages[jjmatchedKind]; + curTokenImage = (im == null) ? input_stream.GetImage() : im; + beginLine = input_stream.getBeginLine(); + beginColumn = input_stream.getBeginColumn(); + endLine = input_stream.getEndLine(); + endColumn = input_stream.getEndColumn(); + } + t = Token.newToken(jjmatchedKind, curTokenImage); + + t.beginLine = beginLine; + t.endLine = endLine; + t.beginColumn = beginColumn; + t.endColumn = endColumn; + + return t; +} + +int curLexState = 0; +int defaultLexState = 0; +int jjnewStateCnt; +int jjround; +int jjmatchedPos; +int jjmatchedKind; + +/** Get the next Token. */ +public Token getNextToken() +{ + Token specialToken = null; + Token matchedToken; + int curPos = 0; + + EOFLoop : + for (;;) + { + try + { + curChar = input_stream.BeginToken(); + } + catch(java.io.IOException e) + { + jjmatchedKind = 0; + matchedToken = jjFillToken(); + matchedToken.specialToken = specialToken; + return matchedToken; + } + image = jjimage; + image.setLength(0); + jjimageLen = 0; + + for (;;) + { + switch(curLexState) + { + case 0: + try { input_stream.backup(0); + while (curChar <= 32 && (0x100003600L & (1L << curChar)) != 0L) + curChar = input_stream.BeginToken(); + } + catch (java.io.IOException e1) { continue EOFLoop; } + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_0(); + break; + case 1: + jjmatchedKind = 17; + jjmatchedPos = -1; + curPos = 0; + curPos = jjMoveStringLiteralDfa0_1(); + break; + case 2: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_2(); + if (jjmatchedPos == 0 && jjmatchedKind > 28) + { + jjmatchedKind = 28; + } + break; + case 3: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_3(); + if (jjmatchedPos == 0 && jjmatchedKind > 28) + { + jjmatchedKind = 28; + } + break; + case 4: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_4(); + if (jjmatchedPos == 0 && jjmatchedKind > 28) + { + jjmatchedKind = 28; + } + break; + case 5: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_5(); + if (jjmatchedPos == 0 && jjmatchedKind > 28) + { + jjmatchedKind = 28; + } + break; + case 6: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_6(); + if (jjmatchedPos == 0 && jjmatchedKind > 28) + { + jjmatchedKind = 28; + } + break; + case 7: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_7(); + if (jjmatchedPos == 0 && jjmatchedKind > 28) + { + jjmatchedKind = 28; + } + break; + case 8: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_8(); + if (jjmatchedPos == 0 && jjmatchedKind > 28) + { + jjmatchedKind = 28; + } + break; + case 9: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_9(); + if (jjmatchedPos == 0 && jjmatchedKind > 28) + { + jjmatchedKind = 28; + } + break; + case 10: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_10(); + if (jjmatchedPos == 0 && jjmatchedKind > 28) + { + jjmatchedKind = 28; + } + break; + case 11: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_11(); + if (jjmatchedPos == 0 && jjmatchedKind > 28) + { + jjmatchedKind = 28; + } + break; + } + if (jjmatchedKind != 0x7fffffff) + { + if (jjmatchedPos + 1 < curPos) + input_stream.backup(curPos - jjmatchedPos - 1); + if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) + { + matchedToken = jjFillToken(); + matchedToken.specialToken = specialToken; + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + return matchedToken; + } + else if ((jjtoSkip[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) + { + if ((jjtoSpecial[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) + { + matchedToken = jjFillToken(); + if (specialToken == null) + specialToken = matchedToken; + else + { + matchedToken.specialToken = specialToken; + specialToken = (specialToken.next = matchedToken); + } + SkipLexicalActions(matchedToken); + } + else + SkipLexicalActions(null); + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + continue EOFLoop; + } + jjimageLen += jjmatchedPos + 1; + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + curPos = 0; + jjmatchedKind = 0x7fffffff; + try { + curChar = input_stream.readChar(); + continue; + } + catch (java.io.IOException e1) { } + } + int error_line = input_stream.getEndLine(); + int error_column = input_stream.getEndColumn(); + String error_after = null; + boolean EOFSeen = false; + try { input_stream.readChar(); input_stream.backup(1); } + catch (java.io.IOException e1) { + EOFSeen = true; + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + if (curChar == '\n' || curChar == '\r') { + error_line++; + error_column = 0; + } + else + error_column++; + } + if (!EOFSeen) { + input_stream.backup(1); + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + } + throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR); + } + } +} + +void SkipLexicalActions(Token matchedToken) +{ + switch(jjmatchedKind) + { + default : + break; + } +} +private void jjCheckNAdd(int state) +{ + if (jjrounds[state] != jjround) + { + jjstateSet[jjnewStateCnt++] = state; + jjrounds[state] = jjround; + } +} +private void jjAddStates(int start, int end) +{ + do { + jjstateSet[jjnewStateCnt++] = jjnextStates[start]; + } while (start++ != end); +} +private void jjCheckNAddTwoStates(int state1, int state2) +{ + jjCheckNAdd(state1); + jjCheckNAdd(state2); +} + +private void jjCheckNAddStates(int start, int end) +{ + do { + jjCheckNAdd(jjnextStates[start]); + } while (start++ != end); +} + +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/parser/ParseException.java b/luaj-2.0.3/src/jse/org/luaj/vm2/parser/ParseException.java new file mode 100644 index 0000000000..b59d68cab2 --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/parser/ParseException.java @@ -0,0 +1,187 @@ +/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 5.0 */ +/* JavaCCOptions:KEEP_LINE_COL=null */ +package org.luaj.vm2.parser; + +/** + * This exception is thrown when parse errors are encountered. + * You can explicitly create objects of this exception type by + * calling the method generateParseException in the generated + * parser. + * + * You can modify this class to customize your error reporting + * mechanisms so long as you retain the public fields. + */ +public class ParseException extends Exception { + + /** + * The version identifier for this Serializable class. + * Increment only if the serialized form of the + * class changes. + */ + private static final long serialVersionUID = 1L; + + /** + * This constructor is used by the method "generateParseException" + * in the generated parser. Calling this constructor generates + * a new object of this type with the fields "currentToken", + * "expectedTokenSequences", and "tokenImage" set. + */ + public ParseException(Token currentTokenVal, + int[][] expectedTokenSequencesVal, + String[] tokenImageVal + ) + { + super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal)); + currentToken = currentTokenVal; + expectedTokenSequences = expectedTokenSequencesVal; + tokenImage = tokenImageVal; + } + + /** + * The following constructors are for use by you for whatever + * purpose you can think of. Constructing the exception in this + * manner makes the exception behave in the normal way - i.e., as + * documented in the class "Throwable". The fields "errorToken", + * "expectedTokenSequences", and "tokenImage" do not contain + * relevant information. The JavaCC generated code does not use + * these constructors. + */ + + public ParseException() { + super(); + } + + /** Constructor with message. */ + public ParseException(String message) { + super(message); + } + + + /** + * This is the last token that has been consumed successfully. If + * this object has been created due to a parse error, the token + * followng this token will (therefore) be the first error token. + */ + public Token currentToken; + + /** + * Each entry in this array is an array of integers. Each array + * of integers represents a sequence of tokens (by their ordinal + * values) that is expected at this point of the parse. + */ + public int[][] expectedTokenSequences; + + /** + * This is a reference to the "tokenImage" array of the generated + * parser within which the parse error occurred. This array is + * defined in the generated ...Constants interface. + */ + public String[] tokenImage; + + /** + * It uses "currentToken" and "expectedTokenSequences" to generate a parse + * error message and returns it. If this object has been created + * due to a parse error, and you do not catch it (it gets thrown + * from the parser) the correct error message + * gets displayed. + */ + private static String initialise(Token currentToken, + int[][] expectedTokenSequences, + String[] tokenImage) { + String eol = System.getProperty("line.separator", "\n"); + StringBuffer expected = new StringBuffer(); + int maxSize = 0; + for (int i = 0; i < expectedTokenSequences.length; i++) { + if (maxSize < expectedTokenSequences[i].length) { + maxSize = expectedTokenSequences[i].length; + } + for (int j = 0; j < expectedTokenSequences[i].length; j++) { + expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' '); + } + if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) { + expected.append("..."); + } + expected.append(eol).append(" "); + } + String retval = "Encountered \""; + Token tok = currentToken.next; + for (int i = 0; i < maxSize; i++) { + if (i != 0) retval += " "; + if (tok.kind == 0) { + retval += tokenImage[0]; + break; + } + retval += " " + tokenImage[tok.kind]; + retval += " \""; + retval += add_escapes(tok.image); + retval += " \""; + tok = tok.next; + } + retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn; + retval += "." + eol; + if (expectedTokenSequences.length == 1) { + retval += "Was expecting:" + eol + " "; + } else { + retval += "Was expecting one of:" + eol + " "; + } + retval += expected.toString(); + return retval; + } + + /** + * The end of line string for this machine. + */ + protected String eol = System.getProperty("line.separator", "\n"); + + /** + * Used to convert raw characters to their escaped version + * when these raw version cannot be used as part of an ASCII + * string literal. + */ + static String add_escapes(String str) { + StringBuffer retval = new StringBuffer(); + char ch; + for (int i = 0; i < str.length(); i++) { + switch (str.charAt(i)) + { + case 0 : + continue; + case '\b': + retval.append("\\b"); + continue; + case '\t': + retval.append("\\t"); + continue; + case '\n': + retval.append("\\n"); + continue; + case '\f': + retval.append("\\f"); + continue; + case '\r': + retval.append("\\r"); + continue; + case '\"': + retval.append("\\\""); + continue; + case '\'': + retval.append("\\\'"); + continue; + case '\\': + retval.append("\\\\"); + continue; + default: + if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { + String s = "0000" + Integer.toString(ch, 16); + retval.append("\\u" + s.substring(s.length() - 4, s.length())); + } else { + retval.append(ch); + } + continue; + } + } + return retval.toString(); + } + +} +/* JavaCC - OriginalChecksum=ef246095a930e4915c0d4bbf4c9880ad (do not edit this line) */ diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/parser/SimpleCharStream.java b/luaj-2.0.3/src/jse/org/luaj/vm2/parser/SimpleCharStream.java new file mode 100644 index 0000000000..da3746caae --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/parser/SimpleCharStream.java @@ -0,0 +1,469 @@ +/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 5.0 */ +/* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ +package org.luaj.vm2.parser; + +/** + * An implementation of interface CharStream, where the stream is assumed to + * contain only ASCII characters (without unicode processing). + */ + +public class SimpleCharStream +{ +/** Whether parser is static. */ + public static final boolean staticFlag = false; + int bufsize; + int available; + int tokenBegin; +/** Position in buffer. */ + public int bufpos = -1; + protected int bufline[]; + protected int bufcolumn[]; + + protected int column = 0; + protected int line = 1; + + protected boolean prevCharIsCR = false; + protected boolean prevCharIsLF = false; + + protected java.io.Reader inputStream; + + protected char[] buffer; + protected int maxNextCharInd = 0; + protected int inBuf = 0; + protected int tabSize = 8; + + protected void setTabSize(int i) { tabSize = i; } + protected int getTabSize(int i) { return tabSize; } + + + protected void ExpandBuff(boolean wrapAround) + { + char[] newbuffer = new char[bufsize + 2048]; + int newbufline[] = new int[bufsize + 2048]; + int newbufcolumn[] = new int[bufsize + 2048]; + + try + { + if (wrapAround) + { + System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); + System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos); + buffer = newbuffer; + + System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); + System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos); + bufline = newbufline; + + System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); + System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos); + bufcolumn = newbufcolumn; + + maxNextCharInd = (bufpos += (bufsize - tokenBegin)); + } + else + { + System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); + buffer = newbuffer; + + System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); + bufline = newbufline; + + System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); + bufcolumn = newbufcolumn; + + maxNextCharInd = (bufpos -= tokenBegin); + } + } + catch (Throwable t) + { + throw new Error(t.getMessage()); + } + + + bufsize += 2048; + available = bufsize; + tokenBegin = 0; + } + + protected void FillBuff() throws java.io.IOException + { + if (maxNextCharInd == available) + { + if (available == bufsize) + { + if (tokenBegin > 2048) + { + bufpos = maxNextCharInd = 0; + available = tokenBegin; + } + else if (tokenBegin < 0) + bufpos = maxNextCharInd = 0; + else + ExpandBuff(false); + } + else if (available > tokenBegin) + available = bufsize; + else if ((tokenBegin - available) < 2048) + ExpandBuff(true); + else + available = tokenBegin; + } + + int i; + try { + if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1) + { + inputStream.close(); + throw new java.io.IOException(); + } + else + maxNextCharInd += i; + return; + } + catch(java.io.IOException e) { + --bufpos; + backup(0); + if (tokenBegin == -1) + tokenBegin = bufpos; + throw e; + } + } + +/** Start. */ + public char BeginToken() throws java.io.IOException + { + tokenBegin = -1; + char c = readChar(); + tokenBegin = bufpos; + + return c; + } + + protected void UpdateLineColumn(char c) + { + column++; + + if (prevCharIsLF) + { + prevCharIsLF = false; + line += (column = 1); + } + else if (prevCharIsCR) + { + prevCharIsCR = false; + if (c == '\n') + { + prevCharIsLF = true; + } + else + line += (column = 1); + } + + switch (c) + { + case '\r' : + prevCharIsCR = true; + break; + case '\n' : + prevCharIsLF = true; + break; + case '\t' : + column--; + column += (tabSize - (column % tabSize)); + break; + default : + break; + } + + bufline[bufpos] = line; + bufcolumn[bufpos] = column; + } + +/** Read a character. */ + public char readChar() throws java.io.IOException + { + if (inBuf > 0) + { + --inBuf; + + if (++bufpos == bufsize) + bufpos = 0; + + return buffer[bufpos]; + } + + if (++bufpos >= maxNextCharInd) + FillBuff(); + + char c = buffer[bufpos]; + + UpdateLineColumn(c); + return c; + } + + /** + * @deprecated + * @see #getEndColumn + */ + + public int getColumn() { + return bufcolumn[bufpos]; + } + + /** + * @deprecated + * @see #getEndLine + */ + + public int getLine() { + return bufline[bufpos]; + } + + /** Get token end column number. */ + public int getEndColumn() { + return bufcolumn[bufpos]; + } + + /** Get token end line number. */ + public int getEndLine() { + return bufline[bufpos]; + } + + /** Get token beginning column number. */ + public int getBeginColumn() { + return bufcolumn[tokenBegin]; + } + + /** Get token beginning line number. */ + public int getBeginLine() { + return bufline[tokenBegin]; + } + +/** Backup a number of characters. */ + public void backup(int amount) { + + inBuf += amount; + if ((bufpos -= amount) < 0) + bufpos += bufsize; + } + + /** Constructor. */ + public SimpleCharStream(java.io.Reader dstream, int startline, + int startcolumn, int buffersize) + { + inputStream = dstream; + line = startline; + column = startcolumn - 1; + + available = bufsize = buffersize; + buffer = new char[buffersize]; + bufline = new int[buffersize]; + bufcolumn = new int[buffersize]; + } + + /** Constructor. */ + public SimpleCharStream(java.io.Reader dstream, int startline, + int startcolumn) + { + this(dstream, startline, startcolumn, 4096); + } + + /** Constructor. */ + public SimpleCharStream(java.io.Reader dstream) + { + this(dstream, 1, 1, 4096); + } + + /** Reinitialise. */ + public void ReInit(java.io.Reader dstream, int startline, + int startcolumn, int buffersize) + { + inputStream = dstream; + line = startline; + column = startcolumn - 1; + + if (buffer == null || buffersize != buffer.length) + { + available = bufsize = buffersize; + buffer = new char[buffersize]; + bufline = new int[buffersize]; + bufcolumn = new int[buffersize]; + } + prevCharIsLF = prevCharIsCR = false; + tokenBegin = inBuf = maxNextCharInd = 0; + bufpos = -1; + } + + /** Reinitialise. */ + public void ReInit(java.io.Reader dstream, int startline, + int startcolumn) + { + ReInit(dstream, startline, startcolumn, 4096); + } + + /** Reinitialise. */ + public void ReInit(java.io.Reader dstream) + { + ReInit(dstream, 1, 1, 4096); + } + /** Constructor. */ + public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, + int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException + { + this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); + } + + /** Constructor. */ + public SimpleCharStream(java.io.InputStream dstream, int startline, + int startcolumn, int buffersize) + { + this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); + } + + /** Constructor. */ + public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, + int startcolumn) throws java.io.UnsupportedEncodingException + { + this(dstream, encoding, startline, startcolumn, 4096); + } + + /** Constructor. */ + public SimpleCharStream(java.io.InputStream dstream, int startline, + int startcolumn) + { + this(dstream, startline, startcolumn, 4096); + } + + /** Constructor. */ + public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException + { + this(dstream, encoding, 1, 1, 4096); + } + + /** Constructor. */ + public SimpleCharStream(java.io.InputStream dstream) + { + this(dstream, 1, 1, 4096); + } + + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream, String encoding, int startline, + int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException + { + ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); + } + + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream, int startline, + int startcolumn, int buffersize) + { + ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); + } + + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException + { + ReInit(dstream, encoding, 1, 1, 4096); + } + + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream) + { + ReInit(dstream, 1, 1, 4096); + } + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream, String encoding, int startline, + int startcolumn) throws java.io.UnsupportedEncodingException + { + ReInit(dstream, encoding, startline, startcolumn, 4096); + } + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream, int startline, + int startcolumn) + { + ReInit(dstream, startline, startcolumn, 4096); + } + /** Get token literal value. */ + public String GetImage() + { + if (bufpos >= tokenBegin) + return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); + else + return new String(buffer, tokenBegin, bufsize - tokenBegin) + + new String(buffer, 0, bufpos + 1); + } + + /** Get the suffix. */ + public char[] GetSuffix(int len) + { + char[] ret = new char[len]; + + if ((bufpos + 1) >= len) + System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); + else + { + System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, + len - bufpos - 1); + System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1); + } + + return ret; + } + + /** Reset buffer when finished. */ + public void Done() + { + buffer = null; + bufline = null; + bufcolumn = null; + } + + /** + * Method to adjust line and column numbers for the start of a token. + */ + public void adjustBeginLineColumn(int newLine, int newCol) + { + int start = tokenBegin; + int len; + + if (bufpos >= tokenBegin) + { + len = bufpos - tokenBegin + inBuf + 1; + } + else + { + len = bufsize - tokenBegin + bufpos + 1 + inBuf; + } + + int i = 0, j = 0, k = 0; + int nextColDiff = 0, columnDiff = 0; + + while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) + { + bufline[j] = newLine; + nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; + bufcolumn[j] = newCol + columnDiff; + columnDiff = nextColDiff; + i++; + } + + if (i < len) + { + bufline[j] = newLine++; + bufcolumn[j] = newCol + columnDiff; + + while (i++ < len) + { + if (bufline[j = start % bufsize] != bufline[++start % bufsize]) + bufline[j] = newLine++; + else + bufline[j] = newLine; + } + } + + line = bufline[j]; + column = bufcolumn[j]; + } + +} +/* JavaCC - OriginalChecksum=ab0c629eabd887d4c88cec51eb5e6477 (do not edit this line) */ diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/parser/Token.java b/luaj-2.0.3/src/jse/org/luaj/vm2/parser/Token.java new file mode 100644 index 0000000000..d3eec17c8d --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/parser/Token.java @@ -0,0 +1,131 @@ +/* Generated By:JavaCC: Do not edit this line. Token.java Version 5.0 */ +/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ +package org.luaj.vm2.parser; + +/** + * Describes the input token stream. + */ + +public class Token implements java.io.Serializable { + + /** + * The version identifier for this Serializable class. + * Increment only if the serialized form of the + * class changes. + */ + private static final long serialVersionUID = 1L; + + /** + * An integer that describes the kind of this token. This numbering + * system is determined by JavaCCParser, and a table of these numbers is + * stored in the file ...Constants.java. + */ + public int kind; + + /** The line number of the first character of this Token. */ + public int beginLine; + /** The column number of the first character of this Token. */ + public int beginColumn; + /** The line number of the last character of this Token. */ + public int endLine; + /** The column number of the last character of this Token. */ + public int endColumn; + + /** + * The string image of the token. + */ + public String image; + + /** + * A reference to the next regular (non-special) token from the input + * stream. If this is the last token from the input stream, or if the + * token manager has not read tokens beyond this one, this field is + * set to null. This is true only if this token is also a regular + * token. Otherwise, see below for a description of the contents of + * this field. + */ + public Token next; + + /** + * This field is used to access special tokens that occur prior to this + * token, but after the immediately preceding regular (non-special) token. + * If there are no such special tokens, this field is set to null. + * When there are more than one such special token, this field refers + * to the last of these special tokens, which in turn refers to the next + * previous special token through its specialToken field, and so on + * until the first special token (whose specialToken field is null). + * The next fields of special tokens refer to other special tokens that + * immediately follow it (without an intervening regular token). If there + * is no such token, this field is null. + */ + public Token specialToken; + + /** + * An optional attribute value of the Token. + * Tokens which are not used as syntactic sugar will often contain + * meaningful values that will be used later on by the compiler or + * interpreter. This attribute value is often different from the image. + * Any subclass of Token that actually wants to return a non-null value can + * override this method as appropriate. + */ + public Object getValue() { + return null; + } + + /** + * No-argument constructor + */ + public Token() {} + + /** + * Constructs a new token for the specified Image. + */ + public Token(int kind) + { + this(kind, null); + } + + /** + * Constructs a new token for the specified Image and Kind. + */ + public Token(int kind, String image) + { + this.kind = kind; + this.image = image; + } + + /** + * Returns the image. + */ + public String toString() + { + return image; + } + + /** + * Returns a new Token object, by default. However, if you want, you + * can create and return subclass objects based on the value of ofKind. + * Simply add the cases to the switch for all those special cases. + * For example, if you have a subclass of Token called IDToken that + * you want to create if ofKind is ID, simply add something like : + * + * case MyParserConstants.ID : return new IDToken(ofKind, image); + * + * to the following switch statement. Then you can cast matchedToken + * variable to the appropriate type and use sit in your lexical actions. + */ + public static Token newToken(int ofKind, String image) + { + switch(ofKind) + { + default : return new Token(ofKind, image); + } + } + + public static Token newToken(int ofKind) + { + return newToken(ofKind, null); + } + +} +/* JavaCC - OriginalChecksum=70d73add5771158f10d1ae81755e7cfc (do not edit this line) */ diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/parser/TokenMgrError.java b/luaj-2.0.3/src/jse/org/luaj/vm2/parser/TokenMgrError.java new file mode 100644 index 0000000000..37a7f55b6a --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/parser/TokenMgrError.java @@ -0,0 +1,147 @@ +/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 5.0 */ +/* JavaCCOptions: */ +package org.luaj.vm2.parser; + +/** Token Manager Error. */ +public class TokenMgrError extends Error +{ + + /** + * The version identifier for this Serializable class. + * Increment only if the serialized form of the + * class changes. + */ + private static final long serialVersionUID = 1L; + + /* + * Ordinals for various reasons why an Error of this type can be thrown. + */ + + /** + * Lexical error occurred. + */ + static final int LEXICAL_ERROR = 0; + + /** + * An attempt was made to create a second instance of a static token manager. + */ + static final int STATIC_LEXER_ERROR = 1; + + /** + * Tried to change to an invalid lexical state. + */ + static final int INVALID_LEXICAL_STATE = 2; + + /** + * Detected (and bailed out of) an infinite loop in the token manager. + */ + static final int LOOP_DETECTED = 3; + + /** + * Indicates the reason why the exception is thrown. It will have + * one of the above 4 values. + */ + int errorCode; + + /** + * Replaces unprintable characters by their escaped (or unicode escaped) + * equivalents in the given string + */ + protected static final String addEscapes(String str) { + StringBuffer retval = new StringBuffer(); + char ch; + for (int i = 0; i < str.length(); i++) { + switch (str.charAt(i)) + { + case 0 : + continue; + case '\b': + retval.append("\\b"); + continue; + case '\t': + retval.append("\\t"); + continue; + case '\n': + retval.append("\\n"); + continue; + case '\f': + retval.append("\\f"); + continue; + case '\r': + retval.append("\\r"); + continue; + case '\"': + retval.append("\\\""); + continue; + case '\'': + retval.append("\\\'"); + continue; + case '\\': + retval.append("\\\\"); + continue; + default: + if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { + String s = "0000" + Integer.toString(ch, 16); + retval.append("\\u" + s.substring(s.length() - 4, s.length())); + } else { + retval.append(ch); + } + continue; + } + } + return retval.toString(); + } + + /** + * Returns a detailed message for the Error when it is thrown by the + * token manager to indicate a lexical error. + * Parameters : + * EOFSeen : indicates if EOF caused the lexical error + * curLexState : lexical state in which this error occurred + * errorLine : line number when the error occurred + * errorColumn : column number when the error occurred + * errorAfter : prefix that was seen before this error occurred + * curchar : the offending character + * Note: You can customize the lexical error message by modifying this method. + */ + protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) { + return("Lexical error at line " + + errorLine + ", column " + + errorColumn + ". Encountered: " + + (EOFSeen ? " " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") + + "after : \"" + addEscapes(errorAfter) + "\""); + } + + /** + * You can also modify the body of this method to customize your error messages. + * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not + * of end-users concern, so you can return something like : + * + * "Internal Error : Please file a bug report .... " + * + * from this method for such cases in the release version of your parser. + */ + public String getMessage() { + return super.getMessage(); + } + + /* + * Constructors of various flavors follow. + */ + + /** No arg constructor. */ + public TokenMgrError() { + } + + /** Constructor with message and reason. */ + public TokenMgrError(String message, int reason) { + super(message); + errorCode = reason; + } + + /** Full Constructor. */ + public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) { + this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); + } +} +/* JavaCC - OriginalChecksum=bd3720425dc7b44a5223b12676db358c (do not edit this line) */ diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/script/LuaScriptEngine.java b/luaj-2.0.3/src/jse/org/luaj/vm2/script/LuaScriptEngine.java new file mode 100644 index 0000000000..468a095d98 --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/script/LuaScriptEngine.java @@ -0,0 +1,286 @@ +/******************************************************************************* +* Copyright (c) 2008 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. +******************************************************************************/ +package org.luaj.vm2.script; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.io.StringReader; +import java.util.Iterator; + +import javax.script.Bindings; +import javax.script.Compilable; +import javax.script.CompiledScript; +import javax.script.ScriptContext; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineFactory; +import javax.script.ScriptException; +import javax.script.SimpleBindings; +import javax.script.SimpleScriptContext; + +import org.luaj.vm2.LoadState; +import org.luaj.vm2.Lua; +import org.luaj.vm2.LuaClosure; +import org.luaj.vm2.LuaError; +import org.luaj.vm2.LuaFunction; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Prototype; +import org.luaj.vm2.Varargs; +import org.luaj.vm2.lib.jse.CoerceJavaToLua; +import org.luaj.vm2.lib.jse.JsePlatform; + +/** + * + * @author jim_roseborough + */ +public class LuaScriptEngine implements ScriptEngine, Compilable { + + private static final String __ENGINE_VERSION__ = Lua._VERSION; + private static final String __NAME__ = "Luaj"; + private static final String __SHORT_NAME__ = "Luaj"; + private static final String __LANGUAGE__ = "lua"; + private static final String __LANGUAGE_VERSION__ = "5.1"; + private static final String __ARGV__ = "arg"; + private static final String __FILENAME__ = "?"; + + private static final ScriptEngineFactory myFactory = new LuaScriptEngineFactory(); + + private ScriptContext defaultContext; + + private final LuaValue _G; + + public LuaScriptEngine() { + + // create globals + _G = JsePlatform.standardGlobals(); + + // set up context + ScriptContext ctx = new SimpleScriptContext(); + ctx.setBindings(createBindings(), ScriptContext.ENGINE_SCOPE); + setContext(ctx); + + // set special values + put(LANGUAGE_VERSION, __LANGUAGE_VERSION__); + put(LANGUAGE, __LANGUAGE__); + put(ENGINE, __NAME__); + put(ENGINE_VERSION, __ENGINE_VERSION__); + put(ARGV, __ARGV__); + put(FILENAME, __FILENAME__); + put(NAME, __SHORT_NAME__); + put("THREADING", null); + } + + + public Object eval(String script) throws ScriptException { + return eval(new StringReader(script)); + } + + public Object eval(String script, ScriptContext context) throws ScriptException { + return eval(new StringReader(script), context); + } + + public Object eval(String script, Bindings bindings) throws ScriptException { + return eval(new StringReader(script), bindings); + } + + public Object eval(Reader reader) throws ScriptException { + return eval(reader, getContext()); + } + + public Object eval(Reader reader, ScriptContext scriptContext) throws ScriptException { + return compile(reader).eval(scriptContext); + } + + public Object eval(Reader reader, Bindings bindings) throws ScriptException { + ScriptContext c = getContext(); + Bindings current = c.getBindings(ScriptContext.ENGINE_SCOPE); + c.setBindings(bindings, ScriptContext.ENGINE_SCOPE); + Object result = eval(reader); + c.setBindings(current, ScriptContext.ENGINE_SCOPE); + return result; + } + + public void put(String key, Object value) { + Bindings b = getBindings(ScriptContext.ENGINE_SCOPE); + b.put(key, value); + } + + public Object get(String key) { + Bindings b = getBindings(ScriptContext.ENGINE_SCOPE); + return b.get(key); + } + + public Bindings getBindings(int scope) { + return getContext().getBindings(scope); + } + + public void setBindings(Bindings bindings, int scope) { + getContext().setBindings(bindings, scope); + } + + public Bindings createBindings() { + return new SimpleBindings(); + } + + public ScriptContext getContext() { + return defaultContext; + } + + public void setContext(ScriptContext context) { + defaultContext = context; + } + + public ScriptEngineFactory getFactory() { + return myFactory; + } + + public CompiledScript compile(String script) throws ScriptException { + return compile(new StringReader(script)); + } + + public CompiledScript compile(Reader reader) throws ScriptException { + try { + InputStream ris = new Utf8Encoder(reader); + try { + final LuaFunction f = LoadState.load(ris, "script", null); + if ( f.isclosure() ) { + // most compiled functions are closures with prototypes + final Prototype p = f.checkclosure().p; + return new CompiledScriptImpl() { + protected LuaFunction newFunctionInstance() { + return new LuaClosure( p, null ); + } + }; + } else { + // when luajc is used, functions are java class instances + final Class c = f.getClass(); + return new CompiledScriptImpl() { + protected LuaFunction newFunctionInstance() throws ScriptException { + try { + return (LuaFunction) c.newInstance(); + } catch (Exception e) { + throw new ScriptException("instantiation failed: "+e.toString()); + } + } + }; + } + } catch ( LuaError lee ) { + throw new ScriptException(lee.getMessage() ); + } finally { + ris.close(); + } + } catch ( Exception e ) { + throw new ScriptException("eval threw "+e.toString()); + } + } + + abstract protected class CompiledScriptImpl extends CompiledScript { + abstract protected LuaFunction newFunctionInstance() throws ScriptException; + public ScriptEngine getEngine() { + return LuaScriptEngine.this; + } + public Object eval(ScriptContext context) throws ScriptException { + Bindings b = context.getBindings(ScriptContext.ENGINE_SCOPE); + LuaFunction f = newFunctionInstance(); + ClientBindings cb = new ClientBindings(b); + f.setfenv(cb.env); + Varargs result = f.invoke(LuaValue.NONE); + cb.copyGlobalsToBindings(); + return result; + } + } + + public class ClientBindings { + public final Bindings b; + public final LuaTable env; + public ClientBindings( Bindings b ) { + this.b = b; + this.env = new LuaTable(); + env.setmetatable(LuaTable.tableOf(new LuaValue[] { LuaValue.INDEX, _G })); + this.copyBindingsToGlobals(); + } + public void copyBindingsToGlobals() { + for ( Iterator i = b.keySet().iterator(); i.hasNext(); ) { + String key = (String) i.next(); + Object val = b.get(key); + LuaValue luakey = toLua(key); + LuaValue luaval = toLua(val); + env.set(luakey, luaval); + i.remove(); + } + } + private LuaValue toLua(Object javaValue) { + return javaValue == null? LuaValue.NIL: + javaValue instanceof LuaValue? (LuaValue) javaValue: + CoerceJavaToLua.coerce(javaValue); + } + public void copyGlobalsToBindings() { + LuaValue[] keys = env.keys(); + for ( int i=0; i 0 ) + return buf[--n]; + int c = r.read(); + if ( c < 0x80 ) + return c; + n = 0; + if ( c < 0x800 ) { + buf[n++] = (0x80 | ( c & 0x3f)); + return (0xC0 | ((c>>6) & 0x1f)); + } else { + buf[n++] = (0x80 | ( c & 0x3f)); + buf[n++] = (0x80 | ((c>>6) & 0x3f)); + return (0xE0 | ((c>>12) & 0x0f)); + } + } + } +} diff --git a/luaj-2.0.3/src/jse/org/luaj/vm2/script/LuaScriptEngineFactory.java b/luaj-2.0.3/src/jse/org/luaj/vm2/script/LuaScriptEngineFactory.java new file mode 100644 index 0000000000..ac5b0a8b54 --- /dev/null +++ b/luaj-2.0.3/src/jse/org/luaj/vm2/script/LuaScriptEngineFactory.java @@ -0,0 +1,134 @@ +/******************************************************************************* +* Copyright (c) 2008 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. +******************************************************************************/ +package org.luaj.vm2.script; + +import java.util.Arrays; +import java.util.List; + +import javax.script.ScriptEngine; +import javax.script.ScriptEngineFactory; + +/** + * Jsr 223 scripting engine factory + */ +public class LuaScriptEngineFactory implements ScriptEngineFactory { + + private static final String [] EXTENSIONS = { + "lua", + ".lua", + }; + + private static final String [] MIMETYPES = { + "text/plain", + "text/lua", + "application/lua" + }; + + private static final String [] NAMES = { + "lua", + "luaj", + }; + + private static final ThreadLocal engines + = new ThreadLocal(); + private List extensions; + private List mimeTypes; + private List names; + + + public LuaScriptEngineFactory() { + extensions = Arrays.asList(EXTENSIONS); + mimeTypes = Arrays.asList(MIMETYPES); + names = Arrays.asList(NAMES); + } + + public String getEngineName() { + return getScriptEngine().get(ScriptEngine.ENGINE).toString(); + } + + public String getEngineVersion() { + return getScriptEngine().get(ScriptEngine.ENGINE_VERSION).toString(); + } + + public List getExtensions() { + return extensions; + } + + public List getMimeTypes() { + return mimeTypes; + } + + public List getNames() { + return names; + } + + public String getLanguageName() { + return getScriptEngine().get(ScriptEngine.LANGUAGE).toString(); + } + + public String getLanguageVersion() { + return getScriptEngine().get(ScriptEngine.LANGUAGE_VERSION).toString(); + } + + public Object getParameter(String key) { + return getScriptEngine().get(key).toString(); + } + + public String getMethodCallSyntax(String obj, String m, String... args) { + StringBuffer sb = new StringBuffer(); + sb.append(obj + ":" + m + "("); + int len = args.length; + for (int i = 0; i < len; i++) { + if (i > 0) { + sb.append(','); + } + sb.append(args[i]); + } + sb.append(")"); + return sb.toString(); + } + + public String getOutputStatement(String toDisplay) { + return "print(" + toDisplay + ")"; + } + + public String getProgram(String ... statements) { + StringBuffer sb = new StringBuffer(); + int len = statements.length; + for (int i = 0; i < len; i++) { + if (i > 0) { + sb.append('\n'); + } + sb.append(statements[i]); + } + return sb.toString(); + } + + public ScriptEngine getScriptEngine() { + ScriptEngine eng = engines.get(); + if ( eng == null ) { + eng = new LuaScriptEngine(); + engines.set(eng); + } + return eng; + } +} diff --git a/luaj-2.0.3/test/java/org/luaj/luajc/TestLuaJ.java b/luaj-2.0.3/test/java/org/luaj/luajc/TestLuaJ.java new file mode 100644 index 0000000000..04edb2a900 --- /dev/null +++ b/luaj-2.0.3/test/java/org/luaj/luajc/TestLuaJ.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2009 Luaj.org. 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. + ******************************************************************************/ +package org.luaj.luajc; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import org.luaj.vm2.LuaClosure; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Print; +import org.luaj.vm2.Prototype; +import org.luaj.vm2.compiler.LuaC; +import org.luaj.vm2.lib.jse.JsePlatform; + +/** Test the plain old bytecode interpreter */ +public class TestLuaJ { + // create the script + public static String name = "script"; + public static String script = + "function r(q,...)\n"+ + " local a=arg\n"+ + " return a and a[2]\n"+ + "end\n" + + "function s(q,...)\n"+ + " local a=arg\n"+ + " local b=...\n"+ + " return a and a[2],b\n"+ + "end\n" + + "print( r(111,222,333),s(111,222,333) )"; + + public static void main(String[] args) throws Exception { + System.out.println(script); + + // create an environment to run in + LuaTable _G = JsePlatform.standardGlobals(); + + // compile into a chunk, or load as a class + InputStream is = new ByteArrayInputStream( script.getBytes() ); + LuaValue chunk = LuaC.instance.load(is, "script",_G); + chunk.call(); + } + + private static void print(Prototype p) { + System.out.println("--- "+p.is_vararg); + Print.printCode(p); + if (p.p!=null) + for ( int i=0,n=p.p.length; i0 && args[0].equals("nocompile")) ) { + InputStream is = new ByteArrayInputStream( script.getBytes() ); + chunk = LuaJC.getInstance().load(is, "script", _G); + } else { + chunk = (LuaValue) Class.forName("script").newInstance(); + } + chunk.setfenv(_G); + + // call with arguments + LuaValue[] vargs = new LuaValue[args.length]; + for ( int i=0; ic), (b>0)\n" ); + } + + public void testNumericForUpvalues() { + runFragment( LuaValue.valueOf(8), + "for i = 3,4 do\n"+ + " i = i + 5\n"+ + " local a = function()\n"+ + " return i\n"+ + " end\n" + + " return a()\n"+ + "end\n"); + } + + public void testNumericForUpvalues2() { + runFragment( LuaValue.valueOf("222 222"), + "local t = {}\n"+ + "local template = [[123 456]]\n"+ + "for i = 1,2 do\n"+ + " t[i] = template:gsub('%d', function(s)\n"+ + " return i\n"+ + " end)\n"+ + "end\n" + + "return t[2]\n"); + } + + public void testReturnUpvalue() { + runFragment( LuaValue.varargsOf(new LuaValue[] { LuaValue.ONE, LuaValue.valueOf(5), }), + "local a = 1\n"+ + "local b\n"+ + "function c()\n"+ + " b=5\n" + + " return a\n"+ + "end\n"+ + "return c(),b\n" ); + } + + public void testUninitializedAroundBranch() { + runFragment( LuaValue.valueOf(333), + "local state\n"+ + "if _G then\n"+ + " state = 333\n"+ + "end\n"+ + "return state\n" ); + } + + public void testLoadedNilUpvalue() { + runFragment( LuaValue.NIL, + "local a = print()\n"+ + "local b = c and { d = e }\n"+ + "local f\n"+ + "local function g()\n"+ + " return f\n"+ + "end\n" + + "return g()\n" ); + } + + public void testUpvalueInFirstSlot() { + runFragment( LuaValue.valueOf("foo"), + "local p = {'foo'}\n"+ + "bar = function()\n"+ + " return p \n"+ + "end\n"+ + "for i,key in ipairs(p) do\n"+ + " print()\n"+ + "end\n" + + "return bar()[1]"); + } + + public void testReadOnlyAndReadWriteUpvalues() { + runFragment( LuaValue.varargsOf( new LuaValue[] { LuaValue.valueOf(333), LuaValue.valueOf(222) } ), + "local a = 111\n" + + "local b = 222\n" + + "local c = function()\n"+ + " a = a + b\n" + + " return a,b\n"+ + "end\n" + + "return c()\n" ); + } + + public void testNestedUpvalues() { + runFragment( LuaValue.varargsOf( new LuaValue[] { LuaValue.valueOf(5), LuaValue.valueOf(8), LuaValue.valueOf(9) } ), + "local x = 3\n"+ + "local y = 5\n"+ + "local function f()\n"+ + " return y\n"+ + "end\n"+ + "local function g(x1, y1)\n"+ + " x = x1\n"+ + " y = y1\n" + + " return x,y\n"+ + "end\n"+ + "return f(), g(8,9)\n"+ + "\n" ); + } + + public void testLoadBool() { + runFragment( LuaValue.NONE, + "print( type(foo)=='string' )\n"+ + "local a,b\n"+ + "if print() then\n"+ + " b = function()\n"+ + " return a\n"+ + " end\n"+ + "end\n" ); + } + + public void testBasicForLoop() { + runFragment( LuaValue.valueOf(2), + "local data\n"+ + "for i = 1, 2 do\n"+ + " data = i\n"+ + "end\n"+ + "local bar = function()\n"+ + " return data\n"+ + "end\n" + + "return bar()\n" ); + } + + public void testGenericForMultipleValues() { + runFragment( LuaValue.varargsOf(LuaValue.valueOf(3),LuaValue.valueOf(2),LuaValue.valueOf(1)), + "local iter = function() return 1,2,3,4 end\n" + + "local foo = function() return iter,5 end\n" + + "for a,b,c in foo() do\n" + + " return c,b,a\n" + + "end\n" ); + } + + public void testPhiUpvalue() { + runFragment( LuaValue.valueOf(6), + "local a = foo or 0\n"+ + "local function b(c)\n"+ + " if c > a then a = c end\n" + + " return a\n"+ + "end\n" + + "b(6)\n" + + "return a\n" ); + } + + public void testAssignReferUpvalues() { + runFragment( LuaValue.valueOf(123), + "local entity = 234\n" + + "local function c()\n" + + " return entity\n" + + "end\n" + + "entity = (a == b) and 123\n" + + "if entity then\n" + + " return entity\n" + + "end\n" ); + } + + public void testSimpleRepeatUntil() { + runFragment( LuaValue.valueOf(5), + "local a\n"+ + "local w\n"+ + "repeat\n"+ + " a = w\n"+ + "until not a\n" + + "return 5\n" ); + } + + public void testLoopVarUpvalues() { + runFragment( LuaValue.valueOf("b"), + "local env = {}\n" + + "for a,b in pairs(_G) do\n" + + " c = function()\n" + + " return b\n" + + " end\n" + + "end\n" + + "local e = env\n" + + "local f = {a='b'}\n" + + "for k,v in pairs(f) do\n" + + " return env[k] or v\n" + + "end\n"); + } + + public void testPhiVarUpvalue() { + runFragment( LuaValue.valueOf(2), + "local a = 1\n"+ + "local function b()\n"+ + " a = a + 1\n"+ + " return function() end\n"+ + "end\n"+ + "for i in b() do\n"+ + " a = 3\n"+ + "end\n" + + "return a\n"); + } + + public void testUpvaluesInElseClauses() { + runFragment( LuaValue.valueOf(111), + "if a then\n" + + " foo(bar)\n" + + "elseif _G then\n" + + " local x = 111\n" + + " if d then\n" + + " foo(bar)\n" + + " else\n" + + " local y = function()\n" + + " return x\n" + + " end\n" + + " return y()\n" + + " end\n" + + "end\n"); + } + } +} diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/LuaOperationsTest.java b/luaj-2.0.3/test/junit/org/luaj/vm2/LuaOperationsTest.java new file mode 100644 index 0000000000..7945fdc383 --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/LuaOperationsTest.java @@ -0,0 +1,261 @@ +/******************************************************************************* + * Copyright (c) 2009 Luaj.org. 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. + ******************************************************************************/ +package org.luaj.vm2; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; + +import junit.framework.TestCase; + +import org.luaj.vm2.TypeTest.MyData; +import org.luaj.vm2.compiler.LuaC; +import org.luaj.vm2.lib.ZeroArgFunction; + +public class LuaOperationsTest extends TestCase { + + private final int sampleint = 77; + private final long samplelong = 123400000000L; + private final double sampledouble = 55.25; + private final String samplestringstring = "abcdef"; + private final String samplestringint = String.valueOf(sampleint); + private final String samplestringlong = String.valueOf(samplelong); + private final String samplestringdouble = String.valueOf(sampledouble); + private final Object sampleobject = new Object(); + private final MyData sampledata = new MyData(); + + private final LuaValue somenil = LuaValue.NIL; + private final LuaValue sometrue = LuaValue.TRUE; + private final LuaValue somefalse = LuaValue.FALSE; + private final LuaValue zero = LuaValue.ZERO; + private final LuaValue intint = LuaValue.valueOf(sampleint); + private final LuaValue longdouble = LuaValue.valueOf(samplelong); + private final LuaValue doubledouble = LuaValue.valueOf(sampledouble); + private final LuaValue stringstring = LuaValue.valueOf(samplestringstring); + private final LuaValue stringint = LuaValue.valueOf(samplestringint); + private final LuaValue stringlong = LuaValue.valueOf(samplestringlong); + private final LuaValue stringdouble = LuaValue.valueOf(samplestringdouble); + private final LuaTable table = LuaValue.listOf( new LuaValue[] { LuaValue.valueOf("aaa"), LuaValue.valueOf("bbb") } ); + private final LuaValue somefunc = new ZeroArgFunction(table) { public LuaValue call() { return NONE;}}; + private final LuaThread thread = new LuaThread(somefunc,table); + private final Prototype proto = new Prototype(); + private final LuaClosure someclosure = new LuaClosure(proto,table); + private final LuaUserdata userdataobj = LuaValue.userdataOf(sampleobject); + private final LuaUserdata userdatacls = LuaValue.userdataOf(sampledata); + + private void throwsLuaError(String methodName, Object obj) { + try { + LuaValue.class.getMethod(methodName).invoke(obj); + fail("failed to throw LuaError as required"); + } catch (InvocationTargetException e) { + if ( ! (e.getTargetException() instanceof LuaError) ) + fail("not a LuaError: "+e.getTargetException()); + return; // pass + } catch ( Exception e ) { + fail( "bad exception: "+e ); + } + } + + private void throwsLuaError(String methodName, Object obj, Object arg) { + try { + LuaValue.class.getMethod(methodName,LuaValue.class).invoke(obj,arg); + fail("failed to throw LuaError as required"); + } catch (InvocationTargetException e) { + if ( ! (e.getTargetException() instanceof LuaError) ) + fail("not a LuaError: "+e.getTargetException()); + return; // pass + } catch ( Exception e ) { + fail( "bad exception: "+e ); + } + } + + public void testLen() { + throwsLuaError( "len", somenil ); + throwsLuaError( "len", sometrue ); + throwsLuaError( "len", somefalse ); + throwsLuaError( "len", zero ); + throwsLuaError( "len", intint ); + throwsLuaError( "len", longdouble ); + throwsLuaError( "len", doubledouble ); + assertEquals( LuaInteger.valueOf(samplestringstring.length()), stringstring.len() ); + assertEquals( LuaInteger.valueOf(samplestringint.length()), stringint.len() ); + assertEquals( LuaInteger.valueOf(samplestringlong.length()), stringlong.len() ); + assertEquals( LuaInteger.valueOf(samplestringdouble.length()), stringdouble.len() ); + assertEquals( LuaInteger.valueOf(2), table.len() ); + throwsLuaError( "len", somefunc ); + throwsLuaError( "len", thread ); + throwsLuaError( "len", someclosure ); + throwsLuaError( "len", userdataobj ); + throwsLuaError( "len", userdatacls ); + } + + public void testLength() { + throwsLuaError( "length", somenil ); + throwsLuaError( "length", sometrue ); + throwsLuaError( "length", somefalse ); + throwsLuaError( "length", zero ); + throwsLuaError( "length", intint ); + throwsLuaError( "length", longdouble ); + throwsLuaError( "length", doubledouble ); + assertEquals( samplestringstring.length(), stringstring.length() ); + assertEquals( samplestringint.length(), stringint.length() ); + assertEquals( samplestringlong.length(), stringlong.length() ); + assertEquals( samplestringdouble.length(), stringdouble.length() ); + assertEquals( 2, table.length() ); + throwsLuaError( "length", somefunc ); + throwsLuaError( "length", thread ); + throwsLuaError( "length", someclosure ); + throwsLuaError( "length", userdataobj ); + throwsLuaError( "length", userdatacls ); + } + + public void testGetfenv() { + throwsLuaError( "getfenv", somenil ); + throwsLuaError( "getfenv", sometrue ); + throwsLuaError( "getfenv", somefalse ); + throwsLuaError( "getfenv", zero ); + throwsLuaError( "getfenv", intint ); + throwsLuaError( "getfenv", longdouble ); + throwsLuaError( "getfenv", doubledouble ); + throwsLuaError( "getfenv", stringstring ); + throwsLuaError( "getfenv", stringint ); + throwsLuaError( "getfenv", stringlong ); + throwsLuaError( "getfenv", stringdouble ); + throwsLuaError( "getfenv", table ); + assertTrue( table == thread.getfenv() ); + assertTrue( table == someclosure.getfenv() ); + assertTrue( table == somefunc.getfenv() ); + throwsLuaError( "getfenv", userdataobj ); + throwsLuaError( "getfenv", userdatacls ); + } + + public void testSetfenv() { + LuaTable table2 = LuaValue.listOf( new LuaValue[] { + LuaValue.valueOf("ccc"), + LuaValue.valueOf("ddd") } ); + throwsLuaError( "setfenv", somenil, table2 ); + throwsLuaError( "setfenv", sometrue, table2 ); + throwsLuaError( "setfenv", somefalse, table2 ); + throwsLuaError( "setfenv", zero, table2 ); + throwsLuaError( "setfenv", intint, table2 ); + throwsLuaError( "setfenv", longdouble, table2 ); + throwsLuaError( "setfenv", doubledouble, table2 ); + throwsLuaError( "setfenv", stringstring, table2 ); + throwsLuaError( "setfenv", stringint, table2 ); + throwsLuaError( "setfenv", stringlong, table2 ); + throwsLuaError( "setfenv", stringdouble, table2 ); + throwsLuaError( "setfenv", table, table2 ); + thread.setfenv(table2); + assertTrue( table2 == thread.getfenv() ); + assertTrue( table == someclosure.getfenv() ); + assertTrue( table == somefunc.getfenv() ); + someclosure.setfenv(table2); + assertTrue( table2 == someclosure.getfenv() ); + assertTrue( table == somefunc.getfenv() ); + somefunc.setfenv(table2); + assertTrue( table2 == somefunc.getfenv() ); + throwsLuaError( "setfenv", userdataobj, table2 ); + throwsLuaError( "setfenv", userdatacls, table2 ); + } + + public Prototype createPrototype( String script, String name ) { + try { + LuaTable _G = org.luaj.vm2.lib.jse.JsePlatform.standardGlobals(); + InputStream is = new ByteArrayInputStream(script.getBytes("UTF-8")); + return LuaC.instance.compile(is, name); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + fail(e.toString()); + return null; + } + } + + public void testFunctionClosureThreadEnv() { + + // set up suitable environments for execution + LuaValue aaa = LuaValue.valueOf("aaa"); + LuaValue eee = LuaValue.valueOf("eee"); + LuaTable _G = org.luaj.vm2.lib.jse.JsePlatform.standardGlobals(); + LuaTable newenv = LuaValue.tableOf( new LuaValue[] { + LuaValue.valueOf("a"), LuaValue.valueOf("aaa"), + LuaValue.valueOf("b"), LuaValue.valueOf("bbb"), } ); + LuaTable mt = LuaValue.tableOf( new LuaValue[] { LuaValue.INDEX, _G } ); + newenv.setmetatable(mt); + _G.set("a", aaa); + newenv.set("a", eee); + + // function tests + { + LuaFunction f = new ZeroArgFunction(_G) { public LuaValue call() { return env.get("a");}}; + assertEquals( aaa, f.call() ); + f.setfenv(newenv); + assertEquals( newenv, f.getfenv() ); + assertEquals( eee, f.call() ); + } + + // closure tests + { + Prototype p = createPrototype( "return a\n", "closuretester" ); + LuaClosure c = new LuaClosure(p, _G); + assertEquals( aaa, c.call() ); + c.setfenv(newenv); + assertEquals( newenv, c.getfenv() ); + assertEquals( eee, c.call() ); + } + + // thread tests, functions created in threads inherit the thread's environment initially + // those closures created not in any other function get the thread's enviroment + Prototype p2 = createPrototype( "return loadstring('return a')", "threadtester" ); + { + LuaThread t = new LuaThread(new LuaClosure(p2,_G), _G); + Varargs v = t.resume(LuaValue.NONE); + assertEquals(LuaValue.TRUE, v.arg(1) ); + LuaValue f = v.arg(2); + assertEquals( LuaValue.TFUNCTION, f.type() ); + assertEquals( aaa, f.call() ); + assertEquals( _G, f.getfenv() ); + } + { + // change the thread environment after creation! + LuaThread t = new LuaThread(new LuaClosure(p2,_G), _G); + t.setfenv(newenv); + Varargs v = t.resume(LuaValue.NONE); + assertEquals(LuaValue.TRUE, v.arg(1) ); + LuaValue f = v.arg(2); + assertEquals( LuaValue.TFUNCTION, f.type() ); + assertEquals( eee, f.call() ); + assertEquals( newenv, f.getfenv() ); + } + { + // let the closure have a different environment from the thread + Prototype p3 = createPrototype( "return function() return a end", "envtester" ); + LuaThread t = new LuaThread(new LuaClosure(p3,newenv), _G); + Varargs v = t.resume(LuaValue.NONE); + assertEquals(LuaValue.TRUE, v.arg(1) ); + LuaValue f = v.arg(2); + assertEquals( LuaValue.TFUNCTION, f.type() ); + assertEquals( eee, f.call() ); + assertEquals( newenv, f.getfenv() ); + } + } +} diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/MathLibTest.java b/luaj-2.0.3/test/junit/org/luaj/vm2/MathLibTest.java new file mode 100644 index 0000000000..47e3423806 --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/MathLibTest.java @@ -0,0 +1,251 @@ +package org.luaj.vm2; + +import junit.framework.TestCase; + +import org.luaj.vm2.lib.MathLib; +import org.luaj.vm2.lib.jse.JseMathLib; +import org.luaj.vm2.lib.jse.JsePlatform; + +public class MathLibTest extends TestCase { + + private LuaValue j2se; + private LuaValue j2me; + private boolean supportedOnJ2me; + + public MathLibTest() { + LuaValue g = JsePlatform.standardGlobals(); + j2se = g.get("math"); + g.load( new MathLib() ); + j2me = g.get("math"); + } + + protected void setUp() throws Exception { + supportedOnJ2me = true; + } + + public void testMathDPow() { + assertEquals( 1, j2mepow(2, 0), 0 ); + assertEquals( 2, j2mepow(2, 1), 0 ); + assertEquals( 8, j2mepow(2, 3), 0 ); + assertEquals( -8, j2mepow(-2, 3), 0 ); + assertEquals( 1/8., j2mepow(2, -3), 0 ); + assertEquals( -1/8., j2mepow(-2, -3), 0 ); + assertEquals( 16, j2mepow(256, .5), 0 ); + assertEquals( 4, j2mepow(256, .25), 0 ); + assertEquals( 64, j2mepow(256, .75), 0 ); + assertEquals( 1./16, j2mepow(256, - .5), 0 ); + assertEquals( 1./ 4, j2mepow(256, -.25), 0 ); + assertEquals( 1./64, j2mepow(256, -.75), 0 ); + assertEquals( Double.NaN, j2mepow(-256, .5), 0 ); + assertEquals( 1, j2mepow(.5, 0), 0 ); + assertEquals( .5, j2mepow(.5, 1), 0 ); + assertEquals(.125, j2mepow(.5, 3), 0 ); + assertEquals( 2, j2mepow(.5, -1), 0 ); + assertEquals( 8, j2mepow(.5, -3), 0 ); + assertEquals(1, j2mepow(0.0625, 0), 0 ); + assertEquals(0.00048828125, j2mepow(0.0625, 2.75), 0 ); + } + + private double j2mepow(double x, double y) { + return j2me.get("pow").call(LuaValue.valueOf(x),LuaValue.valueOf(y)).todouble(); + } + + public void testAbs() { + tryMathOp( "abs", 23.45 ); + tryMathOp( "abs", -23.45 ); + } + + public void testCos() { + tryTrigOps( "cos" ); + } + + public void testCosh() { + supportedOnJ2me = false; + tryTrigOps( "cosh" ); + } + + public void testDeg() { + tryTrigOps( "deg" ); + } + + public void testExp() { + //supportedOnJ2me = false; + tryMathOp( "exp", 0 ); + tryMathOp( "exp", 0.1 ); + tryMathOp( "exp", .9 ); + tryMathOp( "exp", 1. ); + tryMathOp( "exp", 9 ); + tryMathOp( "exp", -.1 ); + tryMathOp( "exp", -.9 ); + tryMathOp( "exp", -1. ); + tryMathOp( "exp", -9 ); + } + + public void testLog() { + supportedOnJ2me = false; + tryMathOp( "log", 0.1 ); + tryMathOp( "log", .9 ); + tryMathOp( "log", 1. ); + tryMathOp( "log", 9 ); + tryMathOp( "log", -.1 ); + tryMathOp( "log", -.9 ); + tryMathOp( "log", -1. ); + tryMathOp( "log", -9 ); + } + + public void testLog10() { + supportedOnJ2me = false; + tryMathOp( "log10", 0.1 ); + tryMathOp( "log10", .9 ); + tryMathOp( "log10", 1. ); + tryMathOp( "log10", 9 ); + tryMathOp( "log10", 10 ); + tryMathOp( "log10", 100 ); + tryMathOp( "log10", -.1 ); + tryMathOp( "log10", -.9 ); + tryMathOp( "log10", -1. ); + tryMathOp( "log10", -9 ); + tryMathOp( "log10", -10 ); + tryMathOp( "log10", -100 ); + } + + public void testRad() { + tryMathOp( "rad", 0 ); + tryMathOp( "rad", 0.1 ); + tryMathOp( "rad", .9 ); + tryMathOp( "rad", 1. ); + tryMathOp( "rad", 9 ); + tryMathOp( "rad", 10 ); + tryMathOp( "rad", 100 ); + tryMathOp( "rad", -.1 ); + tryMathOp( "rad", -.9 ); + tryMathOp( "rad", -1. ); + tryMathOp( "rad", -9 ); + tryMathOp( "rad", -10 ); + tryMathOp( "rad", -100 ); + } + + public void testSin() { + tryTrigOps( "sin" ); + } + + public void testSinh() { + supportedOnJ2me = false; + tryTrigOps( "sinh" ); + } + + public void testSqrt() { + tryMathOp( "sqrt", 0 ); + tryMathOp( "sqrt", 0.1 ); + tryMathOp( "sqrt", .9 ); + tryMathOp( "sqrt", 1. ); + tryMathOp( "sqrt", 9 ); + tryMathOp( "sqrt", 10 ); + tryMathOp( "sqrt", 100 ); + } + public void testTan() { + tryTrigOps( "tan" ); + } + + public void testTanh() { + supportedOnJ2me = false; + tryTrigOps( "tanh" ); + } + + public void testAtan2() { + supportedOnJ2me = false; + tryDoubleOps( "atan2", false ); + } + + public void testFmod() { + tryDoubleOps( "fmod", false ); + } + + public void testPow() { + tryDoubleOps( "pow", true ); + } + + private void tryDoubleOps( String op, boolean positiveOnly ) { + // y>0, x>0 + tryMathOp( op, 0.1, 4.0 ); + tryMathOp( op, .9, 4.0 ); + tryMathOp( op, 1., 4.0 ); + tryMathOp( op, 9, 4.0 ); + tryMathOp( op, 10, 4.0 ); + tryMathOp( op, 100, 4.0 ); + + // y>0, x<0 + tryMathOp( op, 0.1, -4.0 ); + tryMathOp( op, .9, -4.0 ); + tryMathOp( op, 1., -4.0 ); + tryMathOp( op, 9, -4.0 ); + tryMathOp( op, 10, -4.0 ); + tryMathOp( op, 100, -4.0 ); + + if ( ! positiveOnly ) { + // y<0, x>0 + tryMathOp( op, -0.1, 4.0 ); + tryMathOp( op, -.9, 4.0 ); + tryMathOp( op, -1., 4.0 ); + tryMathOp( op, -9, 4.0 ); + tryMathOp( op, -10, 4.0 ); + tryMathOp( op, -100, 4.0 ); + + // y<0, x<0 + tryMathOp( op, -0.1, -4.0 ); + tryMathOp( op, -.9, -4.0 ); + tryMathOp( op, -1., -4.0 ); + tryMathOp( op, -9, -4.0 ); + tryMathOp( op, -10, -4.0 ); + tryMathOp( op, -100, -4.0 ); + } + + // degenerate cases + tryMathOp( op, 0, 1 ); + tryMathOp( op, 1, 0 ); + tryMathOp( op, -1, 0 ); + tryMathOp( op, 0, -1 ); + tryMathOp( op, 0, 0 ); + } + + private void tryTrigOps(String op) { + tryMathOp( op, 0 ); + tryMathOp( op, Math.PI/8 ); + tryMathOp( op, Math.PI*7/8 ); + tryMathOp( op, Math.PI*8/8 ); + tryMathOp( op, Math.PI*9/8 ); + tryMathOp( op, -Math.PI/8 ); + tryMathOp( op, -Math.PI*7/8 ); + tryMathOp( op, -Math.PI*8/8 ); + tryMathOp( op, -Math.PI*9/8 ); + } + + private void tryMathOp(String op, double x) { + try { + double expected = j2se.get(op).call( LuaValue.valueOf(x)).todouble(); + double actual = j2me.get(op).call( LuaValue.valueOf(x)).todouble(); + if ( supportedOnJ2me ) + assertEquals( expected, actual, 1.e-4 ); + else + fail("j2me should throw exception for math."+op+" but returned "+actual); + } catch ( LuaError lee ) { + if ( supportedOnJ2me ) + throw lee; + } + } + + + private void tryMathOp(String op, double a, double b) { + try { + double expected = j2se.get(op).call( LuaValue.valueOf(a), LuaValue.valueOf(b)).todouble(); + double actual = j2me.get(op).call( LuaValue.valueOf(a), LuaValue.valueOf(b)).todouble(); + if ( supportedOnJ2me ) + assertEquals( expected, actual, 1.e-5 ); + else + fail("j2me should throw exception for math."+op+" but returned "+actual); + } catch ( LuaError lee ) { + if ( supportedOnJ2me ) + throw lee; + } + } +} diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/MetatableTest.java b/luaj-2.0.3/test/junit/org/luaj/vm2/MetatableTest.java new file mode 100644 index 0000000000..42526011e0 --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/MetatableTest.java @@ -0,0 +1,366 @@ +/******************************************************************************* + * Copyright (c) 2009 Luaj.org. 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. + ******************************************************************************/ +package org.luaj.vm2; + +import junit.framework.TestCase; + +import org.luaj.vm2.TypeTest.MyData; +import org.luaj.vm2.lib.StringLib; +import org.luaj.vm2.lib.ThreeArgFunction; +import org.luaj.vm2.lib.TwoArgFunction; +import org.luaj.vm2.lib.ZeroArgFunction; + +public class MetatableTest extends TestCase { + + private final String samplestring = "abcdef"; + private final Object sampleobject = new Object(); + private final MyData sampledata = new MyData(); + + private final LuaValue string = LuaValue.valueOf(samplestring); + private final LuaTable table = LuaValue.tableOf(); + private final LuaFunction function = new ZeroArgFunction() { public LuaValue call() { return NONE;}}; + private final LuaThread thread = new LuaThread(function,table); + private final LuaClosure closure = new LuaClosure(); + private final LuaUserdata userdata = LuaValue.userdataOf(sampleobject); + private final LuaUserdata userdatamt = LuaValue.userdataOf(sampledata,table); + + protected void setUp() throws Exception { + // needed for metatable ops to work on strings + new StringLib(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + LuaBoolean.s_metatable = null; + LuaFunction.s_metatable = null; + LuaNil.s_metatable = null; + LuaNumber.s_metatable = null; +// LuaString.s_metatable = null; + LuaThread.s_metatable = null; + } + + public void testGetMetatable() { + assertEquals( null, LuaValue.NIL.getmetatable() ); + assertEquals( null, LuaValue.TRUE.getmetatable() ); + assertEquals( null, LuaValue.ONE.getmetatable() ); +// assertEquals( null, string.getmetatable() ); + assertEquals( null, table.getmetatable() ); + assertEquals( null, function.getmetatable() ); + assertEquals( null, thread.getmetatable() ); + assertEquals( null, closure.getmetatable() ); + assertEquals( null, userdata.getmetatable() ); + assertEquals( table, userdatamt.getmetatable() ); + } + + public void testSetMetatable() { + LuaValue mt = LuaValue.tableOf(); + assertEquals( null, table.getmetatable() ); + assertEquals( null, userdata.getmetatable() ); + assertEquals( table, userdatamt.getmetatable() ); + assertEquals( table, table.setmetatable(mt) ); + assertEquals( userdata, userdata.setmetatable(mt) ); + assertEquals( userdatamt, userdatamt.setmetatable(mt) ); + assertEquals( mt, table.getmetatable() ); + assertEquals( mt, userdata.getmetatable() ); + assertEquals( mt, userdatamt.getmetatable() ); + + // these all get metatable behind-the-scenes + assertEquals( null, LuaValue.NIL.getmetatable() ); + assertEquals( null, LuaValue.TRUE.getmetatable() ); + assertEquals( null, LuaValue.ONE.getmetatable() ); +// assertEquals( null, string.getmetatable() ); + assertEquals( null, function.getmetatable() ); + assertEquals( null, thread.getmetatable() ); + assertEquals( null, closure.getmetatable() ); + LuaNil.s_metatable = mt; + assertEquals( mt, LuaValue.NIL.getmetatable() ); + assertEquals( null, LuaValue.TRUE.getmetatable() ); + assertEquals( null, LuaValue.ONE.getmetatable() ); +// assertEquals( null, string.getmetatable() ); + assertEquals( null, function.getmetatable() ); + assertEquals( null, thread.getmetatable() ); + assertEquals( null, closure.getmetatable() ); + LuaBoolean.s_metatable = mt; + assertEquals( mt, LuaValue.TRUE.getmetatable() ); + assertEquals( null, LuaValue.ONE.getmetatable() ); +// assertEquals( null, string.getmetatable() ); + assertEquals( null, function.getmetatable() ); + assertEquals( null, thread.getmetatable() ); + assertEquals( null, closure.getmetatable() ); + LuaNumber.s_metatable = mt; + assertEquals( mt, LuaValue.ONE.getmetatable() ); + assertEquals( mt, LuaValue.valueOf(1.25).getmetatable() ); +// assertEquals( null, string.getmetatable() ); + assertEquals( null, function.getmetatable() ); + assertEquals( null, thread.getmetatable() ); + assertEquals( null, closure.getmetatable() ); +// LuaString.s_metatable = mt; +// assertEquals( mt, string.getmetatable() ); + assertEquals( null, function.getmetatable() ); + assertEquals( null, thread.getmetatable() ); + assertEquals( null, closure.getmetatable() ); + LuaFunction.s_metatable = mt; + assertEquals( mt, function.getmetatable() ); + assertEquals( null, thread.getmetatable() ); + LuaThread.s_metatable = mt; + assertEquals( mt, thread.getmetatable() ); + } + + public void testMetatableIndex() { + assertEquals( table, table.setmetatable(null) ); + assertEquals( userdata, userdata.setmetatable(null) ); + assertEquals( userdatamt, userdatamt.setmetatable(null) ); + assertEquals( LuaValue.NIL, table.get(1) ); + assertEquals( LuaValue.NIL, userdata.get(1) ); + assertEquals( LuaValue.NIL, userdatamt.get(1) ); + + // empty metatable + LuaValue mt = LuaValue.tableOf(); + assertEquals( table, table.setmetatable(mt) ); + assertEquals( userdata, userdata.setmetatable(mt) ); + LuaBoolean.s_metatable = mt; + LuaFunction.s_metatable = mt; + LuaNil.s_metatable = mt; + LuaNumber.s_metatable = mt; +// LuaString.s_metatable = mt; + LuaThread.s_metatable = mt; + assertEquals( mt, table.getmetatable() ); + assertEquals( mt, userdata.getmetatable() ); + assertEquals( mt, LuaValue.NIL.getmetatable() ); + assertEquals( mt, LuaValue.TRUE.getmetatable() ); + assertEquals( mt, LuaValue.ONE.getmetatable() ); +// assertEquals( StringLib.instance, string.getmetatable() ); + assertEquals( mt, function.getmetatable() ); + assertEquals( mt, thread.getmetatable() ); + + // plain metatable + LuaValue abc = LuaValue.valueOf("abc"); + mt.set( LuaValue.INDEX, LuaValue.listOf(new LuaValue[] { abc } ) ); + assertEquals( abc, table.get(1) ); + assertEquals( abc, userdata.get(1) ); + assertEquals( abc, LuaValue.NIL.get(1) ); + assertEquals( abc, LuaValue.TRUE.get(1) ); + assertEquals( abc, LuaValue.ONE.get(1) ); +// assertEquals( abc, string.get(1) ); + assertEquals( abc, function.get(1) ); + assertEquals( abc, thread.get(1) ); + + // plain metatable + mt.set( LuaValue.INDEX, new TwoArgFunction() { + public LuaValue call(LuaValue arg1, LuaValue arg2) { + return LuaValue.valueOf( arg1.typename()+"["+arg2.tojstring()+"]=xyz" ); + } + + }); + assertEquals( "table[1]=xyz", table.get(1).tojstring() ); + assertEquals( "userdata[1]=xyz", userdata.get(1).tojstring() ); + assertEquals( "nil[1]=xyz", LuaValue.NIL.get(1).tojstring() ); + assertEquals( "boolean[1]=xyz", LuaValue.TRUE.get(1).tojstring() ); + assertEquals( "number[1]=xyz", LuaValue.ONE.get(1).tojstring() ); + // assertEquals( "string[1]=xyz", string.get(1).tojstring() ); + assertEquals( "function[1]=xyz", function.get(1).tojstring() ); + assertEquals( "thread[1]=xyz", thread.get(1).tojstring() ); + } + + + public void testMetatableNewIndex() { + // empty metatable + LuaValue mt = LuaValue.tableOf(); + assertEquals( table, table.setmetatable(mt) ); + assertEquals( userdata, userdata.setmetatable(mt) ); + LuaBoolean.s_metatable = mt; + LuaFunction.s_metatable = mt; + LuaNil.s_metatable = mt; + LuaNumber.s_metatable = mt; +// LuaString.s_metatable = mt; + LuaThread.s_metatable = mt; + + // plain metatable + final LuaValue fallback = LuaValue.tableOf(); + LuaValue abc = LuaValue.valueOf("abc"); + mt.set( LuaValue.NEWINDEX, fallback ); + table.set(2,abc); + userdata.set(3,abc); + LuaValue.NIL.set(4,abc); + LuaValue.TRUE.set(5,abc); + LuaValue.ONE.set(6,abc); +// string.set(7,abc); + function.set(8,abc); + thread.set(9,abc); + assertEquals( abc, fallback.get(2) ); + assertEquals( abc, fallback.get(3) ); + assertEquals( abc, fallback.get(4) ); + assertEquals( abc, fallback.get(5) ); + assertEquals( abc, fallback.get(6) ); +// assertEquals( abc, StringLib.instance.get(7) ); + assertEquals( abc, fallback.get(8) ); + assertEquals( abc, fallback.get(9) ); + + // metatable with function call + mt.set( LuaValue.NEWINDEX, new ThreeArgFunction() { + public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { + fallback.rawset(arg2, LuaValue.valueOf( "via-func-"+arg3 )); + return NONE; + } + + }); + table.set(12,abc); + userdata.set(13,abc); + LuaValue.NIL.set(14,abc); + LuaValue.TRUE.set(15,abc); + LuaValue.ONE.set(16,abc); +// string.set(17,abc); + function.set(18,abc); + thread.set(19,abc); + LuaValue via = LuaValue.valueOf( "via-func-abc" ); + assertEquals( via, fallback.get(12) ); + assertEquals( via, fallback.get(13) ); + assertEquals( via, fallback.get(14) ); + assertEquals( via, fallback.get(15) ); + assertEquals( via, fallback.get(16) ); +// assertEquals( via, StringLib.instance.get(17) ); + assertEquals( via, fallback.get(18) ); + assertEquals( via, fallback.get(19) ); + } + + + private void checkTable( LuaValue t, + LuaValue aa, LuaValue bb, LuaValue cc, LuaValue dd, LuaValue ee, LuaValue ff, LuaValue gg, + LuaValue ra, LuaValue rb, LuaValue rc, LuaValue rd, LuaValue re, LuaValue rf, LuaValue rg ) { + assertEquals( aa, t.get("aa") ); + assertEquals( bb, t.get("bb") ); + assertEquals( cc, t.get("cc") ); + assertEquals( dd, t.get("dd") ); + assertEquals( ee, t.get("ee") ); + assertEquals( ff, t.get("ff") ); + assertEquals( gg, t.get("gg") ); + assertEquals( ra, t.rawget("aa") ); + assertEquals( rb, t.rawget("bb") ); + assertEquals( rc, t.rawget("cc") ); + assertEquals( rd, t.rawget("dd") ); + assertEquals( re, t.rawget("ee") ); + assertEquals( rf, t.rawget("ff") ); + assertEquals( rg, t.rawget("gg") ); + } + + private LuaValue makeTable( String key1, String val1, String key2, String val2 ) { + return LuaValue.tableOf( new LuaValue[] { + LuaValue.valueOf(key1), LuaValue.valueOf(val1), + LuaValue.valueOf(key2), LuaValue.valueOf(val2), + } ); + } + + public void testRawsetMetatableSet() { + // set up tables + LuaValue m = makeTable( "aa", "aaa", "bb", "bbb" ); + m.set(LuaValue.INDEX, m); + m.set(LuaValue.NEWINDEX, m); + LuaValue s = makeTable( "cc", "ccc", "dd", "ddd" ); + LuaValue t = makeTable( "cc", "ccc", "dd", "ddd" ); + t.setmetatable(m); + LuaValue aaa = LuaValue.valueOf("aaa"); + LuaValue bbb = LuaValue.valueOf("bbb"); + LuaValue ccc = LuaValue.valueOf("ccc"); + LuaValue ddd = LuaValue.valueOf("ddd"); + LuaValue ppp = LuaValue.valueOf("ppp"); + LuaValue qqq = LuaValue.valueOf("qqq"); + LuaValue rrr = LuaValue.valueOf("rrr"); + LuaValue sss = LuaValue.valueOf("sss"); + LuaValue ttt = LuaValue.valueOf("ttt"); + LuaValue www = LuaValue.valueOf("www"); + LuaValue xxx = LuaValue.valueOf("xxx"); + LuaValue yyy = LuaValue.valueOf("yyy"); + LuaValue zzz = LuaValue.valueOf("zzz"); + LuaValue nil = LuaValue.NIL; + + // check initial values + // values via "bet()" values via "rawget()" + checkTable( s, nil,nil,ccc,ddd,nil,nil,nil, nil,nil,ccc,ddd,nil,nil,nil ); + checkTable( t, aaa,bbb,ccc,ddd,nil,nil,nil, nil,nil,ccc,ddd,nil,nil,nil ); + checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil ); + + // rawset() + s.rawset("aa", www); + checkTable( s, www,nil,ccc,ddd,nil,nil,nil, www,nil,ccc,ddd,nil,nil,nil ); + checkTable( t, aaa,bbb,ccc,ddd,nil,nil,nil, nil,nil,ccc,ddd,nil,nil,nil ); + checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil ); + s.rawset("cc", xxx); + checkTable( s, www,nil,xxx,ddd,nil,nil,nil, www,nil,xxx,ddd,nil,nil,nil ); + checkTable( t, aaa,bbb,ccc,ddd,nil,nil,nil, nil,nil,ccc,ddd,nil,nil,nil ); + checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil ); + t.rawset("bb", yyy); + checkTable( s, www,nil,xxx,ddd,nil,nil,nil, www,nil,xxx,ddd,nil,nil,nil ); + checkTable( t, aaa,yyy,ccc,ddd,nil,nil,nil, nil,yyy,ccc,ddd,nil,nil,nil ); + checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil ); + t.rawset("dd", zzz); + checkTable( s, www,nil,xxx,ddd,nil,nil,nil, www,nil,xxx,ddd,nil,nil,nil ); + checkTable( t, aaa,yyy,ccc,zzz,nil,nil,nil, nil,yyy,ccc,zzz,nil,nil,nil ); + checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil ); + + // set() invoking metatables + s.set("ee", ppp); + checkTable( s, www,nil,xxx,ddd,ppp,nil,nil, www,nil,xxx,ddd,ppp,nil,nil ); + checkTable( t, aaa,yyy,ccc,zzz,nil,nil,nil, nil,yyy,ccc,zzz,nil,nil,nil ); + checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil ); + s.set("cc", qqq); + checkTable( s, www,nil,qqq,ddd,ppp,nil,nil, www,nil,qqq,ddd,ppp,nil,nil ); + checkTable( t, aaa,yyy,ccc,zzz,nil,nil,nil, nil,yyy,ccc,zzz,nil,nil,nil ); + checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil ); + t.set("ff", rrr); + checkTable( s, www,nil,qqq,ddd,ppp,nil,nil, www,nil,qqq,ddd,ppp,nil,nil ); + checkTable( t, aaa,yyy,ccc,zzz,nil,rrr,nil, nil,yyy,ccc,zzz,nil,nil,nil ); + checkTable( m, aaa,bbb,nil,nil,nil,rrr,nil, aaa,bbb,nil,nil,nil,rrr,nil ); + t.set("dd", sss); + checkTable( s, www,nil,qqq,ddd,ppp,nil,nil, www,nil,qqq,ddd,ppp,nil,nil ); + checkTable( t, aaa,yyy,ccc,sss,nil,rrr,nil, nil,yyy,ccc,sss,nil,nil,nil ); + checkTable( m, aaa,bbb,nil,nil,nil,rrr,nil, aaa,bbb,nil,nil,nil,rrr,nil ); + m.set("gg", ttt); + checkTable( s, www,nil,qqq,ddd,ppp,nil,nil, www,nil,qqq,ddd,ppp,nil,nil ); + checkTable( t, aaa,yyy,ccc,sss,nil,rrr,ttt, nil,yyy,ccc,sss,nil,nil,nil ); + checkTable( m, aaa,bbb,nil,nil,nil,rrr,ttt, aaa,bbb,nil,nil,nil,rrr,ttt ); + + // make s fall back to t + s.setmetatable(LuaValue.tableOf(new LuaValue[] {LuaValue.INDEX,t,LuaValue.NEWINDEX,t})); + checkTable( s, www,yyy,qqq,ddd,ppp,rrr,ttt, www,nil,qqq,ddd,ppp,nil,nil ); + checkTable( t, aaa,yyy,ccc,sss,nil,rrr,ttt, nil,yyy,ccc,sss,nil,nil,nil ); + checkTable( m, aaa,bbb,nil,nil,nil,rrr,ttt, aaa,bbb,nil,nil,nil,rrr,ttt ); + s.set("aa", www); + checkTable( s, www,yyy,qqq,ddd,ppp,rrr,ttt, www,nil,qqq,ddd,ppp,nil,nil ); + checkTable( t, aaa,yyy,ccc,sss,nil,rrr,ttt, nil,yyy,ccc,sss,nil,nil,nil ); + checkTable( m, aaa,bbb,nil,nil,nil,rrr,ttt, aaa,bbb,nil,nil,nil,rrr,ttt ); + s.set("bb", zzz); + checkTable( s, www,zzz,qqq,ddd,ppp,rrr,ttt, www,nil,qqq,ddd,ppp,nil,nil ); + checkTable( t, aaa,zzz,ccc,sss,nil,rrr,ttt, nil,zzz,ccc,sss,nil,nil,nil ); + checkTable( m, aaa,bbb,nil,nil,nil,rrr,ttt, aaa,bbb,nil,nil,nil,rrr,ttt ); + s.set("ee", xxx); + checkTable( s, www,zzz,qqq,ddd,xxx,rrr,ttt, www,nil,qqq,ddd,xxx,nil,nil ); + checkTable( t, aaa,zzz,ccc,sss,nil,rrr,ttt, nil,zzz,ccc,sss,nil,nil,nil ); + checkTable( m, aaa,bbb,nil,nil,nil,rrr,ttt, aaa,bbb,nil,nil,nil,rrr,ttt ); + s.set("ff", yyy); + checkTable( s, www,zzz,qqq,ddd,xxx,yyy,ttt, www,nil,qqq,ddd,xxx,nil,nil ); + checkTable( t, aaa,zzz,ccc,sss,nil,yyy,ttt, nil,zzz,ccc,sss,nil,nil,nil ); + checkTable( m, aaa,bbb,nil,nil,nil,yyy,ttt, aaa,bbb,nil,nil,nil,yyy,ttt ); + + + } + +} diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/OrphanedThreadTest.java b/luaj-2.0.3/test/junit/org/luaj/vm2/OrphanedThreadTest.java new file mode 100644 index 0000000000..2c801abb88 --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/OrphanedThreadTest.java @@ -0,0 +1,184 @@ +/******************************************************************************* + * Copyright (c) 2012 Luaj.org. 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. + ******************************************************************************/ +package org.luaj.vm2; + +import java.io.ByteArrayInputStream; +import java.lang.ref.WeakReference; + +import junit.framework.TestCase; + +import org.luaj.vm2.LoadState; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; +import org.luaj.vm2.compiler.LuaC; +import org.luaj.vm2.lib.OneArgFunction; +import org.luaj.vm2.lib.jse.JsePlatform; + + +public class OrphanedThreadTest extends TestCase { + + LuaThread luathread; + WeakReference luathr_ref; + LuaValue function; + WeakReference func_ref; + LuaValue env; + + protected void setUp() throws Exception { + LuaThread.thread_orphan_check_interval = 5; + env = JsePlatform.standardGlobals(); + } + + protected void tearDown() { + LuaThread.thread_orphan_check_interval = 30000; + } + + public void testCollectOrphanedNormalThread() throws Exception { + function = new NormalFunction(); + doTest(LuaValue.TRUE, LuaValue.ZERO); + } + + public void testCollectOrphanedEarlyCompletionThread() throws Exception { + function = new EarlyCompletionFunction(); + doTest(LuaValue.TRUE, LuaValue.ZERO); + } + + public void testCollectOrphanedAbnormalThread() throws Exception { + function = new AbnormalFunction(); + doTest(LuaValue.FALSE, LuaValue.valueOf("abnormal condition")); + } + + public void testCollectOrphanedClosureThread() throws Exception { + String script = + "print('in closure, arg is '..(...))\n" + + "arg = coroutine.yield(1)\n" + + "print('in closure.2, arg is '..arg)\n" + + "arg = coroutine.yield(0)\n" + + "print('leakage in closure.3, arg is '..arg)\n" + + "return 'done'\n"; + LuaC.install(); + function = LoadState.load(new ByteArrayInputStream(script.getBytes()), "script", env); + doTest(LuaValue.TRUE, LuaValue.ZERO); + } + + public void testCollectOrphanedPcallClosureThread() throws Exception { + String script = + "f = function(x)\n" + + " print('in pcall-closure, arg is '..(x))\n" + + " arg = coroutine.yield(1)\n" + + " print('in pcall-closure.2, arg is '..arg)\n" + + " arg = coroutine.yield(0)\n" + + " print('leakage in pcall-closure.3, arg is '..arg)\n" + + " return 'done'\n" + + "end\n" + + "print( 'pcall-closre.result:', pcall( f, ... ) )\n"; + LuaC.install(); + function = LoadState.load(new ByteArrayInputStream(script.getBytes()), "script", env); + doTest(LuaValue.TRUE, LuaValue.ZERO); + } + + public void testCollectOrphanedLoadCloasureThread() throws Exception { + String script = + "t = { \"print \", \"'hello, \", \"world'\", }\n" + + "i = 0\n" + + "arg = ...\n" + + "f = function()\n" + + " i = i + 1\n" + + " print('in load-closure, arg is', arg, 'next is', t[i])\n" + + " arg = coroutine.yield(1)\n" + + " return t[i]\n" + + "end\n" + + "load(f)()\n"; + LuaC.install(); + function = LoadState.load(new ByteArrayInputStream(script.getBytes()), "script", env); + doTest(LuaValue.TRUE, LuaValue.ONE); + } + + private void doTest(LuaValue status2, LuaValue value2) throws Exception { + luathread = new LuaThread(function, env); + luathr_ref = new WeakReference(luathread); + func_ref = new WeakReference(function); + assertNotNull(luathr_ref.get()); + + // resume two times + Varargs a = luathread.resume(LuaValue.valueOf("foo")); + assertEquals(LuaValue.ONE, a.arg(2)); + assertEquals(LuaValue.TRUE, a.arg1()); + a = luathread.resume(LuaValue.valueOf("bar")); + assertEquals(value2, a.arg(2)); + assertEquals(status2, a.arg1()); + + // drop strong references + luathread = null; + function = null; + + // gc + for (int i=0; i<100 && (luathr_ref.get() != null || func_ref.get() != null); i++) { + Runtime.getRuntime().gc(); + Thread.sleep(5); + } + + // check reference + assertNull(luathr_ref.get()); + assertNull(func_ref.get()); + } + + + static class NormalFunction extends OneArgFunction { + public LuaValue call(LuaValue arg) { + System.out.println("in normal.1, arg is "+arg); + arg = LuaThread.yield(ONE).arg1(); + System.out.println("in normal.2, arg is "+arg); + arg = LuaThread.yield(ZERO).arg1(); + System.out.println("in normal.3, arg is "+arg); + return NONE; + } + } + + static class EarlyCompletionFunction extends OneArgFunction { + public LuaValue call(LuaValue arg) { + System.out.println("in early.1, arg is "+arg); + arg = LuaThread.yield(ONE).arg1(); + System.out.println("in early.2, arg is "+arg); + return ZERO; + } + } + + static class AbnormalFunction extends OneArgFunction { + public LuaValue call(LuaValue arg) { + System.out.println("in abnormal.1, arg is "+arg); + arg = LuaThread.yield(ONE).arg1(); + System.out.println("in abnormal.2, arg is "+arg); + error("abnormal condition"); + return ZERO; + } + } + + static class ClosureFunction extends OneArgFunction { + public LuaValue call(LuaValue arg) { + System.out.println("in abnormal.1, arg is "+arg); + arg = LuaThread.yield(ONE).arg1(); + System.out.println("in abnormal.2, arg is "+arg); + error("abnormal condition"); + return ZERO; + } + } +} diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/RequireClassTest.java b/luaj-2.0.3/test/junit/org/luaj/vm2/RequireClassTest.java new file mode 100644 index 0000000000..3f07435460 --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/RequireClassTest.java @@ -0,0 +1,84 @@ +package org.luaj.vm2; + +import junit.framework.TestCase; + +import org.luaj.vm2.lib.jse.JsePlatform; +import org.luaj.vm2.require.RequireSampleClassCastExcep; +import org.luaj.vm2.require.RequireSampleLoadLuaError; +import org.luaj.vm2.require.RequireSampleLoadRuntimeExcep; + +public class RequireClassTest extends TestCase { + + private LuaTable globals; + private LuaValue require; + + public void setUp() { + globals = JsePlatform.standardGlobals(); + require = globals.get("require"); + } + + public void testRequireClassSuccess() { + LuaValue result = require.call( LuaValue.valueOf("org.luaj.vm2.require.RequireSampleSuccess") ); + assertEquals( "require-sample-success", result.tojstring() ); + result = require.call( LuaValue.valueOf("org.luaj.vm2.require.RequireSampleSuccess") ); + assertEquals( "require-sample-success", result.tojstring() ); + } + + public void testRequireClassLoadLuaError() { + try { + LuaValue result = require.call( LuaValue.valueOf(RequireSampleLoadLuaError.class.getName()) ); + fail( "incorrectly loaded class that threw lua error"); + } catch ( LuaError le ) { + assertEquals( + "sample-load-lua-error", + le.getMessage() ); + } + try { + LuaValue result = require.call( LuaValue.valueOf(RequireSampleLoadLuaError.class.getName()) ); + fail( "incorrectly loaded class that threw lua error"); + } catch ( LuaError le ) { + assertEquals( + "loop or previous error loading module '"+RequireSampleLoadLuaError.class.getName()+"'", + le.getMessage() ); + } + } + + public void testRequireClassLoadRuntimeException() { + try { + LuaValue result = require.call( LuaValue.valueOf(RequireSampleLoadRuntimeExcep.class.getName()) ); + fail( "incorrectly loaded class that threw runtime exception"); + } catch ( RuntimeException le ) { + assertEquals( + "sample-load-runtime-exception", + le.getMessage() ); + } + try { + LuaValue result = require.call( LuaValue.valueOf(RequireSampleLoadRuntimeExcep.class.getName()) ); + fail( "incorrectly loaded class that threw runtime exception"); + } catch ( LuaError le ) { + assertEquals( + "loop or previous error loading module '"+RequireSampleLoadRuntimeExcep.class.getName()+"'", + le.getMessage() ); + } + } + + + public void testRequireClassClassCastException() { + try { + LuaValue result = require.call( LuaValue.valueOf(RequireSampleClassCastExcep.class.getName()) ); + fail( "incorrectly loaded class that threw class cast exception"); + } catch ( LuaError le ) { + String msg = le.getMessage(); + if ( msg.indexOf("not found") < 0 ) + fail( "expected 'not found' message but got "+msg ); + } + try { + LuaValue result = require.call( LuaValue.valueOf(RequireSampleClassCastExcep.class.getName()) ); + fail( "incorrectly loaded class that threw class cast exception"); + } catch ( LuaError le ) { + String msg = le.getMessage(); + if ( msg.indexOf("not found") < 0 ) + fail( "expected 'not found' message but got "+msg ); + } + } +} diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/ScriptDrivenTest.java b/luaj-2.0.3/test/junit/org/luaj/vm2/ScriptDrivenTest.java new file mode 100644 index 0000000000..c50f79cb44 --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/ScriptDrivenTest.java @@ -0,0 +1,258 @@ +/******************************************************************************* + * Copyright (c) 2009-2013 Luaj.org. 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. + ******************************************************************************/ +package org.luaj.vm2; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.net.MalformedURLException; +import java.net.URL; + +import junit.framework.TestCase; + +import org.luaj.vm2.lib.BaseLib; +import org.luaj.vm2.lib.ResourceFinder; +import org.luaj.vm2.lib.jse.JseProcess; +import org.luaj.vm2.luajc.LuaJC; + +abstract +public class ScriptDrivenTest extends TestCase implements ResourceFinder { + public static final boolean nocompile = "true".equals(System.getProperty("nocompile")); + + public enum PlatformType { + JME, JSE, LUAJIT, LUA2JAVA, + } + + private final PlatformType platform; + private final String subdir; + protected LuaTable globals; + + static final String zipdir = "test/lua/"; + static final String zipfile = "luaj2.0-tests.zip"; + + protected ScriptDrivenTest( PlatformType platform, String subdir ) { + this.platform = platform; + this.subdir = subdir; + initGlobals(); + } + + private void initGlobals() { + switch ( platform ) { + default: + case JSE: + case LUAJIT: + case LUA2JAVA: + globals = org.luaj.vm2.lib.jse.JsePlatform.debugGlobals(); + break; + case JME: + globals = org.luaj.vm2.lib.jme.JmePlatform.debugGlobals(); + break; + } + } + + + protected void setUp() throws Exception { + super.setUp(); + initGlobals(); + BaseLib.FINDER = this; + } + + // ResourceFinder implementation. + public InputStream findResource(String filename) { + InputStream is = findInPlainFile(filename); + if (is != null) return is; + is = findInPlainFileAsResource("",filename); + if (is != null) return is; + is = findInPlainFileAsResource("/",filename); + if (is != null) return is; + is = findInZipFileAsPlainFile(filename); + if (is != null) return is; + is = findInZipFileAsResource("",filename); + if (is != null) return is; + is = findInZipFileAsResource("/",filename); + return is; + } + + private InputStream findInPlainFileAsResource(String prefix, String filename) { + return getClass().getResourceAsStream(prefix + subdir + filename); + } + + private InputStream findInPlainFile(String filename) { + try { + File f = new File(zipdir+subdir+filename); + if (f.exists()) + return new FileInputStream(f); + } catch ( IOException ioe ) { + ioe.printStackTrace(); + } + return null; + } + + private InputStream findInZipFileAsPlainFile(String filename) { + URL zip; + File file = new File(zipdir+zipfile); + try { + if ( file.exists() ) { + zip = file.toURI().toURL(); + String path = "jar:"+zip.toExternalForm()+ "!/"+subdir+filename; + URL url = new URL(path); + return url.openStream(); + } + } catch (MalformedURLException e) { + e.printStackTrace(); + } catch (FileNotFoundException e) { + // Ignore and return null. + } catch (IOException ioe) { + ioe.printStackTrace(); + } + return null; + } + + + private InputStream findInZipFileAsResource(String prefix, String filename) { + URL zip = null; + zip = getClass().getResource(zipfile); + if ( zip != null ) + try { + String path = "jar:"+zip.toExternalForm()+ "!/"+subdir+filename; + URL url = new URL(path); + return url.openStream(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + return null; + } + + // */ + protected void runTest(String testName) { + try { + // override print() + final ByteArrayOutputStream output = new ByteArrayOutputStream(); + final PrintStream oldps = BaseLib.instance.STDOUT; + final PrintStream ps = new PrintStream( output ); + BaseLib.instance.STDOUT = ps; + + // run the script + try { + LuaValue chunk = loadScript(testName, globals); + chunk.call(LuaValue.valueOf(platform.toString())); + + ps.flush(); + String actualOutput = new String(output.toByteArray()); + String expectedOutput = getExpectedOutput(testName); + actualOutput = actualOutput.replaceAll("\r\n", "\n"); + expectedOutput = expectedOutput.replaceAll("\r\n", "\n"); + + assertEquals(expectedOutput, actualOutput); + } finally { + BaseLib.instance.STDOUT = oldps; + ps.close(); + } + } catch ( IOException ioe ) { + throw new RuntimeException(ioe.toString()); + } catch ( InterruptedException ie ) { + throw new RuntimeException(ie.toString()); + } + } + + protected LuaValue loadScript(String name, LuaTable _G) throws IOException { + InputStream script = this.findResource(name+".lua"); + if ( script == null ) + fail("Could not load script for test case: " + name); + try { + switch ( this.platform ) { + case LUAJIT: + if ( nocompile ) { + LuaValue c = (LuaValue) Class.forName(name).newInstance(); + return c; + } else { + return LuaJC.getInstance().load( script, name, _G); + } + default: + return LoadState.load(script, "@"+name+".lua", _G); + } + } catch ( Exception e ) { + e.printStackTrace(); + throw new IOException( e.toString() ); + } finally { + script.close(); + } + } + + private String getExpectedOutput(final String name) throws IOException, + InterruptedException { + InputStream output = this.findResource(name+".out"); + if (output != null) + try { + return readString(output); + } finally { + output.close(); + } + String expectedOutput = executeLuaProcess(name); + if (expectedOutput == null) + throw new IOException("Failed to get comparison output or run process for "+name); + return expectedOutput; + } + + private String executeLuaProcess(String name) throws IOException, InterruptedException { + InputStream script = findResource(name+".lua"); + if ( script == null ) + throw new IOException("Failed to find source file "+script); + try { + String luaCommand = System.getProperty("LUA_COMMAND"); + if ( luaCommand == null ) + luaCommand = "lua"; + String[] args = new String[] { luaCommand, "-", platform.toString() }; + return collectProcessOutput(args, script); + } finally { + script.close(); + } + } + + public static String collectProcessOutput(String[] cmd, final InputStream input) + throws IOException, InterruptedException { + Runtime r = Runtime.getRuntime(); + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new JseProcess(cmd, input, baos, System.err).waitFor(); + return new String(baos.toByteArray()); + } + + private String readString(InputStream is) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + copy(is, baos); + return new String(baos.toByteArray()); + } + + private static void copy(InputStream is, OutputStream os) throws IOException { + byte[] buf = new byte[1024]; + int r; + while ((r = is.read(buf)) >= 0) { + os.write(buf, 0, r); + } + } + +} diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/StringTest.java b/luaj-2.0.3/test/junit/org/luaj/vm2/StringTest.java new file mode 100644 index 0000000000..b2b2f61285 --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/StringTest.java @@ -0,0 +1,117 @@ +package org.luaj.vm2; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; + +import junit.framework.TestCase; + +import org.luaj.vm2.lib.jse.JsePlatform; + +public class StringTest extends TestCase { + + protected void setUp() throws Exception { + JsePlatform.standardGlobals(); + } + + public void testToInputStream() throws IOException { + LuaString str = LuaString.valueOf("Hello"); + + InputStream is = str.toInputStream(); + + assertEquals( 'H', is.read() ); + assertEquals( 'e', is.read() ); + assertEquals( 2, is.skip( 2 ) ); + assertEquals( 'o', is.read() ); + assertEquals( -1, is.read() ); + + assertTrue( is.markSupported() ); + + is.reset(); + + assertEquals( 'H', is.read() ); + is.mark( 4 ); + + assertEquals( 'e', is.read() ); + is.reset(); + assertEquals( 'e', is.read() ); + + LuaString substr = str.substring( 1, 4 ); + assertEquals( 3, substr.length() ); + + is.close(); + is = substr.toInputStream(); + + assertEquals( 'e', is.read() ); + assertEquals( 'l', is.read() ); + assertEquals( 'l', is.read() ); + assertEquals( -1, is.read() ); + + is = substr.toInputStream(); + is.reset(); + + assertEquals( 'e', is.read() ); + } + + + private static final String userFriendly( String s ) { + StringBuffer sb = new StringBuffer(); + for ( int i=0, n=s.length(); i= 0x80 ) { + sb.append( "\\u"+Integer.toHexString(0x10000+c).substring(1) ); + } else { + sb.append( (char) c ); + } + } + return sb.toString(); + } + + public void testUtf820482051() throws UnsupportedEncodingException { + int i = 2048; + char[] c = { (char) (i+0), (char) (i+1), (char) (i+2), (char) (i+3) }; + String before = new String(c)+" "+i+"-"+(i+4); + LuaString ls = LuaString.valueOf(before); + String after = ls.tojstring(); + assertEquals( userFriendly( before ), userFriendly( after ) ); + + } + + public void testUtf8() { + for ( int i=4; i<0xffff; i+=4 ) { + char[] c = { (char) (i+0), (char) (i+1), (char) (i+2), (char) (i+3) }; + String before = new String(c)+" "+i+"-"+(i+4); + LuaString ls = LuaString.valueOf(before); + String after = ls.tojstring(); + assertEquals( userFriendly( before ), userFriendly( after ) ); + } + char[] c = { (char) (1), (char) (2), (char) (3) }; + String before = new String(c)+" 1-3"; + LuaString ls = LuaString.valueOf(before); + String after = ls.tojstring(); + assertEquals( userFriendly( before ), userFriendly( after ) ); + + } + + public void testSpotCheckUtf8() throws UnsupportedEncodingException { + byte[] bytes = {(byte)194,(byte)160,(byte)194,(byte)161,(byte)194,(byte)162,(byte)194,(byte)163,(byte)194,(byte)164}; + String expected = new String(bytes, "UTF8"); + String actual = LuaString.valueOf(bytes).tojstring(); + char[] d = actual.toCharArray(); + assertEquals(160, d[0]); + assertEquals(161, d[1]); + assertEquals(162, d[2]); + assertEquals(163, d[3]); + assertEquals(164, d[4]); + + } + + public void testNullTerminated() { + char[] c = { 'a', 'b', 'c', '\0', 'd', 'e', 'f' }; + String before = new String(c); + LuaString ls = LuaString.valueOf(before); + String after = ls.tojstring(); + assertEquals( userFriendly( "abc\0def" ), userFriendly( after ) ); + + } +} diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/TableArrayTest.java b/luaj-2.0.3/test/junit/org/luaj/vm2/TableArrayTest.java new file mode 100644 index 0000000000..3ce96ea4ee --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/TableArrayTest.java @@ -0,0 +1,355 @@ +/******************************************************************************* + * Copyright (c) 2009 Luaj.org. 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. + ******************************************************************************/ +package org.luaj.vm2; + +import java.util.Vector; + +import org.luaj.vm2.LuaDouble; +import org.luaj.vm2.LuaInteger; +import org.luaj.vm2.LuaString; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; + +import junit.framework.TestCase; + +/** + * Tests for tables used as lists. + */ +public class TableArrayTest extends TestCase { + + protected LuaTable new_Table() { + return new LuaTable(); + } + + protected LuaTable new_Table(int n,int m) { + return new LuaTable(n,m); + } + + public void testInOrderIntegerKeyInsertion() { + LuaTable t = new_Table(); + + for ( int i = 1; i <= 32; ++i ) { + t.set( i, LuaString.valueOf( "Test Value! "+i ) ); + } + + // Ensure all keys are still there. + for ( int i = 1; i <= 32; ++i ) { + assertEquals( "Test Value! " + i, t.get( i ).tojstring() ); + } + + // Ensure capacities make sense + assertEquals( 0, t.getHashLength() ); + + assertTrue( t.getArrayLength() >= 32 ); + assertTrue( t.getArrayLength() <= 64 ); + + } + + public void testResize() { + LuaTable t = new_Table(); + + // NOTE: This order of insertion is important. + t.set(3, LuaInteger.valueOf(3)); + t.set(1, LuaInteger.valueOf(1)); + t.set(5, LuaInteger.valueOf(5)); + t.set(4, LuaInteger.valueOf(4)); + t.set(6, LuaInteger.valueOf(6)); + t.set(2, LuaInteger.valueOf(2)); + + for ( int i = 1; i < 6; ++i ) { + assertEquals(LuaInteger.valueOf(i), t.get(i)); + } + + assertTrue( t.getArrayLength() >= 0 && t.getArrayLength() <= 2 ); + assertTrue( t.getHashLength() >= 4 ); + } + + public void testOutOfOrderIntegerKeyInsertion() { + LuaTable t = new_Table(); + + for ( int i = 32; i > 0; --i ) { + t.set( i, LuaString.valueOf( "Test Value! "+i ) ); + } + + // Ensure all keys are still there. + for ( int i = 1; i <= 32; ++i ) { + assertEquals( "Test Value! "+i, t.get( i ).tojstring() ); + } + + // Ensure capacities make sense + assertTrue( t.getArrayLength() >= 0 ); + assertTrue( t.getArrayLength() <= 6 ); + + assertTrue( t.getHashLength() >= 16 ); + assertTrue( t.getHashLength() <= 64 ); + + } + + public void testStringAndIntegerKeys() { + LuaTable t = new_Table(); + + for ( int i = 0; i < 10; ++i ) { + LuaString str = LuaString.valueOf( String.valueOf( i ) ); + t.set( i, str ); + t.set( str, LuaInteger.valueOf( i ) ); + } + + assertTrue( t.getArrayLength() >= 9 ); // 1, 2, ..., 9 + assertTrue( t.getArrayLength() <= 18 ); + assertTrue( t.getHashLength() >= 11 ); // 0, "0", "1", ..., "9" + assertTrue( t.getHashLength() <= 33 ); + + LuaValue[] keys = t.keys(); + + int intKeys = 0; + int stringKeys = 0; + + assertEquals( 20, keys.length ); + for ( int i = 0; i < keys.length; ++i ) { + LuaValue k = keys[i]; + + if ( k instanceof LuaInteger ) { + final int ik = k.toint(); + assertTrue( ik >= 0 && ik < 10 ); + final int mask = 1 << ik; + assertTrue( ( intKeys & mask ) == 0 ); + intKeys |= mask; + } else if ( k instanceof LuaString ) { + final int ik = Integer.parseInt( k.tojstring() ); + assertEquals( String.valueOf( ik ), k.tojstring() ); + assertTrue( ik >= 0 && ik < 10 ); + final int mask = 1 << ik; + assertTrue( "Key \""+ik+"\" found more than once", ( stringKeys & mask ) == 0 ); + stringKeys |= mask; + } else { + fail( "Unexpected type of key found" ); + } + } + + assertEquals( 0x03FF, intKeys ); + assertEquals( 0x03FF, stringKeys ); + } + + public void testBadInitialCapacity() { + LuaTable t = new_Table(0, 1); + + t.set( "test", LuaString.valueOf("foo") ); + t.set( "explode", LuaString.valueOf("explode") ); + assertEquals( 2, t.keyCount() ); + } + + public void testRemove0() { + LuaTable t = new_Table(2, 0); + + t.set( 1, LuaString.valueOf("foo") ); + t.set( 2, LuaString.valueOf("bah") ); + assertNotSame(LuaValue.NIL, t.get(1)); + assertNotSame(LuaValue.NIL, t.get(2)); + assertEquals(LuaValue.NIL, t.get(3)); + + t.set( 1, LuaValue.NIL ); + t.set( 2, LuaValue.NIL ); + t.set( 3, LuaValue.NIL ); + assertEquals(LuaValue.NIL, t.get(1)); + assertEquals(LuaValue.NIL, t.get(2)); + assertEquals(LuaValue.NIL, t.get(3)); + } + + public void testRemove1() { + LuaTable t = new_Table(0, 1); + assertEquals( 0, t.keyCount() ); + + t.set( "test", LuaString.valueOf("foo") ); + assertEquals( 1, t.keyCount() ); + t.set( "explode", LuaValue.NIL ); + assertEquals( 1, t.keyCount() ); + t.set( 42, LuaValue.NIL ); + assertEquals( 1, t.keyCount() ); + t.set( new_Table(), LuaValue.NIL ); + assertEquals( 1, t.keyCount() ); + t.set( "test", LuaValue.NIL ); + assertEquals( 0, t.keyCount() ); + + t.set( 10, LuaInteger.valueOf( 5 ) ); + t.set( 10, LuaValue.NIL ); + assertEquals( 0, t.keyCount() ); + } + + public void testRemove2() { + LuaTable t = new_Table(0, 1); + + t.set( "test", LuaString.valueOf("foo") ); + t.set( "string", LuaInteger.valueOf( 10 ) ); + assertEquals( 2, t.keyCount() ); + + t.set( "string", LuaValue.NIL ); + t.set( "three", LuaDouble.valueOf( 3.14 ) ); + assertEquals( 2, t.keyCount() ); + + t.set( "test", LuaValue.NIL ); + assertEquals( 1, t.keyCount() ); + + t.set( 10, LuaInteger.valueOf( 5 ) ); + assertEquals( 2, t.keyCount() ); + + t.set( 10, LuaValue.NIL ); + assertEquals( 1, t.keyCount() ); + + t.set( "three", LuaValue.NIL ); + assertEquals( 0, t.keyCount() ); + } + + public void testInOrderlen() { + LuaTable t = new_Table(); + + for ( int i = 1; i <= 32; ++i ) { + LuaValue v = LuaString.valueOf( "Test Value! "+i ); + t.set( i, v ); + assertEquals( i, t.length() ); + assertEquals( i, t.maxn() ); + } + } + + public void testOutOfOrderlen() { + LuaTable t = new_Table(); + + for ( int j=8; j<32; j+=8 ) { + for ( int i = j; i > 0; --i ) { + t.set( i, LuaString.valueOf( "Test Value! "+i ) ); + } + assertEquals( j, t.length() ); + assertEquals( j, t.maxn() ); + } + } + + public void testStringKeyslen() { + LuaTable t = new_Table(); + + for ( int i = 1; i <= 32; ++i ) { + t.set( "str-"+i, LuaString.valueOf( "String Key Test Value! "+i ) ); + assertEquals( 0, t.length() ); + assertEquals( 0, t.maxn() ); + } + } + + public void testMixedKeyslen() { + LuaTable t = new_Table(); + + for ( int i = 1; i <= 32; ++i ) { + t.set( "str-"+i, LuaString.valueOf( "String Key Test Value! "+i ) ); + t.set( i, LuaString.valueOf( "Int Key Test Value! "+i ) ); + assertEquals( i, t.length() ); + assertEquals( i, t.maxn() ); + } + } + + private static final void compareLists(LuaTable t,Vector v) { + int n = v.size(); + assertEquals(v.size(),t.length()); + for ( int j=0; j l = new ArrayList(); + LuaValue k = LuaValue.NIL; + while ( true ) { + Varargs n = t.next(k); + if ( (k = n.arg1()).isnil() ) + break; + l.add( k ); + } + return l.toArray(new LuaValue[t.length()]); + } + + + public void testInOrderIntegerKeyInsertion() { + LuaTable t = new_Table(); + + for ( int i = 1; i <= 32; ++i ) { + t.set( i, LuaValue.valueOf( "Test Value! "+i ) ); + } + + // Ensure all keys are still there. + for ( int i = 1; i <= 32; ++i ) { + assertEquals( "Test Value! " + i, t.get( i ).tojstring() ); + } + + // Ensure capacities make sense + assertEquals( 0, t.getHashLength() ); + + assertTrue( t.getArrayLength() >= 32 ); + assertTrue( t.getArrayLength() <= 64 ); + + } + + public void testRekeyCount() { + LuaTable t = new_Table(); + + // NOTE: This order of insertion is important. + t.set(3, LuaInteger.valueOf(3)); + t.set(1, LuaInteger.valueOf(1)); + t.set(5, LuaInteger.valueOf(5)); + t.set(4, LuaInteger.valueOf(4)); + t.set(6, LuaInteger.valueOf(6)); + t.set(2, LuaInteger.valueOf(2)); + + for ( int i = 1; i < 6; ++i ) { + assertEquals(LuaInteger.valueOf(i), t.get(i)); + } + + assertTrue( t.getArrayLength() >= 0 && t.getArrayLength() <= 2 ); + assertTrue( t.getHashLength() >= 4 ); + } + + public void testOutOfOrderIntegerKeyInsertion() { + LuaTable t = new_Table(); + + for ( int i = 32; i > 0; --i ) { + t.set( i, LuaValue.valueOf( "Test Value! "+i ) ); + } + + // Ensure all keys are still there. + for ( int i = 1; i <= 32; ++i ) { + assertEquals( "Test Value! "+i, t.get( i ).tojstring() ); + } + + // Ensure capacities make sense + assertTrue( t.getArrayLength() >= 0 ); + assertTrue( t.getArrayLength() <= 6 ); + + assertTrue( t.getHashLength() >= 16 ); + assertTrue( t.getHashLength() <= 64 ); + + } + + public void testStringAndIntegerKeys() { + LuaTable t = new_Table(); + + for ( int i = 0; i < 10; ++i ) { + LuaString str = LuaValue.valueOf( String.valueOf( i ) ); + t.set( i, str ); + t.set( str, LuaInteger.valueOf( i ) ); + } + + assertTrue( t.getArrayLength() >= 9 ); // 1, 2, ..., 9 + assertTrue( t.getArrayLength() <= 18 ); + assertTrue( t.getHashLength() >= 11 ); // 0, "0", "1", ..., "9" + assertTrue( t.getHashLength() <= 33 ); + + LuaValue[] keys = keys(t); + + int intKeys = 0; + int stringKeys = 0; + + assertEquals( 20, keys.length ); + for ( int i = 0; i < keys.length; ++i ) { + LuaValue k = keys[i]; + + if ( k instanceof LuaInteger ) { + final int ik = k.toint(); + assertTrue( ik >= 0 && ik < 10 ); + final int mask = 1 << ik; + assertTrue( ( intKeys & mask ) == 0 ); + intKeys |= mask; + } else if ( k instanceof LuaString ) { + final int ik = Integer.parseInt( k.strvalue().tojstring() ); + assertEquals( String.valueOf( ik ), k.strvalue().tojstring() ); + assertTrue( ik >= 0 && ik < 10 ); + final int mask = 1 << ik; + assertTrue( "Key \""+ik+"\" found more than once", ( stringKeys & mask ) == 0 ); + stringKeys |= mask; + } else { + fail( "Unexpected type of key found" ); + } + } + + assertEquals( 0x03FF, intKeys ); + assertEquals( 0x03FF, stringKeys ); + } + + public void testBadInitialCapacity() { + LuaTable t = new_Table(0, 1); + + t.set( "test", LuaValue.valueOf("foo") ); + t.set( "explode", LuaValue.valueOf("explode") ); + assertEquals( 2, keyCount(t) ); + } + + public void testRemove0() { + LuaTable t = new_Table(2, 0); + + t.set( 1, LuaValue.valueOf("foo") ); + t.set( 2, LuaValue.valueOf("bah") ); + assertNotSame(LuaValue.NIL, t.get(1)); + assertNotSame(LuaValue.NIL, t.get(2)); + assertEquals(LuaValue.NIL, t.get(3)); + + t.set( 1, LuaValue.NIL ); + t.set( 2, LuaValue.NIL ); + t.set( 3, LuaValue.NIL ); + assertEquals(LuaValue.NIL, t.get(1)); + assertEquals(LuaValue.NIL, t.get(2)); + assertEquals(LuaValue.NIL, t.get(3)); + } + + public void testRemove1() { + LuaTable t = new_Table(0, 1); + + t.set( "test", LuaValue.valueOf("foo") ); + t.set( "explode", LuaValue.NIL ); + t.set( 42, LuaValue.NIL ); + t.set( new_Table(), LuaValue.NIL ); + t.set( "test", LuaValue.NIL ); + assertEquals( 0, keyCount(t) ); + + t.set( 10, LuaInteger.valueOf( 5 ) ); + t.set( 10, LuaValue.NIL ); + assertEquals( 0, keyCount(t) ); + } + + public void testRemove2() { + LuaTable t = new_Table(0, 1); + + t.set( "test", LuaValue.valueOf("foo") ); + t.set( "string", LuaInteger.valueOf( 10 ) ); + assertEquals( 2, keyCount(t) ); + + t.set( "string", LuaValue.NIL ); + t.set( "three", LuaValue.valueOf( 3.14 ) ); + assertEquals( 2, keyCount(t) ); + + t.set( "test", LuaValue.NIL ); + assertEquals( 1, keyCount(t) ); + + t.set( 10, LuaInteger.valueOf( 5 ) ); + assertEquals( 2, keyCount(t) ); + + t.set( 10, LuaValue.NIL ); + assertEquals( 1, keyCount(t) ); + + t.set( "three", LuaValue.NIL ); + assertEquals( 0, keyCount(t) ); + } + + public void testInOrderLuaLength() { + LuaTable t = new_Table(); + + for ( int i = 1; i <= 32; ++i ) { + t.set( i, LuaValue.valueOf( "Test Value! "+i ) ); + assertEquals( i, t.length() ); + assertEquals( i, t.maxn() ); + } + } + + public void testOutOfOrderLuaLength() { + LuaTable t = new_Table(); + + for ( int j=8; j<32; j+=8 ) { + for ( int i = j; i > 0; --i ) { + t.set( i, LuaValue.valueOf( "Test Value! "+i ) ); + } + assertEquals( j, t.length() ); + assertEquals( j, t.maxn() ); + } + } + + public void testStringKeysLuaLength() { + LuaTable t = new_Table(); + + for ( int i = 1; i <= 32; ++i ) { + t.set( "str-"+i, LuaValue.valueOf( "String Key Test Value! "+i ) ); + assertEquals( 0, t.length() ); + assertEquals( 0, t.maxn() ); + } + } + + public void testMixedKeysLuaLength() { + LuaTable t = new_Table(); + + for ( int i = 1; i <= 32; ++i ) { + t.set( "str-"+i, LuaValue.valueOf( "String Key Test Value! "+i ) ); + t.set( i, LuaValue.valueOf( "Int Key Test Value! "+i ) ); + assertEquals( i, t.length() ); + assertEquals( i, t.maxn() ); + } + } + + private static final void compareLists(LuaTable t,Vector v) { + int n = v.size(); + assertEquals(v.size(),t.length()); + for ( int j=0; j4., ia.gt(ib).toboolean()); + assertEquals(.25>.5, da.gt(db).toboolean()); + assertEquals(3.>4., ia.gt_b(ib)); + assertEquals(.25>.5, da.gt_b(db)); + + // unlike kinds + assertEquals(3.>.25, ia.gt(da).toboolean()); + assertEquals(.25>3., da.gt(ia).toboolean()); + assertEquals(3.>.25, ia.gt_b(da)); + assertEquals(.25>3., da.gt_b(ia)); + } + + public void testGtEq() { + LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(4); + LuaValue da=LuaValue.valueOf(.25), db=LuaValue.valueOf(.5); + + // like kinds + assertEquals(3.>=4., ia.gteq(ib).toboolean()); + assertEquals(.25>=.5, da.gteq(db).toboolean()); + assertEquals(3.>=4., ia.gteq_b(ib)); + assertEquals(.25>=.5, da.gteq_b(db)); + + // unlike kinds + assertEquals(3.>=.25, ia.gteq(da).toboolean()); + assertEquals(.25>=3., da.gteq(ia).toboolean()); + assertEquals(3.>=.25, ia.gteq_b(da)); + assertEquals(.25>=3., da.gteq_b(ia)); + } + + public void testNotEq() { + LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(4); + LuaValue da=LuaValue.valueOf(.25), db=LuaValue.valueOf(.5); + LuaValue sa=LuaValue.valueOf("1.5"), sb=LuaValue.valueOf("2.0"); + + // like kinds + assertEquals(3.!=4., ia.neq(ib).toboolean()); + assertEquals(.25!=.5, da.neq(db).toboolean()); + assertEquals(1.5!=2., sa.neq(sb).toboolean()); + assertEquals(3.!=4., ia.neq_b(ib)); + assertEquals(.25!=.5, da.neq_b(db)); + assertEquals(1.5!=2., sa.neq_b(sb)); + + // unlike kinds + assertEquals(3.!=.25, ia.neq(da).toboolean()); + assertEquals(.25!=3., da.neq(ia).toboolean()); + assertEquals(3.!=1.5, ia.neq(sa).toboolean()); + assertEquals(1.5!=3., sa.neq(ia).toboolean()); + assertEquals(.25!=1.5, da.neq(sa).toboolean()); + assertEquals(1.5!=.25, sa.neq(da).toboolean()); + assertEquals(3.!=.25, ia.neq_b(da)); + assertEquals(.25!=3., da.neq_b(ia)); + assertEquals(3.!=1.5, ia.neq_b(sa)); + assertEquals(1.5!=3., sa.neq_b(ia)); + assertEquals(.25!=1.5, da.neq_b(sa)); + assertEquals(1.5!=.25, sa.neq_b(da)); + } + + + public void testCompareErrors() { + LuaValue ia=LuaValue.valueOf(111), ib=LuaValue.valueOf(44); + LuaValue da=LuaValue.valueOf(55.25), db=LuaValue.valueOf(3.5); + LuaValue sa=LuaValue.valueOf("22.125"), sb=LuaValue.valueOf("7.25"); + + String[] ops = { "lt", "lteq", }; + LuaValue[] vals = { LuaValue.NIL, LuaValue.TRUE, LuaValue.tableOf() }; + LuaValue[] numerics = { LuaValue.valueOf(111), LuaValue.valueOf(55.25), LuaValue.valueOf("22.125") }; + for ( int i=0; i 4); + + // check that table can be used to get elements + assertEquals(tableValue, t.get("table")); + assertEquals(stringValue, t.get("string")); + assertEquals(obj, t.get("userdata").checkuserdata()); + + // nothing should be collected, since we have strong references here + collectGarbage(); + + // check that elements are still there + assertEquals(tableValue, t.get("table")); + assertEquals(stringValue, t.get("string")); + assertEquals(obj, t.get("userdata").checkuserdata()); + + // drop our strong references + obj = null; + tableValue = null; + stringValue = null; + + // Garbage collection should cause weak entries to be dropped. + collectGarbage(); + + // check that they are dropped + assertEquals(LuaValue.NIL, t.get("table")); + assertEquals(LuaValue.NIL, t.get("userdata")); + assertFalse("strings should not be in weak references", t.get("string").isnil()); + } + } + + public static class WeakKeyTableTest extends WeakTableTest { + protected LuaTable new_Table() { return new WeakTable(true, false); } + protected LuaTable new_Table(int n,int m) { return new WeakTable(true, false); } + + public void testWeakKeysTable() { + LuaTable t = new WeakTable(true, false); + + LuaValue key = LuaValue.userdataOf(new MyData(111)); + LuaValue val = LuaValue.userdataOf(new MyData(222)); + + // set up the table + t.set( key, val ); + assertEquals( val, t.get(key) ); + System.gc(); + assertEquals( val, t.get(key) ); + + // drop key and value references, replace them with new ones + WeakReference origkey = new WeakReference(key); + WeakReference origval = new WeakReference(val); + key = LuaValue.userdataOf(new MyData(111)); + val = LuaValue.userdataOf(new MyData(222)); + + // new key and value should be interchangeable (feature of this test class) + assertEquals( key, origkey.get() ); + assertEquals( val, origval.get() ); + assertEquals( val, t.get(key) ); + assertEquals( val, t.get((LuaValue) origkey.get()) ); + assertEquals( origval.get(), t.get(key) ); + + // value should not be reachable after gc + collectGarbage(); + assertEquals( null, origkey.get() ); + assertEquals( LuaValue.NIL, t.get(key) ); + collectGarbage(); + assertEquals( null, origval.get() ); + } + + public void testNext() { + LuaTable t = new WeakTable(true, true); + + LuaValue key = LuaValue.userdataOf(new MyData(111)); + LuaValue val = LuaValue.userdataOf(new MyData(222)); + LuaValue key2 = LuaValue.userdataOf(new MyData(333)); + LuaValue val2 = LuaValue.userdataOf(new MyData(444)); + LuaValue key3 = LuaValue.userdataOf(new MyData(555)); + LuaValue val3 = LuaValue.userdataOf(new MyData(666)); + + // set up the table + t.set( key, val ); + t.set( key2, val2 ); + t.set( key3, val3 ); + + // forget one of the keys + key2 = null; + val2 = null; + collectGarbage(); + + // table should have 2 entries + int size = 0; + for ( LuaValue k = t.next(LuaValue.NIL).arg1(); !k.isnil(); + k = t.next(k).arg1() ) { + size++; + } + assertEquals(2, size); + } + } + + public static class WeakKeyValueTableTest extends WeakTableTest { + protected LuaTable new_Table() { return new WeakTable(true, true); } + protected LuaTable new_Table(int n,int m) { return new WeakTable(true, true); } + + public void testWeakKeysValuesTable() { + LuaTable t = new WeakTable(true, true); + + LuaValue key = LuaValue.userdataOf(new MyData(111)); + LuaValue val = LuaValue.userdataOf(new MyData(222)); + LuaValue key2 = LuaValue.userdataOf(new MyData(333)); + LuaValue val2 = LuaValue.userdataOf(new MyData(444)); + LuaValue key3 = LuaValue.userdataOf(new MyData(555)); + LuaValue val3 = LuaValue.userdataOf(new MyData(666)); + + // set up the table + t.set( key, val ); + t.set( key2, val2 ); + t.set( key3, val3 ); + assertEquals( val, t.get(key) ); + assertEquals( val2, t.get(key2) ); + assertEquals( val3, t.get(key3) ); + System.gc(); + assertEquals( val, t.get(key) ); + assertEquals( val2, t.get(key2) ); + assertEquals( val3, t.get(key3) ); + + // drop key and value references, replace them with new ones + WeakReference origkey = new WeakReference(key); + WeakReference origval = new WeakReference(val); + WeakReference origkey2 = new WeakReference(key2); + WeakReference origval2 = new WeakReference(val2); + WeakReference origkey3 = new WeakReference(key3); + WeakReference origval3 = new WeakReference(val3); + key = LuaValue.userdataOf(new MyData(111)); + val = LuaValue.userdataOf(new MyData(222)); + key2 = LuaValue.userdataOf(new MyData(333)); + // don't drop val2, or key3 + val3 = LuaValue.userdataOf(new MyData(666)); + + // no values should be reachable after gc + collectGarbage(); + assertEquals( null, origkey.get() ); + assertEquals( null, origval.get() ); + assertEquals( null, origkey2.get() ); + assertEquals( null, origval3.get() ); + assertEquals( LuaValue.NIL, t.get(key) ); + assertEquals( LuaValue.NIL, t.get(key2) ); + assertEquals( LuaValue.NIL, t.get(key3) ); + + // all originals should be gone after gc, then access + val2 = null; + key3 = null; + collectGarbage(); + assertEquals( null, origval2.get() ); + assertEquals( null, origkey3.get() ); + } + + public void testReplace() { + LuaTable t = new WeakTable(true, true); + + LuaValue key = LuaValue.userdataOf(new MyData(111)); + LuaValue val = LuaValue.userdataOf(new MyData(222)); + LuaValue key2 = LuaValue.userdataOf(new MyData(333)); + LuaValue val2 = LuaValue.userdataOf(new MyData(444)); + LuaValue key3 = LuaValue.userdataOf(new MyData(555)); + LuaValue val3 = LuaValue.userdataOf(new MyData(666)); + + // set up the table + t.set( key, val ); + t.set( key2, val2 ); + t.set( key3, val3 ); + + LuaValue val4 = LuaValue.userdataOf(new MyData(777)); + t.set( key2, val4 ); + + // table should have 3 entries + int size = 0; + for ( LuaValue k = t.next(LuaValue.NIL).arg1(); + !k.isnil() && size < 1000; + k = t.next(k).arg1() ) { + size++; + } + assertEquals(3, size); + } + } +} diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/compiler/AbstractUnitTests.java b/luaj-2.0.3/test/junit/org/luaj/vm2/compiler/AbstractUnitTests.java new file mode 100644 index 0000000000..9695506ae8 --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/compiler/AbstractUnitTests.java @@ -0,0 +1,123 @@ +package org.luaj.vm2.compiler; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.net.MalformedURLException; +import java.net.URL; + +import junit.framework.TestCase; + +import org.luaj.vm2.LoadState; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.Print; +import org.luaj.vm2.Prototype; +import org.luaj.vm2.lib.jse.JsePlatform; + +abstract public class AbstractUnitTests extends TestCase { + + private final String dir; + private final String jar; + private LuaTable _G; + + public AbstractUnitTests(String zipdir, String zipfile, String dir) { + URL zip = null; + zip = getClass().getResource(zipfile); + if ( zip == null ) { + File file = new File(zipdir+"/"+zipfile); + try { + if ( file.exists() ) + zip = file.toURI().toURL(); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + if ( zip == null ) + throw new RuntimeException("not found: "+zipfile); + this.jar = "jar:" + zip.toExternalForm()+ "!/"; + this.dir = dir; + } + + protected void setUp() throws Exception { + super.setUp(); + _G = JsePlatform.standardGlobals(); + } + + protected String pathOfFile(String file) { + return jar + dir + "/" + file; + } + + protected InputStream inputStreamOfPath(String path) throws IOException { + URL url = new URL(path); + return url.openStream(); + } + + protected InputStream inputStreamOfFile(String file) throws IOException { + return inputStreamOfPath(pathOfFile(file)); + } + + protected void doTest(String file) { + try { + // load source from jar + String path = pathOfFile(file); + byte[] lua = bytesFromJar(path); + + // compile in memory + InputStream is = new ByteArrayInputStream(lua); + Prototype p = LuaC.instance.compile(is, "@" + file); + String actual = protoToString(p); + + // load expected value from jar + byte[] luac = bytesFromJar(path.substring(0, path.length()-4)+".lc"); + Prototype e = loadFromBytes(luac, file); + String expected = protoToString(e); + + // compare results + assertEquals(expected, actual); + + // dump into memory + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DumpState.dump(p, baos, false); + byte[] dumped = baos.toByteArray(); + + // re-undump + Prototype p2 = loadFromBytes(dumped, file); + String actual2 = protoToString(p2); + + // compare again + assertEquals(actual, actual2); + + } catch (IOException e) { + fail(e.toString()); + } + } + + protected byte[] bytesFromJar(String path) throws IOException { + InputStream is = inputStreamOfPath(path); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[2048]; + int n; + while ((n = is.read(buffer)) >= 0) + baos.write(buffer, 0, n); + is.close(); + return baos.toByteArray(); + } + + protected Prototype loadFromBytes(byte[] bytes, String script) + throws IOException { + InputStream is = new ByteArrayInputStream(bytes); + return LoadState.loadBinaryChunk(is.read(), is, script); + } + + protected String protoToString(Prototype p) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(baos); + Print.ps = ps; + new Print().printFunction(p, true); + return baos.toString(); + } + +} diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/compiler/CompilerUnitTests.java b/luaj-2.0.3/test/junit/org/luaj/vm2/compiler/CompilerUnitTests.java new file mode 100644 index 0000000000..2def5e54ac --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/compiler/CompilerUnitTests.java @@ -0,0 +1,35 @@ +package org.luaj.vm2.compiler; + + + +public class CompilerUnitTests extends AbstractUnitTests { + + public CompilerUnitTests() { + super("test/lua", "luaj2.0-tests.zip", "lua5.1-tests"); + } + + public void testAll() { doTest("all.lua"); } + public void testApi() { doTest("api.lua"); } + public void testAttrib() { doTest("attrib.lua"); } + public void testBig() { doTest("big.lua"); } + public void testCalls() { doTest("calls.lua"); } + public void testChecktable() { doTest("checktable.lua"); } + public void testClosure() { doTest("closure.lua"); } + public void testCode() { doTest("code.lua"); } + public void testConstruct() { doTest("constructs.lua"); } + public void testDb() { doTest("db.lua"); } + public void testErrors() { doTest("errors.lua"); } + public void testEvents() { doTest("events.lua"); } + public void testFiles() { doTest("files.lua"); } + public void testGc() { doTest("gc.lua"); } + public void testLiterals() { doTest("literals.lua"); } + public void testLocals() { doTest("locals.lua"); } + public void testMain() { doTest("main.lua"); } + public void testMath() { doTest("math.lua"); } + public void testNextvar() { doTest("nextvar.lua"); } + public void testPm() { doTest("pm.lua"); } + public void testSort() { doTest("sort.lua"); } + public void testStrings() { doTest("strings.lua"); } + public void testVararg() { doTest("vararg.lua"); } + public void testVerybig() { doTest("verybig.lua"); } +} diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java b/luaj-2.0.3/test/junit/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java new file mode 100644 index 0000000000..119d0ea515 --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java @@ -0,0 +1,135 @@ +package org.luaj.vm2.compiler; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import junit.framework.TestCase; + +import org.luaj.vm2.LoadState; +import org.luaj.vm2.LuaClosure; +import org.luaj.vm2.LuaFunction; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Prototype; +import org.luaj.vm2.lib.jse.JsePlatform; + + +public class DumpLoadEndianIntTest extends TestCase { + private static final String SAVECHUNKS = "SAVECHUNKS"; + + private static final boolean SHOULDPASS = true; + private static final boolean SHOULDFAIL = false; + private static final String mixedscript = "return tostring(1234)..'-#!-'..tostring(23.75)"; + private static final String intscript = "return tostring(1234)..'-#!-'..tostring(23)"; + private static final String withdoubles = "1234-#!-23.75"; + private static final String withints = "1234-#!-23"; + + private LuaTable _G; + + protected void setUp() throws Exception { + super.setUp(); + _G = JsePlatform.standardGlobals(); + DumpState.ALLOW_INTEGER_CASTING = false; + } + + public void testBigDoubleCompile() { + doTest( false, DumpState.NUMBER_FORMAT_FLOATS_OR_DOUBLES, false, mixedscript, withdoubles, withdoubles, SHOULDPASS ); + doTest( false, DumpState.NUMBER_FORMAT_FLOATS_OR_DOUBLES, true, mixedscript, withdoubles, withdoubles, SHOULDPASS ); + } + + public void testLittleDoubleCompile() { + doTest( true, DumpState.NUMBER_FORMAT_FLOATS_OR_DOUBLES, false, mixedscript, withdoubles, withdoubles, SHOULDPASS ); + doTest( true, DumpState.NUMBER_FORMAT_FLOATS_OR_DOUBLES, true, mixedscript, withdoubles, withdoubles, SHOULDPASS ); + } + + public void testBigIntCompile() { + DumpState.ALLOW_INTEGER_CASTING = true; + doTest( false, DumpState.NUMBER_FORMAT_INTS_ONLY, false, mixedscript, withdoubles, withints, SHOULDPASS ); + doTest( false, DumpState.NUMBER_FORMAT_INTS_ONLY, true, mixedscript, withdoubles, withints, SHOULDPASS ); + DumpState.ALLOW_INTEGER_CASTING = false; + doTest( false, DumpState.NUMBER_FORMAT_INTS_ONLY, false, mixedscript, withdoubles, withints, SHOULDFAIL ); + doTest( false, DumpState.NUMBER_FORMAT_INTS_ONLY, true, mixedscript, withdoubles, withints, SHOULDFAIL ); + doTest( false, DumpState.NUMBER_FORMAT_INTS_ONLY, false, intscript, withints, withints, SHOULDPASS ); + doTest( false, DumpState.NUMBER_FORMAT_INTS_ONLY, true, intscript, withints, withints, SHOULDPASS ); + } + + public void testLittleIntCompile() { + DumpState.ALLOW_INTEGER_CASTING = true; + doTest( true, DumpState.NUMBER_FORMAT_INTS_ONLY, false, mixedscript, withdoubles, withints, SHOULDPASS ); + doTest( true, DumpState.NUMBER_FORMAT_INTS_ONLY, true, mixedscript, withdoubles, withints, SHOULDPASS ); + DumpState.ALLOW_INTEGER_CASTING = false; + doTest( true, DumpState.NUMBER_FORMAT_INTS_ONLY, false, mixedscript, withdoubles, withints, SHOULDFAIL ); + doTest( true, DumpState.NUMBER_FORMAT_INTS_ONLY, true, mixedscript, withdoubles, withints, SHOULDFAIL ); + doTest( true, DumpState.NUMBER_FORMAT_INTS_ONLY, false, intscript, withints, withints, SHOULDPASS ); + doTest( true, DumpState.NUMBER_FORMAT_INTS_ONLY, true, intscript, withints, withints, SHOULDPASS ); + } + + public void testBigNumpatchCompile() { + doTest( false, DumpState.NUMBER_FORMAT_NUM_PATCH_INT32, false, mixedscript, withdoubles, withdoubles, SHOULDPASS ); + doTest( false, DumpState.NUMBER_FORMAT_NUM_PATCH_INT32, true, mixedscript, withdoubles, withdoubles, SHOULDPASS ); + } + + public void testLittleNumpatchCompile() { + doTest( true, DumpState.NUMBER_FORMAT_NUM_PATCH_INT32, false, mixedscript, withdoubles, withdoubles, SHOULDPASS ); + doTest( true, DumpState.NUMBER_FORMAT_NUM_PATCH_INT32, true, mixedscript, withdoubles, withdoubles, SHOULDPASS ); + } + + public void doTest( boolean littleEndian, int numberFormat, boolean stripDebug, + String script, String expectedPriorDump, String expectedPostDump, boolean shouldPass ) { + try { + + // compile into prototype + InputStream is = new ByteArrayInputStream(script.getBytes()); + Prototype p = LuaC.instance.compile(is, "script"); + + // double check script result before dumping + LuaFunction f = new LuaClosure(p, _G); + LuaValue r = f.call(); + String actual = r.tojstring(); + assertEquals( expectedPriorDump, actual ); + + // dump into bytes + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + DumpState.dump(p, baos, stripDebug, numberFormat, littleEndian); + if ( ! shouldPass ) + fail( "dump should not have succeeded" ); + } catch ( Exception e ) { + if ( shouldPass ) + fail( "dump threw "+e ); + else + return; + } + byte[] dumped = baos.toByteArray(); + + // load again using compiler + is = new ByteArrayInputStream(dumped); + f = LoadState.load(is, "dumped", _G); + r = f.call(); + actual = r.tojstring(); + assertEquals( expectedPostDump, actual ); + + // write test chunk + if ( System.getProperty(SAVECHUNKS) != null && script.equals(mixedscript) ) { + new File("build").mkdirs(); + String filename = "build/test-" + +(littleEndian? "little-": "big-") + +(numberFormat==DumpState.NUMBER_FORMAT_FLOATS_OR_DOUBLES? "double-": + numberFormat==DumpState.NUMBER_FORMAT_INTS_ONLY? "int-": + numberFormat==DumpState.NUMBER_FORMAT_NUM_PATCH_INT32? "numpatch4-": "???-") + +(stripDebug? "nodebug-": "debug-") + +"bin.lua"; + FileOutputStream fos = new FileOutputStream(filename); + fos.write( dumped ); + fos.close(); + } + + } catch (IOException e) { + fail(e.toString()); + } + } +} diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/compiler/RegressionTests.java b/luaj-2.0.3/test/junit/org/luaj/vm2/compiler/RegressionTests.java new file mode 100644 index 0000000000..735b030288 --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/compiler/RegressionTests.java @@ -0,0 +1,30 @@ +package org.luaj.vm2.compiler; + +/** + * Framework to add regression tests as problem areas are found. + * + * To add a new regression test: + * 1) run "unpack.sh" in the project root + * 2) add a new "lua" file in the "regressions" subdirectory + * 3) run "repack.sh" in the project root + * 4) add a line to the source file naming the new test + * + * After adding a test, check in the zip file + * rather than the individual regression test files. + * + * @author jrosebor + */ +public class RegressionTests extends AbstractUnitTests { + + public RegressionTests() { + super( "test/lua", "luaj2.0-tests.zip", "regressions" ); + } + + public void testModulo() { doTest("modulo.lua"); } + public void testConstruct() { doTest("construct.lua"); } + public void testBigAttrs() { doTest("bigattr.lua"); } + public void testControlChars() { doTest("controlchars.lua"); } + public void testComparators() { doTest("comparators.lua"); } + public void testMathRandomseed() { doTest("mathrandomseed.lua"); } + public void testVarargs() { doTest("varargs.lua"); } +} diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/compiler/SimpleTests.java b/luaj-2.0.3/test/junit/org/luaj/vm2/compiler/SimpleTests.java new file mode 100644 index 0000000000..e8b2ae1fa4 --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/compiler/SimpleTests.java @@ -0,0 +1,101 @@ +package org.luaj.vm2.compiler; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import junit.framework.TestCase; + +import org.luaj.vm2.LuaDouble; +import org.luaj.vm2.LuaFunction; +import org.luaj.vm2.LuaInteger; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.jse.JsePlatform; + +public class SimpleTests extends TestCase { + + private LuaTable _G; + + protected void setUp() throws Exception { + super.setUp(); + _G = JsePlatform.standardGlobals(); + } + + private void doTest( String script ) { + try { + InputStream is = new ByteArrayInputStream( script.getBytes("UTF8") ); + LuaFunction c = LuaC.instance.load( is, "script", _G ); + c.call(); + } catch ( Exception e ) { + fail("i/o exception: "+e ); + } + } + + public void testTrivial() { + String s = "print( 2 )\n"; + doTest( s ); + } + + public void testAlmostTrivial() { + String s = "print( 2 )\n" + + "print( 3 )\n"; + doTest( s ); + } + + public void testSimple() { + String s = "print( 'hello, world' )\n"+ + "for i = 2,4 do\n" + + " print( 'i', i )\n" + + "end\n"; + doTest( s ); + } + + public void testBreak() { + String s = "a=1\n"+ + "while true do\n"+ + " if a>10 then\n"+ + " break\n"+ + " end\n"+ + " a=a+1\n"+ + " print( a )\n"+ + "end\n"; + doTest( s ); + } + + public void testShebang() { + String s = "#!../lua\n"+ + "print( 2 )\n"; + doTest( s ); + } + + public void testInlineTable() { + String s = "A = {g=10}\n"+ + "print( A )\n"; + doTest( s ); + } + + public void testEqualsAnd() { + String s = "print( 1 == b and b )\n"; + doTest( s ); + } + + private static final int [] samehash = { 0, 1, -1, 2, -2, 4, 8, 16, 32, Integer.MAX_VALUE, Integer.MIN_VALUE }; + private static final double [] diffhash = { .5, 1, 1.5, 1, .5, 1.5, 1.25, 2.5 }; + + public void testDoubleHashCode() { + for ( int i=0; i=0 ); + } + + public void testLuaErrorCause() { + String script = "luajava.bindClass( \""+SomeClass.class.getName()+"\"):someMethod()"; + LuaValue chunk = _G.get("loadstring").call(LuaValue.valueOf(script)); + try { + chunk.invoke(LuaValue.NONE); + fail( "call should not have succeeded" ); + } catch ( LuaError lee ) { + Throwable c = lee.getCause(); + assertEquals( SomeException.class, c.getClass() ); + } + } + + public interface VarArgsInterface { + public String varargsMethod( String a, String ... v ); + public String arrayargsMethod( String a, String[] v ); + } + + public void testVarArgsProxy() { + String script = "return luajava.createProxy( \""+VarArgsInterface.class.getName()+"\", \n"+ + "{\n" + + " varargsMethod = function(a,...)\n" + + " return table.concat({a,...},'-')\n" + + " end,\n" + + " arrayargsMethod = function(a,array)\n" + + " return tostring(a)..(array and \n" + + " ('-'..tostring(array.length)\n" + + " ..'-'..tostring(array[1])\n" + + " ..'-'..tostring(array[2])\n" + + " ) or '-nil')\n" + + " end,\n" + + "} )\n"; + Varargs chunk = _G.get("loadstring").call(LuaValue.valueOf(script)); + if ( ! chunk.arg1().toboolean() ) + fail( chunk.arg(2).toString() ); + LuaValue result = chunk.arg1().call(); + Object u = result.touserdata(); + VarArgsInterface v = (VarArgsInterface) u; + assertEquals( "foo", v.varargsMethod("foo") ); + assertEquals( "foo-bar", v.varargsMethod("foo", "bar") ); + assertEquals( "foo-bar-etc", v.varargsMethod("foo", "bar", "etc") ); + assertEquals( "foo-0-nil-nil", v.arrayargsMethod("foo", new String[0]) ); + assertEquals( "foo-1-bar-nil", v.arrayargsMethod("foo", new String[] {"bar"}) ); + assertEquals( "foo-2-bar-etc", v.arrayargsMethod("foo", new String[] {"bar","etc"}) ); + assertEquals( "foo-3-bar-etc", v.arrayargsMethod("foo", new String[] {"bar","etc","etc"}) ); + assertEquals( "foo-nil", v.arrayargsMethod("foo", null) ); + } + + public void testBigNum() { + String script = + "bigNumA = luajava.newInstance('java.math.BigDecimal','12345678901234567890');\n" + + "bigNumB = luajava.newInstance('java.math.BigDecimal','12345678901234567890');\n" + + "bigNumC = bigNumA:multiply(bigNumB);\n" + + //"print(bigNumA:toString())\n" + + //"print(bigNumB:toString())\n" + + //"print(bigNumC:toString())\n" + + "return bigNumA:toString(), bigNumB:toString(), bigNumC:toString()"; + Varargs chunk = _G.get("loadstring").call(LuaValue.valueOf(script)); + if ( ! chunk.arg1().toboolean() ) + fail( chunk.arg(2).toString() ); + Varargs results = chunk.arg1().invoke(); + int nresults = results.narg(); + String sa = results.tojstring(1); + String sb = results.tojstring(2); + String sc = results.tojstring(3); + assertEquals( 3, nresults ); + assertEquals( "12345678901234567890", sa ); + assertEquals( "12345678901234567890", sb ); + assertEquals( "152415787532388367501905199875019052100", sc ); + } + + public interface IA {} + public interface IB extends IA {} + public interface IC extends IB {} + + public static class A implements IA { + } + public static class B extends A implements IB { + public String set( Object x ) { return "set(Object) "; } + public String set( String x ) { return "set(String) "+x; } + public String set( A x ) { return "set(A) "; } + public String set( B x ) { return "set(B) "; } + public String set( C x ) { return "set(C) "; } + public String set( byte x ) { return "set(byte) "+x; } + public String set( char x ) { return "set(char) "+(int)x; } + public String set( short x ) { return "set(short) "+x; } + public String set( int x ) { return "set(int) "+x; } + public String set( long x ) { return "set(long) "+x; } + public String set( float x ) { return "set(float) "+x; } + public String set( double x ) { return "set(double) "+x; } + + public String setr( double x ) { return "setr(double) "+x; } + public String setr( float x ) { return "setr(float) "+x; } + public String setr( long x ) { return "setr(long) "+x; } + public String setr( int x ) { return "setr(int) "+x; } + public String setr( short x ) { return "setr(short) "+x; } + public String setr( char x ) { return "setr(char) "+(int)x; } + public String setr( byte x ) { return "setr(byte) "+x; } + public String setr( C x ) { return "setr(C) "; } + public String setr( B x ) { return "setr(B) "; } + public String setr( A x ) { return "setr(A) "; } + public String setr( String x ) { return "setr(String) "+x; } + public String setr( Object x ) { return "setr(Object) "; } + + public Object getObject() { return new Object(); } + public String getString() { return "abc"; } + public byte[] getbytearray() { return new byte[] { 1, 2, 3 }; } + public A getA() { return new A(); } + public B getB() { return new B(); } + public C getC() { return new C(); } + public byte getbyte() { return 1; } + public char getchar() { return 65000; } + public short getshort() { return -32000; } + public int getint() { return 100000; } + public long getlong() { return 50000000000L; } + public float getfloat() { return 6.5f; } + public double getdouble() { return Math.PI; } + } + public static class C extends B implements IC { + } + public static class D extends C implements IA { + } + + public void testOverloadedJavaMethodObject() { doOverloadedMethodTest( "Object", "" ); } + public void testOverloadedJavaMethodString() { doOverloadedMethodTest( "String", "abc" ); } + public void testOverloadedJavaMethodA() { doOverloadedMethodTest( "A", "" ); } + public void testOverloadedJavaMethodB() { doOverloadedMethodTest( "B", "" ); } + public void testOverloadedJavaMethodC() { doOverloadedMethodTest( "C", "" ); } + public void testOverloadedJavaMethodByte() { doOverloadedMethodTest( "byte", "1" ); } + public void testOverloadedJavaMethodChar() { doOverloadedMethodTest( "char", "65000" ); } + public void testOverloadedJavaMethodShort() { doOverloadedMethodTest( "short", "-32000" ); } + public void testOverloadedJavaMethodInt() { doOverloadedMethodTest( "int", "100000" ); } + public void testOverloadedJavaMethodLong() { doOverloadedMethodTest( "long", "50000000000" ); } + public void testOverloadedJavaMethodFloat() { doOverloadedMethodTest( "float", "6.5" ); } + public void testOverloadedJavaMethodDouble() { doOverloadedMethodTest( "double", "3.141592653589793" ); } + + private void doOverloadedMethodTest( String typename, String value ) { + String script = + "local a = luajava.newInstance('"+B.class.getName()+"');\n" + + "local b = a:set(a:get"+typename+"())\n" + + "local c = a:setr(a:get"+typename+"())\n" + + "return b,c"; + Varargs chunk = _G.get("loadstring").call(LuaValue.valueOf(script)); + if ( ! chunk.arg1().toboolean() ) + fail( chunk.arg(2).toString() ); + Varargs results = chunk.arg1().invoke(); + int nresults = results.narg(); + assertEquals( 2, nresults ); + LuaValue b = results.arg(1); + LuaValue c = results.arg(2); + String sb = b.tojstring(); + String sc = c.tojstring(); + assertEquals( "set("+typename+") "+value, sb ); + assertEquals( "setr("+typename+") "+value, sc ); + } + + public void testClassInheritanceLevels() { + assertEquals( 0, CoerceLuaToJava.inheritanceLevels(Object.class, Object.class) ); + assertEquals( 1, CoerceLuaToJava.inheritanceLevels(Object.class, String.class) ); + assertEquals( 1, CoerceLuaToJava.inheritanceLevels(Object.class, A.class) ); + assertEquals( 2, CoerceLuaToJava.inheritanceLevels(Object.class, B.class) ); + assertEquals( 3, CoerceLuaToJava.inheritanceLevels(Object.class, C.class) ); + + assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(A.class, Object.class) ); + assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(A.class, String.class) ); + assertEquals( 0, CoerceLuaToJava.inheritanceLevels(A.class, A.class) ); + assertEquals( 1, CoerceLuaToJava.inheritanceLevels(A.class, B.class) ); + assertEquals( 2, CoerceLuaToJava.inheritanceLevels(A.class, C.class) ); + + assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(B.class, Object.class) ); + assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(B.class, String.class) ); + assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(B.class, A.class) ); + assertEquals( 0, CoerceLuaToJava.inheritanceLevels(B.class, B.class) ); + assertEquals( 1, CoerceLuaToJava.inheritanceLevels(B.class, C.class) ); + + assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, Object.class) ); + assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, String.class) ); + assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, A.class) ); + assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, B.class) ); + assertEquals( 0, CoerceLuaToJava.inheritanceLevels(C.class, C.class) ); + } + + public void testInterfaceInheritanceLevels() { + assertEquals( 1, CoerceLuaToJava.inheritanceLevels(IA.class, A.class) ); + assertEquals( 1, CoerceLuaToJava.inheritanceLevels(IB.class, B.class) ); + assertEquals( 2, CoerceLuaToJava.inheritanceLevels(IA.class, B.class) ); + assertEquals( 1, CoerceLuaToJava.inheritanceLevels(IC.class, C.class) ); + assertEquals( 2, CoerceLuaToJava.inheritanceLevels(IB.class, C.class) ); + assertEquals( 3, CoerceLuaToJava.inheritanceLevels(IA.class, C.class) ); + assertEquals( 1, CoerceLuaToJava.inheritanceLevels(IA.class, D.class) ); + assertEquals( 2, CoerceLuaToJava.inheritanceLevels(IC.class, D.class) ); + assertEquals( 3, CoerceLuaToJava.inheritanceLevels(IB.class, D.class) ); + + assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IB.class, A.class) ); + assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IC.class, A.class) ); + assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IC.class, B.class) ); + assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IB.class, IA.class) ); + assertEquals( 1, CoerceLuaToJava.inheritanceLevels(IA.class, IB.class) ); + + } +} + diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/lib/jse/LuajavaAccessibleMembersTest.java b/luaj-2.0.3/test/junit/org/luaj/vm2/lib/jse/LuajavaAccessibleMembersTest.java new file mode 100644 index 0000000000..1bb2d99cff --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/lib/jse/LuajavaAccessibleMembersTest.java @@ -0,0 +1,70 @@ +package org.luaj.vm2.lib.jse; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.security.Permission; + +import junit.framework.TestCase; + +import org.luaj.vm2.LuaFunction; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.compiler.LuaC; +import org.luaj.vm2.lib.jse.JsePlatform; + +public class LuajavaAccessibleMembersTest extends TestCase { + + private LuaTable _G; + + protected void setUp() throws Exception { + super.setUp(); + _G = JsePlatform.standardGlobals(); + } + + private String invokeScript(String script) { + try { + InputStream is = new ByteArrayInputStream( script.getBytes("UTF8") ); + LuaFunction c = LuaC.instance.load( is, "script", _G ); + return c.call().tojstring(); + } catch ( Exception e ) { + fail("exception: "+e ); + return "failed"; + } + } + + public void testAccessFromPrivateClassImplementedMethod() { + assertEquals("privateImpl-aaa-interface_method(bar)", invokeScript( + "b = luajava.newInstance('"+TestClass.class.getName()+"');" + + "a = b:create_PrivateImpl('aaa');" + + "return a:interface_method('bar');")); + } + + public void testAccessFromPrivateClassPublicMethod() { + assertEquals("privateImpl-aaa-public_method", invokeScript( + "b = luajava.newInstance('"+TestClass.class.getName()+"');" + + "a = b:create_PrivateImpl('aaa');" + + "return a:public_method();")); + } + + public void testAccessFromPrivateClassGetPublicField() { + assertEquals("aaa", invokeScript( + "b = luajava.newInstance('"+TestClass.class.getName()+"');" + + "a = b:create_PrivateImpl('aaa');" + + "return a.public_field;")); + } + + public void testAccessFromPrivateClassSetPublicField() { + assertEquals("foo", invokeScript( + "b = luajava.newInstance('"+TestClass.class.getName()+"');" + + "a = b:create_PrivateImpl('aaa');" + + "a.public_field = 'foo';" + + "return a.public_field;")); + } + + public void testAccessFromPrivateClassPublicConcstructor() { + assertEquals("privateImpl-constructor", invokeScript( + "b = luajava.newInstance('"+TestClass.class.getName()+"');" + + "c = b:get_PrivateImplClass();" + + "return luajava.new(c);")); + } +} diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/lib/jse/LuajavaClassMembersTest.java b/luaj-2.0.3/test/junit/org/luaj/vm2/lib/jse/LuajavaClassMembersTest.java new file mode 100644 index 0000000000..0af23eb18e --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/lib/jse/LuajavaClassMembersTest.java @@ -0,0 +1,226 @@ +package org.luaj.vm2.lib.jse; + +import junit.framework.TestCase; + +import org.luaj.vm2.LuaError; +import org.luaj.vm2.LuaValue; + +public class LuajavaClassMembersTest extends TestCase { + public static class A { + protected A() {} + } + public static class B extends A { + public byte m_byte_field; + public int m_int_field; + public double m_double_field; + public String m_string_field; + + protected B() {} + public B(int i) { m_int_field = i; } + + public String setString( String x ) { return "setString(String) "+x; } + public String getString() { return "abc"; } + public int getint() { return 100000; } + + public String uniq() { return "uniq()"; } + public String uniqs(String s) { return "uniqs(string:"+s+")"; } + public String uniqi(int i) { return "uniqi(int:"+i+")"; } + public String uniqsi(String s, int i) { return "uniqsi(string:"+s+",int:"+i+")"; } + public String uniqis(int i, String s) { return "uniqis(int:"+i+",string:"+s+")"; } + + public String pick() { return "pick()"; } + public String pick(String s) { return "pick(string:"+s+")"; } + public String pick(int i) { return "pick(int:"+i+")"; } + public String pick(String s, int i) { return "pick(string:"+s+",int:"+i+")"; } + public String pick(int i, String s) { return "pick(int:"+i+",string:"+s+")"; } + + public static String staticpick() { return "static-pick()"; } + public static String staticpick(String s) { return "static-pick(string:"+s+")"; } + public static String staticpick(int i) { return "static-pick(int:"+i+")"; } + public static String staticpick(String s, int i) { return "static-pick(string:"+s+",int:"+i+")"; } + public static String staticpick(int i, String s) { return "static-pick(int:"+i+",string:"+s+")"; } + } + public static class C extends B { + public C() {} + public C(String s) { m_string_field = s; } + public C(int i) { m_int_field = i; } + public C(String s, int i) { m_string_field = s; m_int_field = i; } + public int getint() { return 200000; } + + public String pick(String s) { return "class-c-pick(string:"+s+")"; } + public String pick(int i) { return "class-c-pick(int:"+i+")"; } + } + + static LuaValue ZERO = LuaValue.ZERO; + static LuaValue ONE = LuaValue.ONE; + static LuaValue PI = LuaValue.valueOf(Math.PI); + static LuaValue THREE = LuaValue.valueOf(3); + static LuaValue NUMS = LuaValue.valueOf(123); + static LuaValue ABC = LuaValue.valueOf("abc"); + static LuaValue SOMEA = CoerceJavaToLua.coerce(new A()); + static LuaValue SOMEB = CoerceJavaToLua.coerce(new B()); + static LuaValue SOMEC = CoerceJavaToLua.coerce(new C()); + + public void testSetByteField() { + B b = new B(); + JavaInstance i = new JavaInstance(b); + i.set("m_byte_field", ONE ); assertEquals( 1, b.m_byte_field ); assertEquals( ONE, i.get("m_byte_field") ); + i.set("m_byte_field", PI ); assertEquals( 3, b.m_byte_field ); assertEquals( THREE, i.get("m_byte_field") ); + i.set("m_byte_field", ABC ); assertEquals( 0, b.m_byte_field ); assertEquals( ZERO, i.get("m_byte_field") ); + } + public void testSetDoubleField() { + B b = new B(); + JavaInstance i = new JavaInstance(b); + i.set("m_double_field", ONE ); assertEquals( 1., b.m_double_field ); assertEquals( ONE, i.get("m_double_field") ); + i.set("m_double_field", PI ); assertEquals( Math.PI, b.m_double_field ); assertEquals( PI, i.get("m_double_field") ); + i.set("m_double_field", ABC ); assertEquals( 0., b.m_double_field ); assertEquals( ZERO, i.get("m_double_field") ); + } + public void testNoFactory() { + JavaClass c = JavaClass.forClass(A.class); + try { + c.call(); + fail( "did not throw lua error as expected" ); + } catch ( LuaError e ) { + } + } + public void testUniqueFactoryCoercible() { + JavaClass c = JavaClass.forClass(B.class); + assertEquals( JavaClass.class, c.getClass() ); + LuaValue constr = c.get("new"); + assertEquals( JavaConstructor.class, constr.getClass() ); + LuaValue v = constr.call(NUMS); + Object b = v.touserdata(); + assertEquals( B.class, b.getClass() ); + assertEquals( 123, ((B)b).m_int_field ); + Object b0 = constr.call().touserdata(); + assertEquals( B.class, b0.getClass() ); + assertEquals( 0, ((B)b0).m_int_field ); + } + public void testUniqueFactoryUncoercible() { + JavaClass f = JavaClass.forClass(B.class); + LuaValue constr = f.get("new"); + assertEquals( JavaConstructor.class, constr.getClass() ); + try { + LuaValue v = constr.call(LuaValue.userdataOf(new Object())); + Object b = v.touserdata(); + // fail( "did not throw lua error as expected" ); + assertEquals( 0, ((B)b).m_int_field ); + } catch ( LuaError e ) { + } + } + public void testOverloadedFactoryCoercible() { + JavaClass f = JavaClass.forClass(C.class); + LuaValue constr = f.get("new"); + assertEquals( JavaConstructor.Overload.class, constr.getClass() ); + Object c = constr.call().touserdata(); + Object ci = constr.call(LuaValue.valueOf(123)).touserdata(); + Object cs = constr.call(LuaValue.valueOf("abc")).touserdata(); + Object csi = constr.call( LuaValue.valueOf("def"), LuaValue.valueOf(456) ).touserdata(); + assertEquals( C.class, c.getClass() ); + assertEquals( C.class, ci.getClass() ); + assertEquals( C.class, cs.getClass() ); + assertEquals( C.class, csi.getClass() ); + assertEquals( null, ((C)c).m_string_field ); + assertEquals( 0, ((C)c).m_int_field ); + assertEquals( "abc", ((C)cs).m_string_field ); + assertEquals( 0, ((C)cs).m_int_field ); + assertEquals( null, ((C)ci).m_string_field ); + assertEquals( 123, ((C)ci).m_int_field ); + assertEquals( "def", ((C)csi).m_string_field ); + assertEquals( 456, ((C)csi).m_int_field ); + } + public void testOverloadedFactoryUncoercible() { + JavaClass f = JavaClass.forClass(C.class); + try { + Object c = f.call(LuaValue.userdataOf(new Object())); + // fail( "did not throw lua error as expected" ); + assertEquals( 0, ((C)c).m_int_field ); + assertEquals( null, ((C)c).m_string_field ); + } catch ( LuaError e ) { + } + } + + public void testNoAttribute() { + JavaClass f = JavaClass.forClass(A.class); + LuaValue v = f.get("bogus"); + assertEquals( v, LuaValue.NIL ); + try { + f.set("bogus",ONE); + fail( "did not throw lua error as expected" ); + } catch ( LuaError e ) {} + } + public void testFieldAttributeCoercible() { + JavaInstance i = new JavaInstance(new B()); + i.set("m_int_field", ONE ); assertEquals( 1, i.get("m_int_field").toint() ); + i.set("m_int_field", THREE ); assertEquals( 3, i.get("m_int_field").toint() ); + i = new JavaInstance(new C()); + i.set("m_int_field", ONE ); assertEquals( 1, i.get("m_int_field").toint() ); + i.set("m_int_field", THREE ); assertEquals( 3, i.get("m_int_field").toint() ); + } + public void testUniqueMethodAttributeCoercible() { + B b = new B(); + JavaInstance ib = new JavaInstance(b); + LuaValue b_getString = ib.get("getString"); + LuaValue b_getint = ib.get("getint"); + assertEquals( JavaMethod.class, b_getString.getClass() ); + assertEquals( JavaMethod.class, b_getint.getClass() ); + assertEquals( "abc", b_getString.call(SOMEB).tojstring() ); + assertEquals( 100000, b_getint.call(SOMEB).toint()); + assertEquals( "abc", b_getString.call(SOMEC).tojstring() ); + assertEquals( 200000, b_getint.call(SOMEC).toint()); + } + public void testUniqueMethodAttributeArgsCoercible() { + B b = new B(); + JavaInstance ib = new JavaInstance(b); + LuaValue uniq = ib.get("uniq"); + LuaValue uniqs = ib.get("uniqs"); + LuaValue uniqi = ib.get("uniqi"); + LuaValue uniqsi = ib.get("uniqsi"); + LuaValue uniqis = ib.get("uniqis"); + assertEquals( JavaMethod.class, uniq.getClass() ); + assertEquals( JavaMethod.class, uniqs.getClass() ); + assertEquals( JavaMethod.class, uniqi.getClass() ); + assertEquals( JavaMethod.class, uniqsi.getClass() ); + assertEquals( JavaMethod.class, uniqis.getClass() ); + assertEquals( "uniq()", uniq.call(SOMEB).tojstring() ); + assertEquals( "uniqs(string:abc)", uniqs.call(SOMEB,ABC).tojstring() ); + assertEquals( "uniqi(int:1)", uniqi.call(SOMEB,ONE).tojstring() ); + assertEquals( "uniqsi(string:abc,int:1)", uniqsi.call(SOMEB,ABC,ONE).tojstring() ); + assertEquals( "uniqis(int:1,string:abc)", uniqis.call(SOMEB,ONE,ABC).tojstring() ); + assertEquals( "uniqis(int:1,string:abc)", uniqis.invoke(LuaValue.varargsOf(new LuaValue[] {SOMEB,ONE,ABC,ONE})).arg1().tojstring() ); + } + public void testOverloadedMethodAttributeCoercible() { + B b = new B(); + JavaInstance ib = new JavaInstance(b); + LuaValue p = ib.get("pick"); + assertEquals( "pick()", p.call(SOMEB).tojstring() ); + assertEquals( "pick(string:abc)", p.call(SOMEB,ABC).tojstring() ); + assertEquals( "pick(int:1)", p.call(SOMEB,ONE).tojstring() ); + assertEquals( "pick(string:abc,int:1)", p.call(SOMEB,ABC,ONE).tojstring() ); + assertEquals( "pick(int:1,string:abc)", p.call(SOMEB,ONE,ABC).tojstring() ); + assertEquals( "pick(int:1,string:abc)", p.invoke(LuaValue.varargsOf(new LuaValue[] {SOMEB,ONE,ABC,ONE})).arg1().tojstring() ); + } + public void testUnboundOverloadedMethodAttributeCoercible() { + B b = new B(); + JavaInstance ib = new JavaInstance(b); + LuaValue p = ib.get("pick"); + assertEquals( JavaMethod.Overload.class, p.getClass() ); + assertEquals( "pick()", p.call(SOMEC).tojstring() ); + assertEquals( "class-c-pick(string:abc)", p.call(SOMEC,ABC).tojstring() ); + assertEquals( "class-c-pick(int:1)", p.call(SOMEC,ONE).tojstring() ); + assertEquals( "pick(string:abc,int:1)", p.call(SOMEC,ABC,ONE).tojstring() ); + assertEquals( "pick(int:1,string:abc)", p.call(SOMEC,ONE,ABC).tojstring() ); + assertEquals( "pick(int:1,string:abc)", p.invoke(LuaValue.varargsOf(new LuaValue[] {SOMEC,ONE,ABC,ONE})).arg1().tojstring() ); + } + public void testOverloadedStaticMethodAttributeCoercible() { + B b = new B(); + JavaInstance ib = new JavaInstance(b); + LuaValue p = ib.get("staticpick"); + assertEquals( "static-pick()", p.call(SOMEB).tojstring() ); + assertEquals( "static-pick(string:abc)", p.call(SOMEB,ABC).tojstring() ); + assertEquals( "static-pick(int:1)", p.call(SOMEB,ONE).tojstring() ); + assertEquals( "static-pick(string:abc,int:1)", p.call(SOMEB,ABC,ONE).tojstring() ); + assertEquals( "static-pick(int:1,string:abc)", p.call(SOMEB,ONE,ABC).tojstring() ); + assertEquals( "static-pick(int:1,string:abc)", p.invoke(LuaValue.varargsOf(new LuaValue[] {SOMEB,ONE,ABC,ONE})).arg1().tojstring() ); + } +} diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/lib/jse/TestClass.java b/luaj-2.0.3/test/junit/org/luaj/vm2/lib/jse/TestClass.java new file mode 100644 index 0000000000..28cb7386c1 --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/lib/jse/TestClass.java @@ -0,0 +1,18 @@ +package org.luaj.vm2.lib.jse; + +public class TestClass { + private static class PrivateImpl implements TestInterface { + public String public_field; + public PrivateImpl() { + this.public_field = "privateImpl-constructor"; + } + PrivateImpl(String f) { + this.public_field = f; + } + public String public_method() { return "privateImpl-"+public_field+"-public_method"; } + public String interface_method(String x) { return "privateImpl-"+public_field+"-interface_method("+x+")"; } + public String toString() { return public_field; } + } + public TestInterface create_PrivateImpl(String f) { return new PrivateImpl(f); } + public Class get_PrivateImplClass() { return PrivateImpl.class; } +} \ No newline at end of file diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/lib/jse/TestInterface.java b/luaj-2.0.3/test/junit/org/luaj/vm2/lib/jse/TestInterface.java new file mode 100644 index 0000000000..1b58a0a516 --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/lib/jse/TestInterface.java @@ -0,0 +1,5 @@ +package org.luaj.vm2.lib.jse; + +public interface TestInterface { + String interface_method(String x); +} \ No newline at end of file diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/require/RequireSampleClassCastExcep.java b/luaj-2.0.3/test/junit/org/luaj/vm2/require/RequireSampleClassCastExcep.java new file mode 100644 index 0000000000..88ba21f6fb --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/require/RequireSampleClassCastExcep.java @@ -0,0 +1,17 @@ +package org.luaj.vm2.require; + +import org.luaj.vm2.LuaValue; + +/** + * This should fail while trying to load via "require() because it is not a LibFunction" + * + */ +public class RequireSampleClassCastExcep { + + public RequireSampleClassCastExcep() { + } + + public LuaValue call() { + return LuaValue.valueOf("require-sample-class-cast-excep"); + } +} diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/require/RequireSampleLoadLuaError.java b/luaj-2.0.3/test/junit/org/luaj/vm2/require/RequireSampleLoadLuaError.java new file mode 100644 index 0000000000..0ba5e1480f --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/require/RequireSampleLoadLuaError.java @@ -0,0 +1,20 @@ +package org.luaj.vm2.require; + +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.ZeroArgFunction; + +/** + * This should fail while trying to load via + * "require()" because it throws a LuaError + * + */ +public class RequireSampleLoadLuaError extends ZeroArgFunction { + + public RequireSampleLoadLuaError() { + } + + public LuaValue call() { + error("sample-load-lua-error"); + return LuaValue.valueOf("require-sample-load-lua-error"); + } +} diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/require/RequireSampleLoadRuntimeExcep.java b/luaj-2.0.3/test/junit/org/luaj/vm2/require/RequireSampleLoadRuntimeExcep.java new file mode 100644 index 0000000000..1f416b893e --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/require/RequireSampleLoadRuntimeExcep.java @@ -0,0 +1,18 @@ +package org.luaj.vm2.require; + +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.ZeroArgFunction; + +/** +* This should fail while trying to load via "require()" because it throws a RuntimeException + * + */ +public class RequireSampleLoadRuntimeExcep extends ZeroArgFunction { + + public RequireSampleLoadRuntimeExcep() { + } + + public LuaValue call() { + throw new RuntimeException("sample-load-runtime-exception"); + } +} diff --git a/luaj-2.0.3/test/junit/org/luaj/vm2/require/RequireSampleSuccess.java b/luaj-2.0.3/test/junit/org/luaj/vm2/require/RequireSampleSuccess.java new file mode 100644 index 0000000000..edd0c549ea --- /dev/null +++ b/luaj-2.0.3/test/junit/org/luaj/vm2/require/RequireSampleSuccess.java @@ -0,0 +1,17 @@ +package org.luaj.vm2.require; + +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.ZeroArgFunction; + +/** + * This should succeed as a library that can be loaded dynamically via "require()" + */ +public class RequireSampleSuccess extends ZeroArgFunction { + + public RequireSampleSuccess() { + } + + public LuaValue call() { + return LuaValue.valueOf("require-sample-success"); + } +} diff --git a/luaj-2.0.3/test/lua/baselib.lua b/luaj-2.0.3/test/lua/baselib.lua new file mode 100644 index 0000000000..dae00527de --- /dev/null +++ b/luaj-2.0.3/test/lua/baselib.lua @@ -0,0 +1,312 @@ + +-- tostring replacement that assigns ids +local ts,id,nid,types = tostring,{},0,{table='tbl',thread='thr',userdata='uda',['function']='func'} +tostring = function(x) + if not x or not types[type(x)] then return ts(x) end + if not id[x] then nid=nid+1; id[x]=types[type(x)]..'.'..nid end + return id[x] +end + +-- wrap pcall to return one result +-- error message are tested elsewhere +local pc = pcall +local pcall = function(...) + local s,e = pc(...) + if s then return e end + return false, type(e) +end + +-- print +print() +print(11) +print("abc",123,nil,"pqr") +print( nil and 'T' or 'F' ) +print( false and 'T' or 'F' ) +print( 0 and 'T' or 'F' ) + +-- assert +print( 'assert(true)', assert(true) ) +print( 'pcall(assert,true)', pcall(assert,true) ) +print( 'pcall(assert,false)', pcall(assert,false) ) +print( 'pcall(assert,nil)', pcall(assert,nil) ) +print( 'pcall(assert,true,"msg")', pcall(assert,true,"msg") ) +print( 'pcall(assert,false,"msg")', pcall(assert,false,"msg") ) +print( 'pcall(assert,nil,"msg")', pcall(assert,nil,"msg") ) +print( 'pcall(assert,false,"msg","msg2")', pcall(assert,false,"msg","msg2") ) + +-- collectgarbage (not supported) +print( 'collectgarbage("count")', type(collectgarbage("count"))) +print( 'collectgarbage("collect")', type(collectgarbage("collect"))) +print( 'collectgarbage("count")', type(collectgarbage("count"))) + +-- dofile (not supported) +-- ipairs +print( 'pcall(ipairs)', pcall(ipairs) ) +print( 'pcall(ipairs,nil)', pcall(ipairs,nil) ) +print( 'pcall(ipairs,"a")', pcall(ipairs,"a") ) +print( 'pcall(ipairs,1)', pcall(ipairs,1) ) +for k,v in ipairs({}) do print('ipairs1',k,v)end +for k,v in ipairs({'one','two'}) do print('ipairs2',k,v)end +for k,v in ipairs({aa='aaa',bb='bbb'}) do print('ipairs3',k,v)end +for k,v in ipairs({aa='aaa',bb='bbb','one','two'}) do print('ipairs4',k,v)end +for k,v in ipairs({[30]='30',[20]='20'}) do print('ipairs5',k,v)end + +-- load +t = { "print ", "'table ", "loaded'", "", " print'after empty string'" } +i = 0 +f = function() i = i + 1; return t[i]; end +c,e = load(f) +if c then print('load: ', pcall(c)) else print('load failed:', e) end + +-- loadfile +-- loadstring +local lst = "print(3+4); return 8" +local chunk, err = loadstring( lst ) +print( 'loadstring("'..lst..'")', chunk, err ) +print( 'loadstring("'..lst..'")()', chunk() ) + +-- pairs +print( 'pcall(pairs)', pcall(pairs) ) +print( 'pcall(pairs,nil)', pcall(pairs,nil) ) +print( 'pcall(pairs,"a")', pcall(pairs,"a") ) +print( 'pcall(pairs,1)', pcall(pairs,1) ) +for k,v in pairs({}) do print('pairs1',k,v)end +for k,v in pairs({'one','two'}) do print('pairs2',k,v)end +for k,v in pairs({aa='aaa',bb='bbb'}) do print('pairs3',k,v)end +for k,v in pairs({aa='aaa',bb='bbb','one','two'}) do print('pairs4',k,v)end +for k,v in pairs({[20]='30',[30]='20'}) do print('pairs5',k,v)end + +-- _G +print( '_G["abc"] (before)', _G["abc"] ) +abc='def' +print( '_G["abc"] (after)', _G["abc"] ) + +-- type +print( 'type(nil)', type(nil) ) +print( 'type("a")', type("a") ) +print( 'type(1)', type(1) ) +print( 'type(1.5)', type(1.5) ) +print( 'type(function() end)', type(function() end) ) +print( 'type({})', type({}) ) +print( 'type(true)', type(true) ) +print( 'type(false)', type(false) ) +print( 'pcall(type,type)', pcall(type,type) ) +print( 'pcall(type)', pcall(type) ) +print( '(function() return pcall(type) end)()', (function() return pcall(type) end)() ) +local function la() return pcall(type) end +print( 'la()', la() ) +function ga() return pcall(type) end +print( 'ga()', ga() ) + +-- getfenv, setfenv: tested in setfenv.lua +-- getmetatable, setmetatable +ta = { aa1="aaa1", aa2="aaa2" } +tb = { bb1="bbb1", bb2="bbb2" } +print( 'getmetatable(ta)', getmetatable(ta) ) +print( 'getmetatable(tb)', getmetatable(tb) ) +print( 'setmetatable(ta),{cc1="ccc1"}', type( setmetatable(ta,{cc1="ccc1"}) ) ) +print( 'setmetatable(tb),{dd1="ddd1"}', type( setmetatable(tb,{dd1="ddd1"}) ) ) +print( 'getmetatable(ta)["cc1"]', getmetatable(ta)["cc1"] ) +print( 'getmetatable(tb)["dd1"]', getmetatable(tb)["dd1"] ) +print( 'getmetatable(1)', getmetatable(1) ) +print( 'pcall(setmetatable,1)', pcall(setmetatable,1) ) +print( 'pcall(setmetatable,nil)', pcall(setmetatable,nil) ) +print( 'pcall(setmetatable,"ABC")', pcall(setmetatable,"ABC") ) +print( 'pcall(setmetatable,function() end)', pcall(setmetatable,function() end) ) + +-- rawget,rawset +local mt = {aa="aaa", bb="bbb"} +mt.__index = mt +mt.__newindex = mt +local s = {cc="ccc", dd="ddd", } +local t = {cc="ccc", dd="ddd"} +setmetatable(t,mt) +print( 'pcall(rawget)', pcall(rawget)) +print( 'pcall(rawget,"a")', pcall(rawget,"a")) +print( 'pcall(rawget,s)', pcall(rawget,s)) +print( 'pcall(rawget,t)', pcall(rawget,t)) + +function printtables() + function printtable(name,t) + print( ' '..name, t["aa"], t["bb"], t["cc"], t["dd"], t["ee"], t["ff"], t["gg"] ) + print( ' '..name, + rawget(t,"aa"), + rawget(t,"bb"), + rawget(t,"cc"), + rawget(t,"dd"), + rawget(t,"ee"), + rawget(t,"ff"), + rawget(t,"gg") ) + end + printtable( 's', s ) + printtable( 't', t ) + printtable( 'mt', mt ) +end +printtables() +print( 'pcall(rawset,s,"aa","www")', rawset(s,"aa","www")) +printtables() +print( 'pcall(rawset,s,"cc","xxx")', rawset(s,"cc","xxx")) +printtables() +print( 'pcall(rawset,t,"aa","yyy")', rawset(t,"aa","yyy")) +printtables() +print( 'pcall(rawset,t,"dd","zzz")', rawset(t,"dd","zzz")) +printtables() + +printtables() +print( 's["ee"]="ppp"' ); s["ee"]="ppp" +printtables() +print( 's["cc"]="qqq"' ); s["cc"]="qqq" +printtables() +print( 't["ff"]="rrr"' ); t["ff"]="rrr" +printtables() +print( 't["dd"]="sss"' ); t["dd"]="sss" +printtables() +print( 'mt["gg"]="ttt"' ); mt["gg"]="ttt" +printtables() + + +-- select +print( 'pcall(select)', pcall(select) ) +print( 'select(1,11,22,33,44,55)', select(1,11,22,33,44,55) ) +print( 'select(2,11,22,33,44,55)', select(2,11,22,33,44,55) ) +print( 'select(3,11,22,33,44,55)', select(3,11,22,33,44,55) ) +print( 'select(4,11,22,33,44,55)', select(4,11,22,33,44,55) ) +print( 'pcall(select,5,11,22,33,44,55)', pcall(select,5,11,22,33,44,55) ) +print( 'pcall(select,6,11,22,33,44,55)', pcall(select,6,11,22,33,44,55) ) +print( 'pcall(select,7,11,22,33,44,55)', pcall(select,7,11,22,33,44,55) ) +print( 'pcall(select,0,11,22,33,44,55)', pcall(select,0,11,22,33,44,55) ) +print( 'pcall(select,-1,11,22,33,44,55)', pcall(select,-1,11,22,33,44,55) ) +print( 'pcall(select,-2,11,22,33,44,55)', pcall(select,-2,11,22,33,44,55) ) +print( 'pcall(select,-4,11,22,33,44,55)', pcall(select,-4,11,22,33,44,55) ) +print( 'pcall(select,-5,11,22,33,44,55)', pcall(select,-5,11,22,33,44,55) ) +print( 'pcall(select,-6,11,22,33,44,55)', pcall(select,-6,11,22,33,44,55) ) +print( 'pcall(select,1)', pcall(select,1) ) +print( 'pcall(select,select)', pcall(select,select) ) +print( 'pcall(select,{})', pcall(select,{}) ) +print( 'pcall(select,"2",11,22,33)', pcall(select,"2",11,22,33) ) +print( 'pcall(select,"abc",11,22,33)', pcall(select,"abc",11,22,33) ) + + +-- tonumber +print( 'pcall(tonumber)', pcall(tostring) ) +print( 'pcall(tonumber,nil)', pcall(tonumber,nil) ) +print( 'pcall(tonumber,"abc")', pcall(tonumber,"abc") ) +print( 'pcall(tonumber,"123")', pcall(tonumber,"123") ) +print( 'pcall(tonumber,"123",10)', pcall(tonumber,"123", 10) ) +print( 'pcall(tonumber,"123",8)', pcall(tonumber,"123", 8) ) +print( 'pcall(tonumber,"123",6)', pcall(tonumber,"123", 6) ) +print( 'pcall(tonumber,"10101",4)', pcall(tonumber,"10101", 4) ) +print( 'pcall(tonumber,"10101",3)', pcall(tonumber,"10101", 3) ) +print( 'pcall(tonumber,"10101",2)', pcall(tonumber,"10101", 2) ) +print( 'pcall(tonumber,"1a1",16)', pcall(tonumber,"1a1", 16) ) +print( 'pcall(tonumber,"1a1",32)', pcall(tonumber,"1a1", 32) ) +print( 'pcall(tonumber,"1a1",54)', pcall(tonumber,"1a1", 54) ) +print( 'pcall(tonumber,"1a1",1)', pcall(tonumber,"1a1", 1) ) +print( 'pcall(tonumber,"1a1",0)', pcall(tonumber,"1a1", 0) ) +print( 'pcall(tonumber,"1a1",-1)', pcall(tonumber,"1a1", -1) ) +print( 'pcall(tonumber,"1a1","32")', pcall(tonumber,"1a1", "32") ) +print( 'pcall(tonumber,"123","456")', pcall(tonumber,"123","456") ) +print( 'pcall(tonumber,"1a1",10)', pcall(tonumber,"1a1", 10) ) +print( 'pcall(tonumber,"151",4)', pcall(tonumber,"151", 4) ) +print( 'pcall(tonumber,"151",3)', pcall(tonumber,"151", 3) ) +print( 'pcall(tonumber,"151",2)', pcall(tonumber,"151", 2) ) +print( 'pcall(tonumber,"123",8,8)', pcall(tonumber,"123", 8, 8) ) +print( 'pcall(tonumber,123)', pcall(tonumber,123) ) +print( 'pcall(tonumber,true)', pcall(tonumber,true) ) +print( 'pcall(tonumber,false)', pcall(tonumber,false) ) +print( 'pcall(tonumber,tonumber)', pcall(tonumber,tonumber) ) +print( 'pcall(tonumber,function() end)', pcall(tonumber,function() end) ) +print( 'pcall(tonumber,{"one","two",a="aa",b="bb"})', pcall(tonumber,{"one","two",a="aa",b="bb"}) ) +print( 'pcall(tonumber,"123.456")', pcall(tonumber,"123.456") ) +print( 'pcall(tonumber," 123.456")', pcall(tonumber," 123.456") ) +print( 'pcall(tonumber," 234qwer")', pcall(tonumber," 234qwer") ) +print( 'pcall(tonumber,"0x20")', pcall(tonumber,"0x20") ) +print( 'pcall(tonumber," 0x20")', pcall(tonumber," 0x20") ) +print( 'pcall(tonumber,"0x20 ")', pcall(tonumber,"0x20 ") ) +print( 'pcall(tonumber," 0x20 ")', pcall(tonumber," 0x20 ") ) +print( 'pcall(tonumber,"0X20")', pcall(tonumber,"0X20") ) +print( 'pcall(tonumber," 0X20")', pcall(tonumber," 0X20") ) +print( 'pcall(tonumber,"0X20 ")', pcall(tonumber,"0X20 ") ) +print( 'pcall(tonumber," 0X20 ")', pcall(tonumber," 0X20 ") ) +print( 'pcall(tonumber,"0x20",10)', pcall(tonumber,"0x20",10) ) +print( 'pcall(tonumber,"0x20",16)', pcall(tonumber,"0x20",16) ) +print( 'pcall(tonumber,"0x20",8)', pcall(tonumber,"0x20",8) ) + +-- tostring +print( 'pcall(tostring)', pcall(tostring) ) +print( 'pcall(tostring,nil)', pcall(tostring,nil) ) +print( 'pcall(tostring,"abc")', pcall(tostring,"abc") ) +print( 'pcall(tostring,"abc","def")', pcall(tostring,"abc","def") ) +print( 'pcall(tostring,123)', pcall(tostring,123) ) +print( 'pcall(tostring,true)', pcall(tostring,true) ) +print( 'pcall(tostring,false)', pcall(tostring,false) ) +print( 'tostring(tostring)', type(tostring(tostring)) ) +print( 'tostring(function() end)', type(tostring(function() end)) ) +print( 'tostring({"one","two",a="aa",b="bb"})', type(tostring({"one","two",a="aa",b="bb"})) ) + +-- unpack +print( 'pcall(unpack)', pcall(unpack) ); +print( 'pcall(unpack,nil)', pcall(unpack,nil) ); +print( 'pcall(unpack,"abc")', pcall(unpack,"abc") ); +print( 'pcall(unpack,1)', pcall(unpack,1) ); +print( 'unpack({"aa"})', unpack({"aa"}) ); +print( 'unpack({"aa","bb"})', unpack({"aa","bb"}) ); +print( 'unpack({"aa","bb","cc"})', unpack({"aa","bb","cc"}) ); +local t = {"aa","bb","cc","dd","ee","ff"} +print( 'pcall(unpack,t)', pcall(unpack,t) ); +print( 'pcall(unpack,t,2)', pcall(unpack,t,2) ); +print( 'pcall(unpack,t,2,5)', pcall(unpack,t,2,5) ); +print( 'pcall(unpack,t,2,6)', pcall(unpack,t,2,6) ); +print( 'pcall(unpack,t,2,7)', pcall(unpack,t,2,7) ); +print( 'pcall(unpack,t,1)', pcall(unpack,t,1) ); +print( 'pcall(unpack,t,1,5)', pcall(unpack,t,1,5) ); +print( 'pcall(unpack,t,1,6)', pcall(unpack,t,1,6) ); +print( 'pcall(unpack,t,1,7)', pcall(unpack,t,1,7) ); +print( 'pcall(unpack,t,0)', pcall(unpack,t,0) ); +print( 'pcall(unpack,t,0,5)', pcall(unpack,t,0,5) ); +print( 'pcall(unpack,t,0,6)', pcall(unpack,t,0,6) ); +print( 'pcall(unpack,t,0,7)', pcall(unpack,t,0,7) ); +print( 'pcall(unpack,t,-1)', pcall(unpack,t,-1) ); +print( 'pcall(unpack,t,-1,5)', pcall(unpack,t,-1,5) ); +print( 'pcall(unpack,t,-1,6)', pcall(unpack,t,-1,6) ); +print( 'pcall(unpack,t,-1,7)', pcall(unpack,t,-1,7) ); +print( 'pcall(unpack,t,2,4)', pcall(unpack,t,2,4) ); +print( 'pcall(unpack,t,2,5)', pcall(unpack,t,2,5) ); +print( 'pcall(unpack,t,2,6)', pcall(unpack,t,2,6) ); +print( 'pcall(unpack,t,2,7)', pcall(unpack,t,2,7) ); +print( 'pcall(unpack,t,2,8)', pcall(unpack,t,2,8) ); +print( 'pcall(unpack,t,2,2)', pcall(unpack,t,2,0) ); +print( 'pcall(unpack,t,2,1)', pcall(unpack,t,2,0) ); +print( 'pcall(unpack,t,2,0)', pcall(unpack,t,2,0) ); +print( 'pcall(unpack,t,2,-1)', pcall(unpack,t,2,-1) ); +t[0] = 'zz' +t[-1] = 'yy' +t[-2] = 'xx' +print( 'pcall(unpack,t,0)', pcall(unpack,t,0) ); +print( 'pcall(unpack,t,2,0)', pcall(unpack,t,2,0) ); +print( 'pcall(unpack,t,2,-1)', pcall(unpack,t,2,-1) ); +print( 'pcall(unpack,t,"3")', pcall(unpack,t,"3") ); +print( 'pcall(unpack,t,"a")', pcall(unpack,t,"a") ); +print( 'pcall(unpack,t,function() end)', pcall(unpack,t,function() end) ); + +-- _VERSION +print( '_VERSION', type(_VERSION) ) + +-- xpcall +local errfunc = function( detail ) + print( ' in errfunc', type(detail) ) + return 'response-from-xpcall' +end +local badfunc = function() error( 'error-from-badfunc' ) end +local wrappedbad = function() pcall( badfunc ) end +print( 'pcall(badfunc)', pcall(badfunc) ) +print( 'pcall(badfunc,errfunc)', pcall(badfunc,errfunc) ) +print( 'pcall(badfunc,badfunc)', pcall(badfunc,badfunc) ) +print( 'pcall(wrappedbad)', pcall(wrappedbad) ) +print( 'pcall(wrappedbad,errfunc)', pcall(wrappedbad,errfunc) ) +print( 'pcall(xpcall(badfunc))', pcall(xpcall,badfunc) ) +print( 'pcall(xpcall(badfunc,errfunc))', pcall(xpcall,badfunc,errfunc) ) +print( 'pcall(xpcall(badfunc,badfunc))', pcall(xpcall,badfunc,badfunc) ) +print( 'pcall(xpcall(wrappedbad))', pcall(xpcall,wrappedbad) ) +print( 'xpcall(wrappedbad,errfunc)', xpcall(wrappedbad,errfunc) ) + diff --git a/luaj-2.0.3/test/lua/coroutinelib.lua b/luaj-2.0.3/test/lua/coroutinelib.lua new file mode 100644 index 0000000000..31e3934eb7 --- /dev/null +++ b/luaj-2.0.3/test/lua/coroutinelib.lua @@ -0,0 +1,125 @@ +function printrunning() + if coroutine.running() == nil then + print("running is nil"); + else + print("running is not nil") + end +end + +function foo (a) + print("foo", a) + return coroutine.yield(2*a) +end + +co = coroutine.create(function (a,b) + print("co-body", a, b) + local r = foo(a+1) + print("co-body", r) + local r, s = coroutine.yield(a+b, a-b) + print("co-body", r, s) + + printrunning() + print("co.status.inside",coroutine.status(co)); + local co2 = coroutine.create(function() + print("co.status.inside2",coroutine.status(co)); + end) + print("co.status.inside",coroutine.status(co)); + coroutine.resume(co2); + + return b, "end" +end) + +function exercise() + printrunning() + print("co.status",coroutine.status(co)); + print("main", coroutine.resume(co, 1, 10)) + print("co.status",coroutine.status(co)); + print("main", coroutine.resume(co, "r")) + print("co.status",coroutine.status(co)); + print("main", coroutine.resume(co, "x", "y")) + print("co.status",coroutine.status(co)); + print("main", coroutine.resume(co, "x", "y")) + print("co.status",coroutine.status(co)); +end + +exercise(); + +co = coroutine.create(function (a,b) + print("co-body", a, b) +-- TODO: make java and C behave the same for yielding in pcalls +-- local status,r = pcall( foo, a+1 ) +foo(a+1) + print("co-body", status,r) + local r, s = coroutine.yield(a+b, a-b) + print("co-body", r, s) + return b, "end" +end) + +exercise(); + + +-- wrap test +local g = coroutine.wrap(function (a,b) + print("co-body", a, b) + local r = foo(a+1) + print("co-body", r) + local r, s = coroutine.yield(a+b, a-b) + print("co-body", r, s) + return b, "end" +end ) + +print("g", g(1, 10)) +print("g", g("r")) +print("g", g("x", "y")) +local s,e = pcall( g, "x", "y" ) +print("g", string.match(e,'cannot resume dead coroutine') or 'badmessage: '..tostring(e)) + +-- varargs passing +local echo = function(msg,...) + print( msg, ...) + return ... +end +local echocr = function(...) + echo('(echocr) first args', unpack(arg,1,arg.n)) + local a = arg + while true do + a = { echo( '(echoch) yield returns', coroutine.yield( unpack(a) ) ) } + end +end +local c = coroutine.create( echocr ) +local step = function(...) + echo( '(main) resume returns', + coroutine.resume(c, echo('(main) sending args', ...)) ) +end +step(111,222,333) +step() +step(111) +step(111,222,333) + +-- test loops in resume calls +b = coroutine.create( function( arg ) + while ( true ) do + print( ' b-resumed', arg, b == coroutine.running() ) + print( ' b-b', coroutine.status(b) ) + print( ' b-c', coroutine.status(c) ) + print( ' b-resume-b',coroutine.resume( b, 'b-arg-for-b' ) ) + print( ' b-resume-c',coroutine.resume( c, 'b-arg-for-c' ) ) + arg = coroutine.yield( 'b-rslt' ) + end +end ) +c = coroutine.create( function( arg ) + for i=1,3 do + print( ' c-resumed', arg, c == coroutine.running() ) + print( ' c-b', coroutine.status(b) ) + print( ' c-c', coroutine.status(c) ) + print( ' c-resume-b',coroutine.resume( b, 'b-arg-for-b' ) ) + print( ' c-resume-c',coroutine.resume( c, 'b-arg-for-c' ) ) + arg = coroutine.yield( 'c-rslt' ) + end +end ) +for i=1,3 do + print( 'main-b', coroutine.status(b) ) + print( 'main-c', coroutine.status(c) ) + print( 'main-resume-b',coroutine.resume( b, 'main-arg-for-b' ) ) + print( 'main-resume-c',coroutine.resume( c, 'main-arg-for-c' ) ) +end diff --git a/luaj-2.0.3/test/lua/debuglib.lua b/luaj-2.0.3/test/lua/debuglib.lua new file mode 100644 index 0000000000..b858d98a58 --- /dev/null +++ b/luaj-2.0.3/test/lua/debuglib.lua @@ -0,0 +1,232 @@ + +local print,tostring,_G,pcall,ipairs,isnumber = print,tostring,_G,pcall,ipairs,isnumber +local e,f,g,h,s +print( 'has debug', debug~=nil ) +if not debug then error( 'no debug' ) end + +print( '----- debug.getfenv, debug.setfenv' ) +f = function(a) + return 'f:'..tostring(a)..'|'..tostring(b) +end +s,e,g = pcall( debug.getfenv, f ) +print( s, type(e), type(g), (e==G), pcall( f, 'abc' ) ) +s,e,g = pcall( debug.setfenv, f, {b='def'} ) +print( s, type(e), type(g), (e==G), pcall( f, 'abc' ) ) +s,e,g = pcall( debug.getfenv, f ) +print( s, type(e), type(g), (e==G), pcall( f, 'abc' ) ) + + +print( '----- debug.getlocal, debug.setlocal' ) +h = function(v,i,n) + s = 'h-'..v..'-'..i + local x1,y1 = debug.getlocal(v,i) + local x2,y2 = debug.setlocal(v,i,n) + local x3,y3 = debug.getlocal(v,i) + return s..' -> '..v..'-'..i..' '.. + 'get='..tostring(x1)..','..tostring(y1)..' '.. + 'set='..tostring(x2)..','..tostring(y2)..' '.. + 'get='..tostring(x3)..','..tostring(y3)..' ' +end +g = function(...) + local p,q,r=7,8,9 + local t = h(...) + local b = table.concat({...},',') + return t..'\tg locals='..p..','..q..','..r..' tbl={'..b..'}' +end +f = function(a,b,c) + local d,e,f = 4,5,6 + local t = g(a,b,c) + return t..'\tf locals='..','..a..','..b..','..c..','..d..','..e..','..f +end +for lvl=3,2,-1 do + for lcl=0,7 do + print( pcall( f, lvl, lcl, '#' ) ) + end +end +for lvl=1,1 do + for lcl=3,7 do + print( pcall( f, lvl, lcl, '#' ) ) + end +end + + +print( '----- debug.getupvalue, debug.setupvalue' ) +local m,n,o = 101,102,103 +f = function(p,q,r) + local p,q,r = 104,105,106 + local g = function(s,t,u) + local v,w,x = 107,108,109 + return function() + return m,n,o,p,q,r,v,w,x + end + end + return g +end +g = f() +h = g() +local callh = function() + local t = {} + for i,v in ipairs( { pcall(h) } ) do + t[i] = tostring(v) + end + return table.concat(t,',') +end +print( 'h', h() ) +local funs = { f, g, h } +local names = { 'f', 'g', 'h' } +for i=1,3 do + local fun,name = funs[i],names[i] + for index=0,10 do + local s1,x1,y1 = pcall( debug.getupvalue, fun, index ) + local s2,x2,y2 = pcall( debug.setupvalue, fun, index, 666000+i*111000+index ) + local s3,x3,y3 = pcall( debug.getupvalue, fun, index ) + print( name..' -> '..i..'-'..index..' '.. + 'get='..tostring(s1)..','..tostring(x1)..','..tostring(y1)..' '.. + 'set='..tostring(s2)..','..tostring(x2)..','..tostring(y2)..' '.. + 'get='..tostring(s3)..','..tostring(x3)..','..tostring(y3)..' '.. + 'tbl='..callh() ) + end +end + +print( '----- debug.setmetatable, debug.getmetatable' ) +local a = {a='bbb'} +local b = {} +local mt = {__index={b='ccc'}} +print( 'a.a='..tostring(a.a)..' a.b='..tostring(a.b)..' b.a='..tostring(b.a)..' b.b='..tostring(b.b)) +local s1,x1,y1 = pcall( debug.getmetatable, a ) +local s2,x2,y2 = pcall( debug.setmetatable, a, mt ) +print( 'a.a='..tostring(a.a)..' a.b='..tostring(a.b)..' b.a='..tostring(b.a)..' b.b='..tostring(b.b)) +local s3,x3,y3 = pcall( debug.getmetatable, a ) +local s4,x4,y4 = pcall( debug.getmetatable, b ) +local s5,x5,y5 = pcall( debug.setmetatable, a, nil ) +print( 'a.a='..tostring(a.a)..' a.b='..tostring(a.b)..' b.a='..tostring(b.a)..' b.b='..tostring(b.b)) +local s6,x6,y6 = pcall( debug.getmetatable, a ) +if not s1 then print( 's1 error', x1 ) end +if not s2 then print( 's2 error', x2 ) end +if not s3 then print( 's3 error', x3 ) end +if not s4 then print( 's4 error', x4 ) end +if not s5 then print( 's5 error', x5 ) end +if not s6 then print( 's6 error', x6 ) end +print( 'get='..tostring(s1)..','..tostring(x1==nil)..','..tostring(y1) ) +print( 'set='..tostring(s2)..','..tostring(x2==a)..','..tostring(y2) ) +print( 'get='..tostring(s3)..','..tostring(x3==mt)..','..tostring(y3) ) +print( 'get='..tostring(s4)..','..tostring(x4==nil)..','..tostring(y4) ) +print( 'set='..tostring(s5)..','..tostring(x5==a)..','..tostring(y5) ) +print( 'get='..tostring(s6)..','..tostring(x6==nil)..','..tostring(y6) ) +print( pcall( debug.getmetatable, 1 ) ) +print( pcall( debug.setmetatable, 1, {} ) ) +print( pcall( debug.setmetatable, 1, nil ) ) + +print( '----- debug.getinfo' ) +local printfield = function(tbl, field) + local x = tbl[field] + if x == nil then return end + local typ = type(x) + if typ=='table' then + x = '{'..table.concat(x,',')..'}' + elseif typ=='function' then + x = typ + end + print( ' '..field..': '..tostring(x) ) +end +local fields = { 'source', 'short_src', 'what', + 'currentline', 'linedefined', 'lastlinedefined', + 'nups', 'func', 'activelines' } +local printinfo = function(...) + for i,a in ipairs(arg) do + if type(a) == 'table' then + for j,field in ipairs(fields) do + printfield( a, field) + end + else + print( tostring(a) ) + end + end +end +function test() + local x = 5 + function f() + x = x + 1 + return x + end + function g() + x = x - 1 + print( '---' ) + printinfo( 'debug.getinfo(1)', debug.getinfo(1) ) + printinfo( 'debug.getinfo(1,"")', debug.getinfo(1, "") ) + printinfo( 'debug.getinfo(1,"l")', debug.getinfo(1, "l") ) + printinfo( 'debug.getinfo(1,"fL")', debug.getinfo(1, "fL") ) + printinfo( 'debug.getinfo(2)', debug.getinfo(2) ) + printinfo( 'debug.getinfo(2,"l")', debug.getinfo(2, "l") ) + printinfo( 'debug.getinfo(2,"fL")', debug.getinfo(2, "fL") ) + printinfo( 'debug.getinfo(10,"")', pcall( debug.getinfo, 10, "" ) ) + printinfo( 'debug.getinfo(-10,"")', pcall( debug.getinfo, -10, "" ) ) + --[[ + for i=1,3 do + printinfo( 'debug.traceback("msg")', debug.traceback('msg') ) + printinfo( 'debug.traceback("another",'..i..')', debug.traceback('another',i) ) + end + --]] + print( '---' ) + return x + end + print(f()) + print(g()) + return f, g +end + +local options = "nSlufL" +local e,f,g = pcall( test ) +print( 'e,f,g', e, type(f), type(g) ) +printinfo( 'debug.getinfo(f)', pcall(debug.getinfo, f) ) +printinfo( 'debug.getinfo(f,"'..options..'")', pcall(debug.getinfo, f, options) ) +for j=1,6 do + local opts = options:sub(j,j) + printinfo( 'debug.getinfo(f,"'..opts..'")', pcall(debug.getinfo, f, opts) ) +end +printinfo( 'debug.getinfo(g)', pcall(debug.getinfo, g) ) +printinfo( 'debug.getinfo(test)', pcall(debug.getinfo, test) ) + +print( '----- debug.sethook, debug.gethook' ) +f = function(x) + g = function(y) + return math.min(x,h) + end + local a = g(x) + return a + a +end +local hook = function(...) + print( ' ... in hook', ... ) + local info = debug.getinfo(2,"Sl") + if info then + print( ' info[2]='..tostring(info.short_src)..','..tostring(info.currentline) ) + end +end +local tryfunc = function(hook,mask,func,arg) + local x,f,h,m + pcall( function() + debug.sethook(hook,mask) + x = func(arg) + f,h,m = debug.gethook() + end ) + debug.sethook() + return x,f,h,m +end + +local tryhooks = function(mask) + local s1,a1,b1,c1,d1 = pcall( tryfunc, hook, mask, f, 333 ) + print( 'hook = '..mask..' -> '.. + 'result='..tostring(s1)..','..tostring(a1)..','.. + type(b1)..','..type(c1)..','.. + tostring(b1==f)..','..tostring(c1==hook)..','.. + tostring(d1)..' ' ) +end + +--[[ +tryhooks("c") +tryhooks("r") +tryhooks("l") +tryhooks("crl") +--]] + + \ No newline at end of file diff --git a/luaj-2.0.3/test/lua/errors.lua b/luaj-2.0.3/test/lua/errors.lua new file mode 100644 index 0000000000..3ed06c2e99 --- /dev/null +++ b/luaj-2.0.3/test/lua/errors.lua @@ -0,0 +1,137 @@ +-- tostring replacement that assigns ids +local ts,id,nid,types = tostring,{},0,{table='tbl',thread='thr',userdata='uda',['function']='func'} +tostring = function(x) + if not x or not types[type(x)] then return ts(x) end + if not id[x] then nid=nid+1; id[x]=types[type(x)]..'.'..nid end + return id[x] +end + +-- test of common types of errors +-- local function c(f,...) return f(...) end +-- local function b(...) return c(...) end +--local function a(...) return (pcall(b,...)) end +local function a(...) local s,e=pcall(...) if s then return s,e else return false,type(e) end end +s = 'some string' +local t = {} +-- error message tests +print( 'a(error)', a(error) ) +print( 'a(error,"msg")', a(error,"msg") ) +print( 'a(error,"msg",0)', a(error,"msg",0) ) +print( 'a(error,"msg",1)', a(error,"msg",1) ) +print( 'a(error,"msg",2)', a(error,"msg",2) ) +print( 'a(error,"msg",3)', a(error,"msg",3) ) +print( 'a(error,"msg",4)', a(error,"msg",4) ) +print( 'a(error,"msg",5)', a(error,"msg",5) ) +print( 'a(error,"msg",6)', a(error,"msg",6) ) + +-- call errors +print( 'a(nil())', a(function() return n() end) ) +print( 'a(t()) ', a(function() return t() end) ) +print( 'a(s()) ', a(function() return s() end) ) +print( 'a(true())', a(function() local b = true; return b() end) ) + +-- arithmetic errors +print( 'a(nil+1)', a(function() return nil+1 end) ) +print( 'a(a+1) ', a(function() return a+1 end) ) +print( 'a(s+1) ', a(function() return s+1 end) ) +print( 'a(true+1)', a(function() local b = true; return b+1 end) ) + +-- table errors +print( 'a(nil.x)', a(function() return n.x end) ) +print( 'a(a.x) ', a(function() return a.x end) ) +print( 'a(s.x) ', a(function() return s.x end) ) +print( 'a(true.x)', a(function() local b = true; return b.x end) ) +print( 'a(nil.x=5)', a(function() n.x=5 end) ) +print( 'a(a.x=5) ', a(function() a.x=5 end) ) +print( 'a(s.x=5) ', a(function() s.x=5 end) ) +print( 'a(true.x=5)', a(function() local b = true; b.x=5 end) ) + +-- len operator +print( 'a(#nil) ', a(function() return #n end) ) +print( 'a(#t) ', a(function() return #t end) ) +print( 'a(#s) ', a(function() return #s end) ) +print( 'a(#a) ', a(function() return #a end) ) +print( 'a(#true)', a(function() local b = true; return #b end) ) + +-- comparison errors +print( 'a(nil>1)', a(function() return nil>1 end) ) +print( 'a(a>1) ', a(function() return a>1 end) ) +print( 'a(s>1) ', a(function() return s>1 end) ) +print( 'a(true>1)', a(function() local b = true; return b>1 end) ) + +-- unary minus errors +print( 'a(-nil)', a(function() return -n end) ) +print( 'a(-a) ', a(function() return -a end) ) +print( 'a(-s) ', a(function() return -s end) ) +print( 'a(-true)', a(function() local b = true; return -b end) ) + +-- string concatenation +local function concatsuite(comparefunc) + print( '"a".."b"', comparefunc("a","b") ) + print( '"a"..nil', comparefunc("a",nil) ) + print( 'nil.."b"', comparefunc(nil,"b") ) + print( '"a"..{}', comparefunc("a",{}) ) + print( '{}.."b"', comparefunc({},"b") ) + print( '"a"..2', comparefunc("a",2) ) + print( '2.."b"', comparefunc(2,"b") ) + print( '"a"..print', comparefunc("a",print) ) + print( 'print.."b"', comparefunc(print,"b") ) + print( '"a"..true', comparefunc("a",true) ) + print( 'true.."b"', comparefunc(true,"b") ) + print( 'nil..true', comparefunc(nil,true) ) + print( '"a"..3.5', comparefunc("a",3.5) ) + print( '3.5.."b"', comparefunc(3.5,"b") ) +end +local function strconcat(a,b) + return (pcall( function() return a..b end) ) +end +local function tblconcat(a,b) + local t={a,b} + return (pcall( function() return table.concat(t,'-',1,2) end )) +end + +print( '-------- string concatenation' ) +concatsuite(strconcat) +print( '-------- table concatenation' ) +concatsuite(tblconcat) + +-- pairs +print( '-------- pairs tests' ) +print( 'a(pairs(nil))', a(function() return pairs(nil,{}) end) ) +print( 'a(pairs(a)) ', a(function() return pairs(a,{}) end) ) +print( 'a(pairs(s)) ', a(function() return pairs(s,{}) end) ) +print( 'a(pairs(t)) ', a(function() return pairs(t,{}) end) ) +print( 'a(pairs(true))', a(function() local b = true; return pairs(b,{}) end) ) + +-- setmetatable +print( '-------- setmetatable tests' ) +function sm(...) + return tostring(setmetatable(...)) +end +print( 'a(setmetatable(nil))', a(function() return sm(nil,{}) end) ) +print( 'a(setmetatable(a)) ', a(function() return sm(a,{}) end) ) +print( 'a(setmetatable(s)) ', a(function() return sm(s,{}) end) ) +print( 'a(setmetatable(true))', a(function() local b = true; return sm(b,{}) end) ) +print( 'a(setmetatable(t)) ', a(function() return sm(t,{}) end) ) +print( 'a(getmetatable(t)) ', a(function() return getmetatable(t),type(getmetatable(t)) end) ) +print( 'a(setmetatable(t*)) ', a(function() return sm(t,{__metatable={}}) end) ) +print( 'a(getmetatable(t)) ', a(function() return getmetatable(t),type(getmetatable(t)) end) ) +print( 'a(setmetatable(t)) ', a(function() return sm(t,{}) end) ) +print( 'a(getmetatable(t)) ', a(function() return getmetatable(t),type(getmetatable(t)) end) ) +t = {} +print( 'a(setmetatable(t)) ', a(function() return sm(t,{}) end) ) +print( 'a(getmetatable(t)) ', a(function() return getmetatable(t),type(getmetatable(t)) end) ) +print( 'a(setmetatable(t*)) ', a(function() return sm(t,{__metatable='some string'}) end) ) +print( 'a(getmetatable(t)) ', a(function() return getmetatable(t),type(getmetatable(t)) end) ) +print( 'a(setmetatable(t)) ', a(function() return sm(t,{}) end) ) +print( 'a(getmetatable(t)) ', a(function() return getmetatable(t),type(getmetatable(t)) end) ) +print( 'a(setmetatable(t,nil)) ', a(function() return sm(t,nil) end) ) +print( 'a(setmetatable(t)) ', a(function() return sm(t) end) ) +print( 'a(setmetatable({},"abc")) ', a(function() return sm({},'abc') end) ) + +-- bad args to error! +print( 'error("msg","arg")', a(function() error('some message', 'some bad arg') end) ) + +-- loadfile, dofile on missing files +print( 'loadfile("bogus.txt")', a(function() return loadfile("bogus.txt") end) ) +print( 'dofile("bogus.txt")', a(function() return dofile("bogus.txt") end) ) diff --git a/luaj-2.0.3/test/lua/errors/args.lua b/luaj-2.0.3/test/lua/errors/args.lua new file mode 100644 index 0000000000..eafdabf0f8 --- /dev/null +++ b/luaj-2.0.3/test/lua/errors/args.lua @@ -0,0 +1,197 @@ +-- utilities to check that args of various types pass or fail +-- argument type checking +local ok = '-\t' +local fail = 'fail ' +local needcheck = 'needcheck ' +local badmsg = 'badmsg ' + +akey = 'aa' +astring = 'abc' +astrnum = '789' +anumber = 1.25 +ainteger = 345 +adouble = 12.75 +aboolean = true +atable = {[akey]=456} +afunction = function() end +anil = nil +athread = coroutine.create(afunction) + +anylua = { nil, astring, anumber, aboolean, atable, afunction, athread } + +somestring = { astring, anumber } +somenumber = { anumber, astrnum } +someboolean = { aboolean } +sometable = { atable } +somefunction = { afunction } +somenil = { anil } +somekey = { akey } +notakey = { astring, anumber, aboolean, atable, afunction } + +notastring = { nil, aboolean, atable, afunction, athread } +notanumber = { nil, astring, aboolean, atable, afunction, athread } +notaboolean = { nil, astring, anumber, atable, afunction, athread } +notatable = { nil, astring, anumber, aboolean, afunction, athread } +notafunction = { nil, astring, anumber, aboolean, atable, athread } +notathread = { nil, astring, anumber, aboolean, atable, afunction } +notanil = { astring, anumber, aboolean, atable, afunction, athread } + +nonstring = { aboolean, atable, afunction, athread } +nonnumber = { astring, aboolean, atable, afunction, athread } +nonboolean = { astring, anumber, atable, afunction, athread } +nontable = { astring, anumber, aboolean, afunction, athread } +nonfunction = { astring, anumber, aboolean, atable, athread } +nonthread = { astring, anumber, aboolean, atable, afunction } +nonkey = { astring, anumber, aboolean, atable, afunction } + +local structtypes = { + ['table']='', + ['function']='', + ['thread']='', + ['userdata']='', +} + +local function bracket(v) + return "<"..type(v)..">" +end + +local function quote(v) + return "'"..v.."'" +end + +local function ellipses(v) + local s = tostring(v) + return #s <= 8 and s or (string.sub(s,1,8)..'...') +end + +local pretty = { + ['table']=bracket, + ['function']=bracket, + ['thread']=bracket, + ['userdata']=bracket, + ['string']= quote, + ['number']= ellipses, +} + +local function values(list) + local t = {} + for i=1,(list.n or #list) do + local ai = list[i] + local fi = pretty[type(ai)] + t[i] = fi and fi(ai) or tostring(ai) + end + return table.concat(t,',') +end + +local function types(list) + local t = {} + for i=1,(list.n or #list) do + local ai = list[i] + t[i] = type(ai) + end + return table.concat(t,',') +end + +local function signature(name,arglist) + return name..'('..values(arglist)..')' +end + +local function dup(t) + local s = {} + for i=1,(t.n or #t) do + s[i] = t[i] + end + return s +end + +local function split(t) + local s = {} + local n = (t.n or #t) + for i=1,n-1 do + s[i] = t[i] + end + return s,t[n] +end + +local function expand(argsets, typesets, ...) + local n = typesets and #typesets or 0 + if n <= 0 then + table.insert(argsets,arg) + return argsets + end + + local s,v = split(typesets) + for i=1,(v.n or #v) do + expand(argsets, s, v[i], unpack(arg,1,arg.n)) + end + return argsets +end + +local function arglists(typesets) + local argsets = expand({},typesets) + return ipairs(argsets) +end + +function lookup( name ) + return loadstring('return '..name)() +end + +function invoke( name, arglist ) + local s,c = pcall(lookup, name) + if not s then return s,c end + return pcall(c, unpack(arglist,1,arglist.n or #arglist)) +end + +-- messages, banners +local _print = print +local _tostring = tostring +local _find = string.find +function banner(name) + _print( '====== '.._tostring(name)..' ======' ) +end + +local function subbanner(name) + _print( '--- '.._tostring(name) ) +end + +local function pack(s,...) + return s,arg +end + +-- check that all combinations of arguments pass +function checkallpass( name, typesets, typesonly ) + subbanner('checkallpass') + for i,v in arglists(typesets) do + local sig = signature(name,v) + local s,r = pack( invoke( name, v ) ) + if s then + if typesonly then + _print( ok, sig, types(r) ) + else + _print( ok, sig, values(r) ) + end + else + _print( fail, sig, values(r) ) + end + end +end + +-- check that all combinations of arguments fail in some way, +-- ignore error messages +function checkallerrors( name, typesets, template ) + subbanner('checkallerrors') + template = _tostring(template) + for i,v in arglists(typesets) do + local sig = signature(name,v) + local s,e = invoke( name, v ) + if not s then + if _find(e, template, 1, true) then + _print( ok, sig, '...'..template..'...' ) + else + _print( badmsg, sig, "template='"..template.."' actual='"..e.."'" ) + end + else + _print( needcheck, sig, e ) + end + end +end diff --git a/luaj-2.0.3/test/lua/errors/baselibargs.lua b/luaj-2.0.3/test/lua/errors/baselibargs.lua new file mode 100644 index 0000000000..6a0d23492c --- /dev/null +++ b/luaj-2.0.3/test/lua/errors/baselibargs.lua @@ -0,0 +1,171 @@ +package.path = "?.lua;test/lua/errors/?.lua" +require 'args' + +-- arg types for basic library functions + +-- assert +banner('assert') +checkallpass('assert',{{true,123},anylua}) +checkallerrors('assert',{{nil,false,n=2},{nil,n=1}},'assertion failed') +checkallerrors('assert',{{nil,false,n=2},{'message'}},'message') + +-- collectgarbage +banner('collectgarbage') +checkallpass('collectgarbage',{{'collect','count'}},true) +checkallerrors('collectgarbage',{{astring, anumber}},'bad argument') +checkallerrors('collectgarbage',{{aboolean, atable, afunction, athread}},'string expected') + +-- dofile +banner('dofile') +--checkallpass('dofile', {}) +checkallpass('dofile', {{'args.lua'}}) +checkallerrors('dofile', {{'foo.bar'}}, 'cannot open foo.bar') +checkallerrors('dofile', {nonstring}, 'bad argument') + +-- error +banner('error') +checkallerrors('error', {{'message'},{nil,0,1,2,n=4}}, 'message') +checkallerrors('error', {{123},{nil,1,2,n=3}}, 123) + +-- getfenv +banner('getfenv') +checkallpass('getfenv', {{nil,print,function()end,0,1,2,n=5}}) +checkallerrors('getfenv', {{true,{},'abc'}}, 'bad argument') + +-- getmetatable +banner('getmetatable') +checkallpass('getmetatable', {notanil}) +checkallerrors('getmetatable',{},'bad argument') + +-- ipairs +banner('ipairs') +checkallpass('ipairs', {sometable}) +checkallerrors('ipairs', {notatable}, 'bad argument') + +-- load +banner('load') +checkallpass('load', {somefunction,{nil,astring,n=2}}) +checkallerrors('load', {notafunction,{nil,astring,anumber,n=3}}, 'bad argument') +checkallerrors('load', {somefunction,{afunction,atable}}, 'bad argument') + +-- loadfile +banner('loadfile') +--checkallpass('loadfile', {}) +checkallpass('loadfile', {{'bogus'}}) +checkallpass('loadfile', {{'test/lua/errors/args.lua'}}) +checkallpass('loadfile', {{'args.lua'}}) +checkallerrors('loadfile', {nonstring}, 'bad argument') + +-- loadstring +banner('loadstring') +checkallpass('loadstring', {{'return'}}) +checkallpass('loadstring', {{'return'},{'mychunk'}}) +checkallpass('loadstring', {{'return a ... b'},{'mychunk'}},true) +checkallerrors('loadstring', {notastring,{nil,astring,anumber,n=3}}, 'bad argument') +checkallerrors('loadstring', {{'return'},{afunction,atable}}, 'bad argument') + +-- next +banner('next') +checkallpass('next', {sometable,somekey}) +checkallerrors('next', {notatable,{nil,1,n=2}}, 'bad argument') +checkallerrors('next', {sometable,nonkey}, 'invalid key') + +-- pairs +banner('pairs') +checkallpass('pairs', {sometable}) +checkallerrors('pairs', {notatable}, 'bad argument') + +-- pcall +banner('pcall') +checkallpass('pcall', {notanil,anylua}, true) +checkallerrors('pcall',{},'bad argument') + +-- print +banner('print') +checkallpass('print', {}) +checkallpass('print', {{nil,astring,anumber,aboolean,n=4}}) + +-- rawequal +banner('rawequal') +checkallpass('rawequal', {notanil,notanil}) +checkallerrors('rawequal', {}, 'bad argument') +checkallerrors('rawequal', {notanil}, 'bad argument') + +-- rawget +banner('rawget') +checkallpass('rawget', {sometable,somekey}) +checkallpass('rawget', {sometable,nonkey}) +checkallerrors('rawget', {sometable,somenil},'bad argument') +checkallerrors('rawget', {notatable,notakey}, 'bad argument') +checkallerrors('rawget', {}, 'bad argument') + +-- rawset +banner('rawset') +checkallpass('rawset', {sometable,somekey,notanil}) +checkallpass('rawset', {sometable,nonkey,notanil}) +checkallerrors('rawset', {sometable,somenil},'table index is nil') +checkallerrors('rawset', {}, 'bad argument') +checkallerrors('rawset', {notatable,somestring,somestring}, 'bad argument') +checkallerrors('rawset', {sometable,somekey}, 'bad argument') + +-- select +banner('select') +checkallpass('select', {{anumber,'#'},anylua}) +checkallerrors('select', {notanumber}, 'bad argument') + +-- setfenv +banner('setfenv') +local g = _G +checkallpass('setfenv', {{function()end},sometable}) +checkallerrors('setfenv', {{-1, '-2'},{g}}, 'level must be non-negative') +checkallerrors('setfenv', {{10, '11'},{g}}, 'invalid level') +checkallerrors('setfenv', {{rawset},{g}}, 'cannot change environment of given object') +checkallerrors('setfenv', {{atable,athread,aboolean,astring},{g}}, 'bad argument') +checkallerrors('setfenv', {notafunction}, 'bad argument') +checkallerrors('setfenv', {anylua}, 'bad argument') +checkallerrors('setfenv', {{function()end},notatable}, 'bad argument') + +-- setmetatable +banner('setmetatable') +checkallpass('setmetatable', {sometable,sometable}) +checkallpass('setmetatable', {sometable,{}}) +checkallerrors('setmetatable',{notatable,sometable},'bad argument') +checkallerrors('setmetatable',{sometable,nontable},'bad argument') + +-- tonumber +banner('tonumber') +checkallpass('tonumber',{somenumber,{nil,2,10,36,n=4}}) +checkallpass('tonumber',{notanil,{nil,10,n=2}}) +checkallerrors('tonumber',{{nil,afunction,atable,n=3},{2,9,11,36}},'bad argument') +checkallerrors('tonumber',{somenumber,{1,37,atable,afunction,aboolean}},'bad argument') + +-- tostring +banner('tostring') +checkallpass('tostring',{{astring,anumber,aboolean}}) +checkallpass('tostring',{{atable,afunction,athread}},true) +checkallpass('tostring',{{astring,anumber,aboolean},{'anchor'}}) +checkallpass('tostring',{{atable,afunction,athread},{'anchor'}},true) +checkallerrors('tostring',{},'bad argument') + +-- type +banner('type') +checkallpass('type',{notanil}) +checkallpass('type',{anylua,{'anchor'}}) +checkallerrors('type',{},'bad argument') + +-- unpack +banner('unpack') +checkallpass('unpack',{sometable}) +checkallpass('unpack',{sometable,{3,'5'}}) +checkallpass('unpack',{sometable,{3,'5'},{1.25,'7'}}) +checkallerrors('unpack',{notatable,somenumber,somenumber},'bad argument') +checkallerrors('unpack',{sometable,nonnumber,somenumber},'bad argument') +checkallerrors('unpack',{sometable,somenumber,nonnumber},'bad argument') + +-- xpcall +banner('xpcall') +checkallpass('xpcall', {notanil,nonfunction}) +checkallpass('xpcall', {notanil,{function(...)return 'aaa', 'bbb', #{...} end}}) +checkallerrors('xpcall',{anylua},'bad argument') + + diff --git a/luaj-2.0.3/test/lua/errors/coroutinelibargs.lua b/luaj-2.0.3/test/lua/errors/coroutinelibargs.lua new file mode 100644 index 0000000000..caad62002b --- /dev/null +++ b/luaj-2.0.3/test/lua/errors/coroutinelibargs.lua @@ -0,0 +1,47 @@ +package.path = "?.lua;test/lua/errors/?.lua" +require 'args' + +-- arg type tests for coroutine library functions + +-- coroutine.create +banner('coroutine.create') +checkallpass('coroutine.create',{somefunction}) +checkallerrors('coroutine.create',{notafunction},'bad argument') + +-- coroutine.resume +banner('coroutine.resume') +local co = coroutine.create(function() while true do coroutine.yield() end end) +checkallpass('coroutine.resume',{{co},anylua}) +checkallerrors('coroutine.resume',{notathread},'bad argument') + +-- coroutine.running +banner('coroutine.running') +checkallpass('coroutine.running',{anylua}) + +-- coroutine.status +banner('coroutine.status') +checkallpass('coroutine.status',{{co}}) +checkallerrors('coroutine.status',{notathread},'bad argument') + +-- coroutine.wrap +banner('coroutine.wrap') +checkallpass('coroutine.wrap',{somefunction}) +checkallerrors('coroutine.wrap',{notafunction},'bad argument') + +-- coroutine.yield +banner('coroutine.yield') +local function f() + print( 'yield', coroutine.yield() ) + print( 'yield', coroutine.yield(astring,anumber,aboolean) ) + error('error within coroutine thread') +end +local co = coroutine.create( f ) +print( 'status', coroutine.status(co) ) +print( coroutine.resume(co,astring,anumber) ) +print( 'status', coroutine.status(co) ) +print( coroutine.resume(co,astring,anumber) ) +print( 'status', coroutine.status(co) ) +local s,e = coroutine.resume(co,astring,anumber) +print( s, string.match(e,'error within coroutine thread') or 'bad message: '..tostring(e) ) +print( 'status', coroutine.status(co) ) + diff --git a/luaj-2.0.3/test/lua/errors/iolibargs.lua b/luaj-2.0.3/test/lua/errors/iolibargs.lua new file mode 100644 index 0000000000..1f8a3ac44e --- /dev/null +++ b/luaj-2.0.3/test/lua/errors/iolibargs.lua @@ -0,0 +1,85 @@ +package.path = "?.lua;test/lua/errors/?.lua" +require 'args' + +-- arg type tests for io library functions +local f + +-- io.close ([file]) +banner('io.close') +f = io.open("abc.txt","w") +checkallpass('io.close',{{f}}) +checkallerrors('io.close',{notanil},'bad argument') + +-- io.input ([file]) +banner('io.input') +f = io.open("abc.txt","r") +checkallpass('io.input',{{nil,f,"abc.txt",n=3}}) +checkallerrors('io.input',{nonstring},'bad argument') + +-- io.lines ([filename]) +banner('io.lines') +io.input("abc.txt") +checkallpass('io.lines',{{"abc.txt"}}) +checkallerrors('io.lines',{{f}},'bad argument') +checkallerrors('io.lines',{notastring},'bad argument') + +-- io.open (filename [, mode]) +banner('io.open') +checkallpass('io.open',{{"abc.txt"},{nil,"r","w","a","r+","w+","a+"}}) +checkallerrors('io.open',{notastring},'bad argument') +checkallerrors('io.open',{{"abc.txt"},{nonstring}},'bad argument') + +-- io.output ([file]) +banner('io.output') +checkallpass('io.output',{{nil,f,"abc.txt",n=3}}) +checkallerrors('io.output',{nonstring},'bad argument') + +-- io.popen (prog [, mode]) +banner('io.popen') +--checkallpass('io.popen',{{"hostname"},{nil,"w",n=2}}) +checkallerrors('io.popen',{notastring},'bad argument') +checkallerrors('io.popen',{{"hostname"},{nonstring}},'bad argument') + +-- io.read (���) +banner('io.read') +checkallpass('io.read',{}) +checkallpass('io.read',{{2,"*n","*a","*l"}}) +checkallpass('io.read',{{2,"*n","*a","*l"},{2,"*a","*l"}}) +checkallerrors('io.read',{{aboolean,afunction,atable,"3"}},'bad argument') + +-- io.write (���) +banner('io.write') +checkallpass('io.write',{}) +checkallpass('io.write',{somestring}) +checkallpass('io.write',{somestring,somestring}) +checkallerrors('io.write',{nonstring},'bad argument') +checkallerrors('io.write',{somestring,nonstring},'bad argument') + +-- file:write () +banner('file:write') +file = io.open("seektest.txt","w") +checkallpass('file.write',{{file},somestring}) +checkallpass('file.write',{{file},somestring,somestring}) +checkallerrors('file.write',{},'bad argument') +checkallerrors('file.write',{{file},nonstring},'bad argument') +checkallerrors('file.write',{{file},somestring,nonstring},'bad argument') +pcall( file.close, file ) + +-- file:seek ([whence] [, offset]) +banner('file:seek') +file = io.open("seektest.txt","r") +checkallpass('file.seek',{{file}}) +checkallpass('file.seek',{{file},{"set","cur","end"}}) +checkallpass('file.seek',{{file},{"set","cur","end"},{2,"3"}}) +checkallerrors('file.seek',{},'bad argument') +checkallerrors('file.seek',{{file},nonstring},'bad argument') +checkallerrors('file.seek',{{file},{"set","cur","end"},nonnumber},'bad argument') + +-- file:setvbuf (mode [, size]) +banner('file:setvbuf') +checkallpass('file.setvbuf',{{file},{"no","full","line"}}) +checkallpass('file.setvbuf',{{file},{"full"},{1024,"512"}}) +checkallerrors('file.setvbuf',{},'bad argument') +checkallerrors('file.setvbuf',{{file},notastring},'bad argument') +checkallerrors('file.setvbuf',{{file},{"full"},nonnumber},'bad argument') + diff --git a/luaj-2.0.3/test/lua/errors/mathlibargs.lua b/luaj-2.0.3/test/lua/errors/mathlibargs.lua new file mode 100644 index 0000000000..2259461877 --- /dev/null +++ b/luaj-2.0.3/test/lua/errors/mathlibargs.lua @@ -0,0 +1,112 @@ +package.path = "?.lua;test/lua/errors/?.lua" +require 'args' + +local tostring = tostring +_G.tostring = function(x) + local s = tostring(x) + return type(x)=='number' and #s>4 and (s:sub(1,5)..'...') or s +end + +-- arg type tests for math library functions +local somenumber = {1,0.75,'-1','-0.25'} +local somepositive = {1,0.75,'2', '2.5'} +local notanumber = {nil,astring,aboolean,afunction,atable,athread} +local nonnumber = {astring,aboolean,afunction,atable} + +local singleargfunctions = { + 'abs', 'acos', 'asin', 'atan', 'cos', 'cosh', 'deg', 'exp', 'floor', + 'rad', 'randomseed', 'sin', 'sinh', 'tan', 'tanh', 'frexp', + } + +local singleargposdomain = { + 'log', 'log10', 'sqrt', 'ceil', + } + +local twoargfunctions = { + 'atan2', + } + +local twoargsposdomain = { + 'pow', 'fmod', +} + +-- single argument tests +for i,v in ipairs(singleargfunctions) do + local funcname = 'math.'..v + banner(funcname) + checkallpass(funcname,{somenumber}) + checkallerrors(funcname,{notanumber},'bad argument') +end + +-- single argument, positive domain tests +for i,v in ipairs(singleargposdomain) do + local funcname = 'math.'..v + banner(funcname) + checkallpass(funcname,{somepositive}) + checkallerrors(funcname,{notanumber},'bad argument') +end + +-- two-argument tests +for i,v in ipairs(twoargfunctions) do + local funcname = 'math.'..v + banner(funcname) + checkallpass(funcname,{somenumber,somenumber}) + checkallerrors(funcname,{},'bad argument') + checkallerrors(funcname,{notanumber},'bad argument') + checkallerrors(funcname,{notanumber,somenumber},'bad argument') + checkallerrors(funcname,{somenumber},'bad argument') + checkallerrors(funcname,{somenumber,notanumber},'bad argument') +end + +-- two-argument, positive domain tests +for i,v in ipairs(twoargsposdomain) do + local funcname = 'math.'..v + banner(funcname) + checkallpass(funcname,{somepositive,somenumber}) + checkallerrors(funcname,{},'bad argument') + checkallerrors(funcname,{notanumber},'bad argument') + checkallerrors(funcname,{notanumber,somenumber},'bad argument') + checkallerrors(funcname,{somenumber},'bad argument') + checkallerrors(funcname,{somenumber,notanumber},'bad argument') +end + +-- math.max +banner('math.max') +checkallpass('math.max',{somenumber}) +checkallpass('math.max',{somenumber,somenumber}) +checkallerrors('math.max',{},'bad argument') +checkallerrors('math.max',{nonnumber},'bad argument') +checkallerrors('math.max',{somenumber,nonnumber},'bad argument') + +-- math.min +banner('math.min') +checkallpass('math.min',{somenumber}) +checkallpass('math.min',{somenumber,somenumber}) +checkallerrors('math.min',{},'bad argument') +checkallerrors('math.min',{nonnumber},'bad argument') +checkallerrors('math.min',{somenumber,nonnumber},'bad argument') + +-- math.random +local somem = {3,4.5,'6.7'} +local somen = {8,9.10,'12.34'} +local notamn = {astring,aboolean,atable,afunction} +banner('math.random') +checkallpass('math.random',{},true) +checkallpass('math.random',{somem},true) +checkallpass('math.random',{somem,somen},true) +checkallpass('math.random',{{-4,-5.6,'-7','-8.9'},{-1,100,23.45,'-1.23'}},true) +checkallerrors('math.random',{{-4,-5.6,'-7','-8.9'}},'interval is empty') +checkallerrors('math.random',{somen,somem},'interval is empty') +checkallerrors('math.random',{notamn,somen},'bad argument') +checkallerrors('math.random',{somem,notamn},'bad argument') + +-- math.ldexp +local somee = {-3,0,3,9.10,'12.34'} +local notae = {nil,astring,aboolean,atable,afunction} +banner('math.ldexp') +checkallpass('math.ldexp',{somenumber,somee}) +checkallerrors('math.ldexp',{},'bad argument') +checkallerrors('math.ldexp',{notanumber},'bad argument') +checkallerrors('math.ldexp',{notanumber,somee},'bad argument') +checkallerrors('math.ldexp',{somenumber},'bad argument') +checkallerrors('math.ldexp',{somenumber,notae},'bad argument') \ No newline at end of file diff --git a/luaj-2.0.3/test/lua/errors/modulelibargs.lua b/luaj-2.0.3/test/lua/errors/modulelibargs.lua new file mode 100644 index 0000000000..711cc7c113 --- /dev/null +++ b/luaj-2.0.3/test/lua/errors/modulelibargs.lua @@ -0,0 +1,46 @@ +package.path = "?.lua;test/lua/errors/?.lua" +require 'args' + +-- arg type tests for module library functions + +-- require +banner('require') +checkallpass('require',{{'math','coroutine','package','string','table'}},true) +checkallerrors('require',{{anumber}},'not found') +checkallerrors('require',{{anil,aboolean,afunction,atable}},'bad argument') + +-- package.loadlib +banner('package.loadlib') +checkallpass('package.loadlib',{{'foo'},{'bar'}},true) +checkallerrors('package.loadlib',{notastring},'bad argument') + +-- package.seeall +banner('package.seeall') +checkallpass('package.seeall',{sometable}) +checkallerrors('package.seeall',{notatable},'bad argument') + + +-- module tests - require special rigging +banner('module') +checkallerrors('module',{{20001},{nil,package.seeall,n=2},{nil,function()end,n=2}},"'module' not called from a Lua function") +checkallerrors('module',{{'testmodule1'},{nil,'pqrs',aboolean,athread,atable}},"'module' not called from a Lua function") +checkallerrors('module',{{aboolean,atable,function() end}},'bad argument') +checkallerrors('module',{{aboolean,atable,function() end},{package.seeall}},'bad argument') + +-- enclose each invokation in its own function +function invoke( name, arglist ) + assert( name=='module', 'module rig used for '..name ) + local func = function() + module( unpack(arglist,1,arglist.n or #arglist) ) + end + return pcall( func ) +end +checkallpass('module',{{'foo1',20001}}) +checkallpass('module',{{'foo2',20002},{package.seeall}}) +checkallpass('module',{{'foo3',20003},{package.seeall},{function() end}}) +checkallerrors('module',{{aboolean,atable,function() end}},'bad argument') +checkallerrors('module',{{aboolean,atable,function() end},{package.seeall}},'bad argument') +checkallerrors('module',{{'testmodule2'},{'pqrs'}},'attempt to call') +checkallerrors('module',{{'testmodule3'},{aboolean}},'attempt to call') +checkallerrors('module',{{'testmodule4'},{athread}},'attempt to call') +checkallerrors('module',{{'testmodule5'},{atable}},'attempt to call') diff --git a/luaj-2.0.3/test/lua/errors/operators.lua b/luaj-2.0.3/test/lua/errors/operators.lua new file mode 100644 index 0000000000..ba53b5077c --- /dev/null +++ b/luaj-2.0.3/test/lua/errors/operators.lua @@ -0,0 +1,157 @@ +package.path = "?.lua;test/lua/errors/?.lua" +require 'args' + +-- arg types for language operator + +-- ========= unary operators: - # not + +-- unary minus - +banner('unary -') +negative = function(a) return - a end +checkallpass('negative',{somenumber}) +checkallerrors('negative',{notanumber},'attempt to perform arithmetic') + +-- length +banner('#') +lengthop = function(a) return #a end +checkallpass('lengthop',{sometable}) +checkallerrors('lengthop',{notatable},'attempt to get length of') + +-- length +banner('not') +notop = function(a) return not a end +checkallpass('notop',{somenumber}) +checkallpass('notop',{notanumber}) + +-- function call +banner( '()' ) +funcop = function(a) return a() end +checkallpass('funcop',{somefunction}) +checkallerrors('funcop',{notafunction},'attempt to call') + +-- ========= binary ops: .. + - * / % ^ == ~= <= >= < > [] . and or +banner( '..' ) +concatop = function(a,b) return a..b end +checkallpass('concatop',{somestring,somestring}) +checkallerrors('concatop',{notastring,somestring},'attempt to concatenate') +checkallerrors('concatop',{somestring,notastring},'attempt to concatenate') + +banner( '+' ) +plusop = function(a,b) return a+b end +checkallpass('plusop',{somenumber,somenumber}) +checkallerrors('plusop',{notanumber,somenumber},'attempt to perform arithmetic') +checkallerrors('plusop',{somenumber,notanumber},'attempt to perform arithmetic') + +banner( '-' ) +minusop = function(a,b) return a-b end +checkallpass('minusop',{somenumber,somenumber}) +checkallerrors('minusop',{notanumber,somenumber},'attempt to perform arithmetic') +checkallerrors('minusop',{somenumber,notanumber},'attempt to perform arithmetic') + +banner( '*' ) +timesop = function(a,b) return a*b end +checkallpass('timesop',{somenumber,somenumber}) +checkallerrors('timesop',{notanumber,somenumber},'attempt to perform arithmetic') +checkallerrors('timesop',{somenumber,notanumber},'attempt to perform arithmetic') + +banner( '/' ) +divideop = function(a,b) return a/b end +checkallpass('divideop',{somenumber,somenumber}) +checkallerrors('divideop',{notanumber,somenumber},'attempt to perform arithmetic') +checkallerrors('divideop',{somenumber,notanumber},'attempt to perform arithmetic') + +banner( '%' ) +modop = function(a,b) return a%b end +checkallpass('modop',{somenumber,somenumber}) +checkallerrors('modop',{notanumber,somenumber},'attempt to perform arithmetic') +checkallerrors('modop',{somenumber,notanumber},'attempt to perform arithmetic') + +banner( '^' ) +powerop = function(a,b) return a^b end +checkallpass('powerop',{{2,'2.5'},{3,'3.5'}}) +checkallerrors('powerop',{notanumber,{3,'3.1'}},'attempt to perform arithmetic') +checkallerrors('powerop',{{2,'2.1'},notanumber},'attempt to perform arithmetic') + +banner( '==' ) +equalsop = function(a,b) return a==b end +checkallpass('equalsop',{anylua,anylua}) + +banner( '~=' ) +noteqop = function(a,b) return a~=b end +checkallpass('noteqop',{anylua,anylua}) + +banner( '<=' ) +leop = function(a,b) return a<=b end +checkallpass('leop',{{anumber},{anumber}}) +checkallpass('leop',{{astring,astrnum},{astring,astrnum}}) +checkallerrors('leop',{notanumber,{anumber}},'attempt to compare') +checkallerrors('leop',{{astrnum},{anumber}},'attempt to compare') +checkallerrors('leop',{notastring,{astring,astrnum}},'attempt to compare') +checkallerrors('leop',{{anumber},notanumber},'attempt to compare') +checkallerrors('leop',{{anumber},{astrnum}},'attempt to compare') +checkallerrors('leop',{{astring,astrnum},notastring},'attempt to compare') + +banner( '>=' ) +geop = function(a,b) return a>=b end +checkallpass('geop',{{anumber},{anumber}}) +checkallpass('geop',{{astring,astrnum},{astring,astrnum}}) +checkallerrors('geop',{notanumber,{anumber}},'attempt to compare') +checkallerrors('geop',{{astrnum},{anumber}},'attempt to compare') +checkallerrors('geop',{notastring,{astring,astrnum}},'attempt to compare') +checkallerrors('geop',{{anumber},notanumber},'attempt to compare') +checkallerrors('geop',{{anumber},{astrnum}},'attempt to compare') +checkallerrors('geop',{{astring,astrnum},notastring},'attempt to compare') + +banner( '<' ) +ltop = function(a,b) return a' ) +gtop = function(a,b) return a>b end +checkallpass('gtop',{{anumber},{anumber}}) +checkallpass('gtop',{{astring,astrnum},{astring,astrnum}}) +checkallerrors('gtop',{notanumber,{anumber}},'attempt to compare') +checkallerrors('gtop',{{astrnum},{anumber}},'attempt to compare') +checkallerrors('gtop',{notastring,{astring,astrnum}},'attempt to compare') +checkallerrors('gtop',{{anumber},notanumber},'attempt to compare') +checkallerrors('gtop',{{anumber},{astrnum}},'attempt to compare') +checkallerrors('gtop',{{astring,astrnum},notastring},'attempt to compare') + +banner( '[]' ) +bracketop = function(a,b) return a[b] end +checkallpass('bracketop',{sometable,notanil}) +checkallerrors('bracketop',{notatable,notanil},'attempt to index') +checkallerrors('bracketop',{sometable},'attempt to index') + +banner( '.' ) +dotop = function(a,b) return a.b end +checkallpass('dotop',{sometable,notanil}) +checkallerrors('dotop',{notatable,notanil},'attempt to index') +checkallerrors('dotop',{sometable},'attempt to index') + +banner( 'and' ) +types = {['table']='table',['function']='function',['thread']='thread'} +clean = function(x) return types[type(x)] or x end +andop = function(a,b) return clean(a and b) end +checkallpass('andop',{anylua,anylua}) + +banner( 'or' ) +orop = function(a,b) return clean(a or b) end +checkallpass('orop',{anylua,anylua}) + +-- ========= for x in y +banner( 'for x=a,b,c' ) +forop = function(a,b,c) for x=a,b,c do end end +checkallpass('forop',{{1,'1.1'},{10,'10.1'},{2,'2.1'}}) +checkallerrors('forop',{notanumber,{10,'10.1'},{2,'2.1'}},"'for' initial value must be a number") +checkallerrors('forop',{{1,'1.1'},notanumber,{2,'2.1'}},"'for' limit must be a number") +checkallerrors('forop',{{1,'1.1'},{10,'10.1'},notanumber},"'for' step must be a number") + + diff --git a/luaj-2.0.3/test/lua/errors/stringlibargs.lua b/luaj-2.0.3/test/lua/errors/stringlibargs.lua new file mode 100644 index 0000000000..6cb732e887 --- /dev/null +++ b/luaj-2.0.3/test/lua/errors/stringlibargs.lua @@ -0,0 +1,120 @@ +package.path = "?.lua;test/lua/errors/?.lua" +require 'args' + +-- arg type tests for string library functions + +-- string.byte +banner('string.byte') +checkallpass('string.byte',{somestring}) +checkallpass('string.byte',{somestring,somenumber}) +checkallpass('string.byte',{somestring,somenumber,somenumber}) +checkallerrors('string.byte',{somestring,{astring,afunction,atable}},'bad argument') +checkallerrors('string.byte',{notastring,{nil,111,n=2}},'bad argument') + +-- string.char +function string_char(...) + return string.byte( string.char( ... ) ) +end +banner('string_char') +checkallpass('string.char',{{60}}) +checkallpass('string.char',{{60},{70}}) +checkallpass('string.char',{{60},{70},{80}}) +checkallpass('string_char',{{0,9,40,127,128,255,'0','9','255','9.2',9.2}}) +checkallpass('string_char',{{0,127,255},{0,127,255}}) +checkallerrors('string_char',{},'bad argument') +checkallerrors('string_char',{{nil,-1,256,3}},'bad argument') +checkallerrors('string_char',{notanumber,{23,'45',6.7}},'bad argument') +checkallerrors('string_char',{{23,'45',6.7},nonnumber},'bad argument') + +-- string.dump +banner('string.dump') +local someupval = 435 +local function funcwithupvals() return someupval end +checkallpass('string.dump',{{function() return 123 end}}) +checkallpass('string.dump',{{funcwithupvals}}) +checkallerrors('string.dump',{notafunction},'bad argument') + +-- string.find +banner('string.find') +checkallpass('string.find',{somestring,somestring}) +checkallpass('string.find',{somestring,somestring,{nil,-3,3,n=3}}) +checkallpass('string.find',{somestring,somestring,somenumber,anylua}) +checkallerrors('string.find',{notastring,somestring},'bad argument') +checkallerrors('string.find',{somestring,notastring},'bad argument') +checkallerrors('string.find',{somestring,somestring,nonnumber},'bad argument') + +-- string.format +--local numfmts = {'%c','%d','%E','%e','%f','%g','%G','%i','%o','%u','%X','%x'} +local numfmts = {'%c','%d','%i','%o','%u','%X','%x'} +local strfmts = {'%q','%s'} +local badfmts = {'%w'} +banner('string.format') +checkallpass('string.format',{somestring,anylua}) +checkallpass('string.format',{numfmts,somenumber}) +checkallpass('string.format',{strfmts,somestring}) +checkallerrors('string.format',{numfmts,notanumber},'bad argument') +checkallerrors('string.format',{strfmts,notastring},'bad argument') +checkallerrors('string.format',{badfmts,somestring},"invalid option '%w'") + +-- string.gmatch +banner('string.gmatch') +checkallpass('string.gmatch',{somestring,somestring}) +checkallerrors('string.gmatch',{notastring,somestring},'bad argument') +checkallerrors('string.gmatch',{somestring,notastring},'bad argument') + +-- string.gsub +local somerepl = {astring,atable,afunction} +local notarepl = {nil,aboolean,n=2} +banner('string.gsub') +checkallpass('string.gsub',{somestring,somestring,somerepl,{nil,-1,n=2}}) +checkallerrors('string.gsub',{nonstring,somestring,somerepl},'bad argument') +checkallerrors('string.gsub',{somestring,nonstring,somerepl},'bad argument') +checkallerrors('string.gsub',{{astring},{astring},notarepl},'bad argument') +checkallerrors('string.gsub',{{astring},{astring},somerepl,nonnumber},'bad argument') + +-- string.len +banner('string.len') +checkallpass('string.len',{somestring}) +checkallerrors('string.len',{notastring},'bad argument') + +-- string.lower +banner('string.lower') +checkallpass('string.lower',{somestring}) +checkallerrors('string.lower',{notastring},'bad argument') + +-- string.match +banner('string.match') +checkallpass('string.match',{somestring,somestring}) +checkallpass('string.match',{somestring,somestring,{nil,-3,3,n=3}}) +checkallerrors('string.match',{},'bad argument') +checkallerrors('string.match',{nonstring,somestring},'bad argument') +checkallerrors('string.match',{somestring},'bad argument') +checkallerrors('string.match',{somestring,nonstring},'bad argument') +checkallerrors('string.match',{somestring,somestring,notanumber},'bad argument') + +-- string.reverse +banner('string.reverse') +checkallpass('string.reverse',{somestring}) +checkallerrors('string.reverse',{notastring},'bad argument') + +-- string.rep +banner('string.rep') +checkallpass('string.rep',{somestring,somenumber}) +checkallerrors('string.rep',{notastring,somenumber},'bad argument') +checkallerrors('string.rep',{somestring,notanumber},'bad argument') + +-- string.sub +banner('string.sub') +checkallpass('string.sub',{somestring,somenumber}) +checkallpass('string.sub',{somestring,somenumber,somenumber}) +checkallerrors('string.sub',{},'bad argument') +checkallerrors('string.sub',{nonstring,somenumber,somenumber},'bad argument') +checkallerrors('string.sub',{somestring},'bad argument') +checkallerrors('string.sub',{somestring,nonnumber,somenumber},'bad argument') +checkallerrors('string.sub',{somestring,somenumber,nonnumber},'bad argument') + +-- string.upper +banner('string.upper') +checkallpass('string.upper',{somestring}) +checkallerrors('string.upper',{notastring},'bad argument') + diff --git a/luaj-2.0.3/test/lua/errors/tablelibargs.lua b/luaj-2.0.3/test/lua/errors/tablelibargs.lua new file mode 100644 index 0000000000..0e85f1f6be --- /dev/null +++ b/luaj-2.0.3/test/lua/errors/tablelibargs.lua @@ -0,0 +1,66 @@ +package.path = "?.lua;test/lua/errors/?.lua" +require 'args' + +-- arg type tests for table library functions + +-- table.concat +local somestringstable = {{8,7,6,5,4,3,2,1,}} +local somenonstringtable = {{true,true,true,true,true,true,true,true,}} +local somesep = {',',1.23} +local notasep = {aboolean,atable,afunction} +local somei = {2,'2','2.2'} +local somej = {4,'4','4.4'} +local notij = {astring,aboolean,atable,afunction} +banner('table.concat') +checkallpass('table.concat',{somestringstable}) +checkallpass('table.concat',{somestringstable,somesep}) +checkallpass('table.concat',{somestringstable,{'-'},somei}) +checkallpass('table.concat',{somestringstable,{'-'},{2},somej}) +checkallerrors('table.concat',{notatable},'bad argument') +checkallerrors('table.concat',{somenonstringtable},'boolean') +checkallerrors('table.concat',{somestringstable,notasep},'bad argument') +checkallerrors('table.concat',{somestringstable,{'-'},notij},'bad argument') +checkallerrors('table.concat',{somestringstable,{'-'},{2},notij},'bad argument') + +-- table.insert +banner('table.insert') +checkallpass('table.insert',{sometable,notanil}) +checkallpass('table.insert',{sometable,somei,notanil}) +checkallerrors('table.insert',{notatable,somestring},'bad argument') +checkallerrors('table.insert',{sometable,notij,notanil},'bad argument') + +-- table.maxn +banner('table.maxn') +checkallpass('table.maxn',{sometable}) +checkallerrors('table.maxn',{notatable},'bad argument') + +-- table.remove +banner('table.remove') +checkallpass('table.remove',{sometable}) +checkallpass('table.remove',{sometable,somei}) +checkallerrors('table.remove',{notatable},'bad argument') +checkallerrors('table.remove',{notatable,somei},'bad argument') +checkallerrors('table.remove',{sometable,notij},'bad argument') + +-- table.sort +local somecomp = {nil,afunction,n=2} +local notacomp = {astring,anumber,aboolean,atable} +banner('table.sort') +checkallpass('table.sort',{somestringstable,somecomp}) +checkallerrors('table.sort',{sometable},'attempt to') +checkallerrors('table.sort',{notatable,somecomp},'bad argument') +checkallerrors('table.sort',{sometable,notacomp},'bad argument') + +-- table get +banner('table_get - tbl[key]') +function table_get(tbl,key) return tbl[key] end +checkallpass('table_get',{sometable,anylua}) + +-- table set +banner('table_set - tbl[key]=val') +function table_set(tbl,key,val) tbl[key]=val end +function table_set_nil_key(tbl,val) tbl[nil]=val end +checkallpass('table_set',{sometable,notanil,anylua}) +checkallerrors('table_set_nil_key',{sometable,anylua},'table index') + + diff --git a/luaj-2.0.3/test/lua/foo.log b/luaj-2.0.3/test/lua/foo.log new file mode 100644 index 0000000000..2b2d013408 --- /dev/null +++ b/luaj-2.0.3/test/lua/foo.log @@ -0,0 +1,242 @@ +Archive: luaj2.0-tests.zip + inflating: baselib.out + inflating: coroutinelib.out + inflating: debuglib.out + inflating: errors.out + inflating: functions.out + inflating: iolib.out + inflating: manyupvals.out + inflating: mathlib.out + inflating: metatags.out + inflating: oslib.out + inflating: stringlib.out + inflating: tablelib.out + inflating: tailcalls.out + inflating: tmp1.out + inflating: tmp2.out + inflating: upvalues.out + inflating: vm.out + inflating: lua5.1-tests/all.lc + inflating: lua5.1-tests/api.lc + inflating: lua5.1-tests/attrib.lc + inflating: lua5.1-tests/big.lc + inflating: lua5.1-tests/calls.lc + inflating: lua5.1-tests/checktable.lc + inflating: lua5.1-tests/closure.lc + inflating: lua5.1-tests/code.lc + inflating: lua5.1-tests/constructs.lc + inflating: lua5.1-tests/db.lc + inflating: lua5.1-tests/errors.lc + inflating: lua5.1-tests/events.lc + inflating: lua5.1-tests/files.lc + inflating: lua5.1-tests/gc.lc + inflating: lua5.1-tests/literals.lc + inflating: lua5.1-tests/locals.lc + inflating: lua5.1-tests/main.lc + inflating: lua5.1-tests/math.lc + inflating: lua5.1-tests/nextvar.lc + inflating: lua5.1-tests/pm.lc + inflating: lua5.1-tests/sort.lc + inflating: lua5.1-tests/strings.lc + inflating: lua5.1-tests/vararg.lc + inflating: lua5.1-tests/verybig.lc + inflating: regressions/bigattr.lc + inflating: regressions/comparators.lc + inflating: regressions/construct.lc + inflating: regressions/controlchars.lc + inflating: regressions/mathrandomseed.lc + inflating: regressions/modulo.lc + inflating: regressions/varargs.lc + extracting: errors/args.out + inflating: errors/baselibargs.out + inflating: errors/coroutinelibargs.out + inflating: errors/iolibargs.out + inflating: errors/mathlibargs.out + inflating: errors/modulelibargs.out + inflating: errors/operators.out + inflating: errors/stringlibargs.out + inflating: errors/tablelibargs.out + inflating: perf/binarytrees.out + extracting: perf/fannkuch.out + inflating: perf/nbody.out + inflating: perf/nsieve.out +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests all +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests api +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests attrib +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests big +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests calls +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests checktable +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests closure +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests code +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests constructs +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests db +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests errors +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests events +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests files +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests gc +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests literals +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests locals +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests main +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests math +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests nextvar +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests pm +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests sort +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests strings +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests vararg +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/lua5.1-tests verybig +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/regressions bigattr +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/regressions comparators +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/regressions construct +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/regressions controlchars +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/regressions mathrandomseed +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/regressions modulo +compiling /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/regressions varargs +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/errors args +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/errors baselibargs +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/errors coroutinelibargs +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/errors iolibargs +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/errors mathlibargs +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/errors modulelibargs +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/errors operators +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/errors stringlibargs +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/errors tablelibargs +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/perf binarytrees +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/perf fannkuch +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/perf nbody +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua/perf nsieve +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua baselib +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua coroutinelib +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua debuglib +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua errors +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua functions +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua iolib +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua manyupvals +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua mathlib +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua metatags +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua oslib +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua stringlib +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua tablelib +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua tailcalls +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua upvalues +executing /Users/jrosebor/Workspaces/luaj3/luaj-vm-2.0/test/lua vm + zip warning: name not matched: *.lc + adding: baselib.lua (deflated 81%) + adding: coroutinelib.lua (deflated 74%) + adding: debuglib.lua (deflated 72%) + adding: errors.lua (deflated 80%) + adding: functions.lua (deflated 74%) + adding: iolib.lua (deflated 73%) + adding: manyupvals.lua (deflated 51%) + adding: mathlib.lua (deflated 69%) + adding: metatags.lua (deflated 86%) + adding: oslib.lua (deflated 65%) + adding: stringlib.lua (deflated 71%) + adding: tablelib.lua (deflated 75%) + adding: tailcalls.lua (deflated 65%) + adding: upvalues.lua (deflated 66%) + adding: vm.lua (deflated 76%) + adding: baselib.out (deflated 83%) + adding: coroutinelib.out (deflated 83%) + adding: debuglib.out (deflated 84%) + adding: errors.out (deflated 81%) + adding: functions.out (deflated 75%) + adding: iolib.out (deflated 70%) + adding: manyupvals.out (deflated 91%) + adding: mathlib.out (deflated 80%) + adding: metatags.out (deflated 91%) + adding: oslib.out (deflated 55%) + adding: stringlib.out (deflated 86%) + adding: tablelib.out (deflated 83%) + adding: tailcalls.out (deflated 89%) + adding: tmp1.out (deflated 33%) + adding: tmp2.out (deflated 33%) + adding: upvalues.out (deflated 48%) + adding: vm.out (deflated 79%) + adding: errors/args.lua (deflated 71%) + adding: errors/baselibargs.lua (deflated 78%) + adding: errors/coroutinelibargs.lua (deflated 73%) + adding: errors/iolibargs.lua (deflated 77%) + adding: errors/mathlibargs.lua (deflated 78%) + adding: errors/modulelibargs.lua (deflated 70%) + adding: errors/operators.lua (deflated 82%) + adding: errors/stringlibargs.lua (deflated 81%) + adding: errors/tablelibargs.lua (deflated 76%) + adding: lua5.1-tests/all.lua (deflated 61%) + adding: lua5.1-tests/api.lua (deflated 71%) + adding: lua5.1-tests/attrib.lua (deflated 67%) + adding: lua5.1-tests/big.lua (deflated 66%) + adding: lua5.1-tests/calls.lua (deflated 66%) + adding: lua5.1-tests/checktable.lua (deflated 64%) + adding: lua5.1-tests/closure.lua (deflated 70%) + adding: lua5.1-tests/code.lua (deflated 66%) + adding: lua5.1-tests/constructs.lua (deflated 65%) + adding: lua5.1-tests/db.lua (deflated 70%) + adding: lua5.1-tests/errors.lua (deflated 66%) + adding: lua5.1-tests/events.lua (deflated 73%) + adding: lua5.1-tests/files.lua (deflated 72%) + adding: lua5.1-tests/gc.lua (deflated 69%) + adding: lua5.1-tests/literals.lua (deflated 81%) + adding: lua5.1-tests/locals.lua (deflated 64%) + adding: lua5.1-tests/main.lua (deflated 64%) + adding: lua5.1-tests/math.lua (deflated 68%) + adding: lua5.1-tests/nextvar.lua (deflated 70%) + adding: lua5.1-tests/pm.lua (deflated 69%) + adding: lua5.1-tests/sort.lua (deflated 61%) + adding: lua5.1-tests/strings.lua (deflated 73%) + adding: lua5.1-tests/vararg.lua (deflated 63%) + adding: lua5.1-tests/verybig.lua (deflated 55%) + adding: perf/binarytrees.lua (deflated 61%) + adding: perf/fannkuch.lua (deflated 51%) + adding: perf/nbody.lua (deflated 62%) + adding: perf/nsieve.lua (deflated 56%) + adding: regressions/bigattr.lua (deflated 31%) + adding: regressions/comparators.lua (stored 0%) + adding: regressions/construct.lua (stored 0%) + adding: regressions/controlchars.lua (deflated 11%) + adding: regressions/mathrandomseed.lua (stored 0%) + adding: regressions/modulo.lua (deflated 28%) + adding: regressions/varargs.lua (deflated 79%) + adding: lua5.1-tests/all.lc (deflated 64%) + adding: lua5.1-tests/api.lc (deflated 73%) + adding: lua5.1-tests/attrib.lc (deflated 71%) + adding: lua5.1-tests/big.lc (deflated 70%) + adding: lua5.1-tests/calls.lc (deflated 71%) + adding: lua5.1-tests/checktable.lc (deflated 64%) + adding: lua5.1-tests/closure.lc (deflated 71%) + adding: lua5.1-tests/code.lc (deflated 70%) + adding: lua5.1-tests/constructs.lc (deflated 71%) + adding: lua5.1-tests/db.lc (deflated 70%) + adding: lua5.1-tests/errors.lc (deflated 66%) + adding: lua5.1-tests/events.lc (deflated 76%) + adding: lua5.1-tests/files.lc (deflated 72%) + adding: lua5.1-tests/gc.lc (deflated 68%) + adding: lua5.1-tests/literals.lc (deflated 78%) + adding: lua5.1-tests/locals.lc (deflated 67%) + adding: lua5.1-tests/main.lc (deflated 65%) + adding: lua5.1-tests/math.lc (deflated 73%) + adding: lua5.1-tests/nextvar.lc (deflated 73%) + adding: lua5.1-tests/pm.lc (deflated 74%) + adding: lua5.1-tests/sort.lc (deflated 68%) + adding: lua5.1-tests/strings.lc (deflated 78%) + adding: lua5.1-tests/vararg.lc (deflated 69%) + adding: lua5.1-tests/verybig.lc (deflated 62%) + adding: regressions/bigattr.lc (deflated 50%) + adding: regressions/comparators.lc (deflated 47%) + adding: regressions/construct.lc (deflated 46%) + adding: regressions/controlchars.lc (deflated 34%) + adding: regressions/mathrandomseed.lc (deflated 46%) + adding: regressions/modulo.lc (deflated 51%) + adding: regressions/varargs.lc (deflated 73%) + adding: errors/args.out (stored 0%) + adding: errors/baselibargs.out (deflated 88%) + adding: errors/coroutinelibargs.out (deflated 83%) + adding: errors/iolibargs.out (deflated 88%) + adding: errors/mathlibargs.out (deflated 89%) + adding: errors/modulelibargs.out (deflated 85%) + adding: errors/operators.out (deflated 90%) + adding: errors/stringlibargs.out (deflated 92%) + adding: errors/tablelibargs.out (deflated 89%) + adding: perf/binarytrees.out (deflated 46%) + adding: perf/fannkuch.out (stored 0%) + adding: perf/nbody.out (deflated 12%) + adding: perf/nsieve.out (deflated 49%) diff --git a/luaj-2.0.3/test/lua/functions.lua b/luaj-2.0.3/test/lua/functions.lua new file mode 100644 index 0000000000..e55f035799 --- /dev/null +++ b/luaj-2.0.3/test/lua/functions.lua @@ -0,0 +1,74 @@ + +function f0() print( "f0:" ) end +function f1(a) print( "f1:", a ) end +function f2(a,b) print( "f2:", a, b ) end +function f3(a,b,c) print( "f3:", a, b, c ) end +function f4(a,b,c,d) print( "f4:", a, b, c, d ) end + +f0() f0( "a1/1" ) f0( "a1/2", "a2/2" ) f0( "a1/3", "a2/3", "a3/3" ) f0( "a1/4", "a2/4", "a3/4", "a4/4" ) +f1() f1( "a1/1" ) f1( "a1/2", "a2/2" ) f1( "a1/3", "a2/3", "a3/3" ) f1( "a1/4", "a2/4", "a3/4", "a4/4" ) +f2() f2( "a1/1" ) f2( "a1/2", "a2/2" ) f2( "a1/3", "a2/3", "a3/3" ) f2( "a1/4", "a2/4", "a3/4", "a4/4" ) +f3() f3( "a1/1" ) f3( "a1/2", "a2/2" ) f3( "a1/3", "a2/3", "a3/3" ) f3( "a1/4", "a2/4", "a3/4", "a4/4" ) +f4() f4( "a1/1" ) f4( "a1/2", "a2/2" ) f4( "a1/3", "a2/3", "a3/3" ) f4( "a1/4", "a2/4", "a3/4", "a4/4" ) + +function g0(a,b,c,d) return end +function g1(a,b,c,d) return d end +function g2(a,b,c,d) return c, d end +function g3(a,b,c,d) return b, c, d end +function g4(a,b,c,d) return a, b, c, d end + +z = g0("c0.1/4", "c0.2/4", "c0.3/4", "c0.4/4") +print( "z0:", z ) +z = g2("c2.1/4", "c2.2/4", "c2.3/4", "c2.4/4") +print( "z2:", z ) +z = g4("c4.1/4", "c4.2/4", "c4.3/4", "c4.4/4") +print( "z4:", z ) + +a,b,c,d = g0( "c0.1/4", "c0.2/4", "c0.3/4", "c0.4/4" ) +print( "g0:", a, b, c, d, "(eol)" ) +a,b,c,d = g2( "b2.1/4", "b2.2/4", "b2.3/4", "b2.4/4" ) +print( "g2:", a, b, c, d, "(eol)" ) +a,b,c,d = g4( "b4.1/4", "b4.2/4", "b4.3/4", "b4.4/4" ) +print( "g4:", a, b, c, d, "(eol)" ) + +function func(a,b,c) + return a, b, c +end + +print( func(11, 12, 13) ) +print( func(23, 22, 21) ) +print( func(func(32,33,34), func(45,46,47), func(58,59,50)) ) + +function p(a,...) + print("a",a) + print("...",...) + print("...,a",...,a) + print("a,...",a,...) +end +p() +p("q") +p("q","r") +p("q","r","s") + +-- tail call tests +function first(...) + return 'abc', ..., '|', ... +end + +function second(a,...) + return 'def', ..., '|', a, ... +end + +function third( a, b, c ) + print( 'third', first( a, b, c ) ) + print( 'third', second( a, b, c ) ) + return second( a, b, c ) +end + +print( 'third', third() ) +print( 'third', third('p') ) +print( 'third', third('p','q') ) +print( 'third', third('p','q','r') ) +print( 'third', third('p','q','r','s') ) +print( 'third', third() ) + diff --git a/luaj-2.0.3/test/lua/iolib.lua b/luaj-2.0.3/test/lua/iolib.lua new file mode 100644 index 0000000000..ec87c0cbd6 --- /dev/null +++ b/luaj-2.0.3/test/lua/iolib.lua @@ -0,0 +1,141 @@ +local platform = ... +print( 'platform', platform ) + +-- simple io-library tests +-- +-- C version on Windows will add change \n into \r\n for text files at least +-- +print( io ~= nil ) +print( io.open ~= nil ) +print( io.stdin ~= nil ) +print( io.stdout ~= nil ) +print( io.stderr ~= nil ) +print( 'write', io.write() ) +print( 'write', io.write("This") ) +print( 'write', io.write(" is a pen.") ) +print( 'flush', io.flush() ) + +local f = io.open("abc.txt","w") +print( 'f', type(f) ) +print( io.type(f) ) +print( 'write', f:write("abcdef 12345 \t\t 678910 more\aaaaaaa\bbbbthe rest") ) +print( 'type(f)', io.type(f) ) +print( 'close', f:close() ) +print( 'type(f)', io.type(f) ) +print( 'type("f")', io.type("f") ) + +local g = io.open("abc.txt","r") +local t = { g:read(3, 3, "*n", "*n", "*l", "*l", "*a") } +for i,v in ipairs(t) do + print( string.format("%q",tostring(v)), type(v)) + print( '----- ', i ) +end + +local h,s = io.open("abc.txt", "a") +print( 'h', io.type(h), string.sub(tostring(h),1,6), s ) +print( 'write', h:write('and more and more and more text.') ) +print( 'close', h:close() ) + +if platform ~= 'JME' then + local j = io.open( "abc.txt", "r" ) + print( 'j', io.type(j) ) + print( 'seek', j:seek("set", 3) ) + print( 'read', j:read(4), j:read(3) ) + print( 'seek', j:seek("set", 2) ) + print( 'read', j:read(4), j:read(3) ) + print( 'seek', j:seek("cur", -8 ) ) + print( 'read', j:read(4), j:read(3) ) + print( 'seek(cur,0)', j:seek("cur",0) ) + print( 'seek(cur,20)', j:seek("cur",20) ) + print( 'seek(end,-5)', j:seek("end", -5) ) + print( 'read(4)', string.format("%q", tostring(j:read(4))) ) + print( 'read(4)', string.format("%q", tostring(j:read(4))) ) + print( 'read(4)', string.format("%q", tostring(j:read(4))) ) + print( 'close', j:close() ) +end + +-- write a few lines, including a non-terminating one +f = io.open("abc.txt","w") +print( 'f', io.type(f) ) +print( 'write', f:write("line one\nline two\n\nafter blank line\nunterminated line") ) +print( 'type(f)', io.type(f) ) +print( 'close', f:close() ) + +-- read using io.lines() +for l in io.lines("abc.txt") do + print( string.format('%q',l) ) +end +io.input("abc.txt") +for l in io.lines() do + print( string.format('%q',l) ) +end +io.input(io.open("abc.txt","r")) +for l in io.lines() do + print( string.format('%q',l) ) +end +io.input("abc.txt") +io.input(io.input()) +for l in io.lines() do + print( string.format('%q',l) ) +end + +local count = 0 +io.tmpfile = function() + count = count + 1 + return io.open("tmp"..count..".out","w") +end + +local a = io.tmpfile() +local b = io.tmpfile() +print( io.type(a) ) +print( io.type(b) ) +print( "a:write", a:write('aaaaaaa') ) +print( "b:write", b:write('bbbbbbb') ) +print( "a:setvbuf", a:setvbuf("no") ) +print( "a:setvbuf", a:setvbuf("full",1024) ) +print( "a:setvbuf", a:setvbuf("line") ) +print( "a:write", a:write('ccccc') ) +print( "b:write", b:write('ddddd') ) +print( "a:flush", a:flush() ) +print( "b:flush", b:flush() ) +--[[ +print( "a:read", a:read(7) ) +print( "b:read", b:read(7) ) +print( "a:seek", a:seek("cur",-4) ) +print( "b:seek", b:seek("cur",-4) ) +print( "a:read", ( a:read(7) ) ) +print( "b:read", ( b:read(7) ) ) +print( "a:seek", a:seek("cur",-8) ) +print( "b:seek", b:seek("cur",-8) ) +print( "a:read", ( a:read(7) ) ) +print( "b:read", ( b:read(7) ) ) +--]] + +local pcall = function(...) + local s,e = pcall(...) + if s then return s end + return s,e:match("closed") +end + +print( 'a:close', pcall( a.close, a ) ) +print( 'a:write', pcall( a.write, a, 'eee') ) +print( 'a:flush', pcall( a.flush, a) ) +print( 'a:read', pcall( a.read, a, 5) ) +print( 'a:lines', pcall( a.lines, a) ) +print( 'a:seek', pcall( a.seek, a, "cur", -2) ) +print( 'a:setvbuf', pcall( a.setvbuf, a, "no") ) +print( 'a:close', pcall( a.close, a ) ) +print( 'io.type(a)', pcall( io.type, a ) ) + +print( 'io.close()', pcall( io.close ) ) +print( 'io.close(io.output())', pcall( io.close, io.output() ) ) + +io.output('abc.txt') +print( 'io.close()', pcall( io.close ) ) +print( 'io.write', pcall( io.write, 'eee') ) +print( 'io.flush', pcall( io.flush) ) +print( 'io.close', pcall( io.close ) ) +io.input('abc.txt'):close() +print( 'io.read', pcall( io.read, 5) ) +print( 'io.lines', pcall( io.lines) ) + diff --git a/luaj-2.0.3/test/lua/luaj2.0-tests.zip b/luaj-2.0.3/test/lua/luaj2.0-tests.zip new file mode 100644 index 0000000000000000000000000000000000000000..d1213b4c7ced017a538c31fe25848f163e20ca90 GIT binary patch literal 234243 zcmagFQ?MvOlPNb{WR|=X zFbE0&000C)pfn3V5W8c?CL{oW84~~iGyo2Op@EZ$wS^(AwTpp@G9&NPVYuvZI zi#s#`Acz(M5CBLxG62Aerk34NC!%kxALs!3g!*RuF?-i~2;OEP&$$$IGdMUj$UtDD z`Ix$vEAi*B#Qxvi0}-`dZ~xZ<2ty^NC!cK0+4#hp3G2}JhSQbW?ZU{MSLYeH>f>-e zrC4*FyH=AJR}r2Kyfx=IcNteuii5nq9Q7DgnoMtP2|-@=nKx_H2X8#YUu_1>{t+kC z1gDwGK*!F=SnS8Qcmj?R1|5^%>`u?MJ2 zvip>jeQrKA5_Sl};mJago5-=KR=_^B`@a-FrNvbQ3*NW`dpOi60j0^M$OIYut-4g6 zf@I^M#7FDXp46ByS5LXn$f_#)=K(7$JB-3qq3l&0z^gtpx_KHS&a84);mVFJKm%J* zzPx!t-;x^0q%$oDgH_-KO#y4zP)UdxmFY5CZ*uW^ya{y=%6(-POoPmNMv11->W4f7 zWob}sl;XR%3yu5>bqVTW=XQveE{=?4tPCuJsO7Y(EWP>SI-}j3O%}rPe;bP;jYADf zh+}FfoC%7Hz=S1qFd(-1Au{Hu0^wiKw0xE*>%!pN_0Aqv18$kwrfKw;>Y!sHbZ1{2 z`pm3)OH^nldC_{*^5n{lKuh*y*qNgqKHX_Mvc*y>g?L^N$F1-}Snm_J&qKnS*==3D zm;~pqWu4VlijFA_(jr)tQYHjE-+y$GB(%0gWzt=Zs-$*kC!4Skwr0LI1?;Oy4w5utVK^x)9y;@eo%Hr~5QWo-{zPE*g4_b2} z&Mhjy!;)IqEV_9*TiHc#YI9rcsU{i%o#U-|ZrP2jQ4<#GljY0r8FYaiiD7cJXAItL zX=NF`kUP4>)#cN6B+n7#j!d)3-?q%50=+|dt|}mcXoI;||L7KI$@0F*O~U_Twczbn zy7}DCo-!8RY*$B`J-HOR=p0gTp~$X6K6A{DYz8q`!aFAb-$VZFkvq|_-1hq-ZX{b$ zN2Fj!6I!|5Jo~l!5+3edy|zD#rTfrQfzRBCg%J_6J(32jr{He^SSQ=-tVje?=9H%a=Z>SXmorNVKJp*?!w#>&a>d0qnpN@&ehxYek&Tjy&dGX`nR2P+X z@ken%O&mUejed2em~qZt%QaOTaOH!_wR#|8rn4w8hCB3)axelMVaM5z3!AG zaA;vX3s8~OQ$pCzJ|`v`2FJa_@#GP$xQ`7R_Abk_G2GK8eXUMuD6}y9!i^ph@lg5E z#qlg*oRp`(4tBEJ3=Bj>oMbSDEkD7}y96Bmhb6#-BJg+$7JVsrRt&CnTO(d|F@BHI z?kFLAe0T#)DWfrc6#+0f4CcGxct4F$Yl_?yellLoGZIi20&$DzQddHH6zn((Uhp?Q z>P^FZ>9%@{CUseK=Kk86ng)g>4*c*Ec7*WB;nWEu;pH$Jq65#%)|OVDIeu@7cr%8t zpC2Bg%OOKTP@Aet%V60Oq!>vOMqyzCg67!1$!q+|kuWJwFm%goaAQ^URhp+w)L49I^VZs|YErpL;spJK8 z{N#E$=U=a}UY2$*;{IB~DyTqehP_rL?uik<`VWhI+F&8;*y=yW7vYKJa?-%>C* z@-_u-Hf3Q$@0W`Mf@OC>{cFMJm za;JO&y_2ZJjCD$bLDj?5#XI_d(Vod?-)JHq;o}Ms`GW(D^ic@LyJh~f`sa${?RkKE z8FXCC-_~#(?TxOkx{;|_5?;u00*OkK!rO_ffIJ)(Y@CAzYR(G0h@SJ~HuBAjUKbq& zv|+Fx@$SvOTb3TG=tPmdbyF36RBP@+6@6H%ty^@(`>V)~5|+}Z&SPn(>~~@L{I-eA z#VERKE`Zygs9hhMOw(!yrzoc9UvL!LOYd3~6Z?yQ_b;oY6&Q4WZyO`CYWC3=Q`+t% z;`(SMR?Ep zK-};AIn{YHym4)3Ud`8rMJ&0?II@<}q|YOXnup?FcO+=y2cYT);(u>e+!1`a!&q{M zab~7k`5A5@rmrNKpsVJldc_+0DWx; zAA3T%U_wxS09Wk&e%AT@{mJ`l?tv}fRJN$i#zurbQ6(p>suI}tw@O%R;sp0sS&X8kcFK~7-d3X}@LV5OxXPYT#|iN)TSxy-IoZ>CmaV2U z*e~O>0JthtTM@b!r8Y>LC%<4W2+yU-)PB9$BEYNCg=!@3C%pXsrH2HSQ@oUw1DJBa z004t9000R8=%JCFqn(Shh3)_1h`l_|GXH@i&ZtT`Wzi$>X6ZEyfmS4BZ1$2IDS6G6 z`0+zvF6kd6;KyA&_qm}@=v#|3TEIyhM)$sTo(t%Ak2GRN4&P{<6pH

N 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 + do + local result + function f() + if not result then + result = f() + f() + end + return result + end + end +]] +t[1] = [[ + local f1 + f1 = function() return 1 end +]] +t[2] = [[ + local f2 + f2 = function() return 1 end +]] +for i = 3, 149 do + t[i] = template:gsub("<([^>]+)>", function(s) + local c = assert(loadstring('return '..s), 'could not compile: '..s) + setfenv(c, { i = i }) + return c() + end) +end +t[150] = [[ + print("5th fibonacci number is", f5()) + print("10th fibonacci number is", f10()) + print("149th fibonacci number is", f149()) +]] + +local s = table.concat(t) +print(s) +f = loadstring(s) +f() diff --git a/luaj-2.0.3/test/lua/mathlib.lua b/luaj-2.0.3/test/lua/mathlib.lua new file mode 100644 index 0000000000..cf39b6e68e --- /dev/null +++ b/luaj-2.0.3/test/lua/mathlib.lua @@ -0,0 +1,223 @@ +local platform = ... +print( 'platform', platform ) + +local aliases = { + ['0']='', + ['-0']='', + ['nan']='', + ['inf']='', + ['-inf']='', + ['1.#INF']='', + ['-1.#INF']='', + ['1.#IND']='', + ['-1.#IND']='', +} + +local UNOPVALUES = { -2.5, -2, 0, 2, 2.5, "'-2.5'", "'-2'", "'0'", "'2'", "'2.5'" } + +local NUMBERPAIRS = { + { 2, 0 }, { -2.5, 0 }, { 2, 1 }, + { 5, 2 }, {-5, 2 }, {16, 2}, {-16, -2}, + {256, .25}, + {256, -0.25}, {256, -.25}, {-256, .25}, + { .5, 0}, {.5, 1}, {.5, 2}, {.5, -1}, {.5, 2}, + {2.25, 0}, {2.25, 2}, {2.25, .25}, {2.25, 2.25}, {-2, 0}, + { 3, 3 }, +} + +local STRINGPAIRS = { + { "'2'", "'0'" }, { "'2.5'","'3'" }, { "'-2'", "'1.25'" }, { "'-2.5'", "'-1.25'" }, + { "'3.0'", "'3.0'" }, { 2.75, 2.25 }, { "'2.75'", "'2.25'" }, +} + +local MIXEDPAIRS = { + { 3, "'3'" }, { "'3'", 3 }, { 2.75, "'2.25'" }, { "'2.75'", 2.25 }, + { -3, "'-4'" }, { "'-3'", 4 }, { -3, "'4'" }, { "'-3'", -4 }, + { -4.75, "'2.25'" }, { "'-2.75'", 1.25 }, { 4.75, "'-2.25'" }, { "'2.75'", -1.25 }, +} + +local BINOPVALUES = {} + +local RELATIONALOPVALUES = {} + +local function addall( t, s ) + for i,v in ipairs(s) do + t[#t+1] = v + end +end +addall( BINOPVALUES, NUMBERPAIRS ) +addall( BINOPVALUES, STRINGPAIRS ) +addall( BINOPVALUES, MIXEDPAIRS ) +addall( RELATIONALOPVALUES, NUMBERPAIRS ) +addall( RELATIONALOPVALUES, STRINGPAIRS ) + +local VARARGSVALUES = { + { 4, }, { -4.5 }, { "'5.5'" }, { "'-5'" }, + { 4, "'8'" }, { -4.5, "'-8'" }, { "'5.5'", 2.2 }, { "'-5'", -2.2 }, + { 111,222,333 }, { -222,-333,-111 }, { 444,-111,-222 }, +} + +local CONSTANTS = { + "huge", "pi", +} +local UNARYOPS = { + "-", "not ", +} +local BINARYOPS = { + "+", "-", "*", "^", "/", "%", +} +local RELATIONALS = { + "==", "~=", ">", "<", ">=", "<=", +} +local ONEARG_JME = { + "abs", "ceil", "cos", "deg", + "exp", "floor", "frexp", "modf", + "rad", "sin", "sqrt", "tan", +} +local ONEARG_JSE = { + "acos", "asin", "atan", "cosh", + "log", "log10", "sinh", "tanh", +} +local TWOARGS_JME = { + "fmod", "ldexp", "pow", +} +local TWOARGS_JSE = { + "atan2", +} +local VARARGSFUNCS = { + "max", "min", +} + +local ts = tostring +tostring = function(x) + local s = ts(x) + if type(x)~='number' then return s end + if aliases[s] then return aliases[s] end + if #s < 7 then return s end + local a,b = string.match(s,'([%-0-9%.]*)([eE]?[%-0-9]*)') + return a and (string.sub(a,1,6)..(b or '')) or s +end + +local function eval( expr, script ) + script = script or ('return '..expr) + local s,a,b = loadstring( script, 'expr' ) + if s then print( expr, pcall( s ) ) + else print( expr, 'loadstring:', a ) end +end + +-- misc tests +print( '---------- miscellaneous tests ----------' ) +eval( 'math.sin( 0.0 )' ) +eval( 'math.cos( math.pi )' ) +eval( 'math.sqrt( 9.0 )' ) +eval( 'math.modf( 5.25 )') +eval( 'math.frexp(0.00625)' ) +eval( '-5 ^ 2' ) +eval( '-5 / 2' ) +eval( '-5 % 2' ) + +-- constants +print( '---------- constants ----------' ) +for i,v in ipairs(CONSTANTS) do + eval( 'math.'..v ) +end + +-- unary operators +for i,v in ipairs(UNARYOPS) do + print( '---------- unary operator '..v..' ----------' ) + for j,a in ipairs(UNOPVALUES) do + eval( v..a, 'return '..v..a ) + end +end + +-- binary operators +for i,v in ipairs(BINARYOPS) do + print( '---------- binary operator '..v..' ----------' ) + for j,xy in ipairs(BINOPVALUES) do + eval( xy[1]..v..xy[2], + 'local x,y='..xy[1]..','..xy[2]..'; return x'..v..'y' ) + end +end + +-- relational operators +for i,v in ipairs(RELATIONALS) do + print( '---------- binary operator '..v..' ----------' ) + for j,xy in ipairs(RELATIONALOPVALUES) do + eval( xy[1]..v..xy[2], + 'local x,y='..xy[1]..','..xy[2]..'; return x'..v..'y' ) + end +end + +-- one-argument math functions +for i,v in ipairs(ONEARG_JME) do + print( '---------- math.'..v..' ----------' ) + for j,x in ipairs(UNOPVALUES) do + eval( 'math.'..v..'('..x..')' ) + end +end +if platform ~= 'JME' then + for i,v in ipairs(ONEARG_JSE) do + print( '---------- math.'..v..' (jse only) ----------' ) + for j,x in ipairs(UNOPVALUES) do + eval( 'math.'..v..'('..x..')' ) + end + end +end + +-- two-argument math functions +for i,v in ipairs(TWOARGS_JME) do + print( '---------- math.'..v..' ----------' ) + for j,x in ipairs(BINOPVALUES) do + eval( 'math.'..v..'('..x[1]..','..x[2]..')' ) + end +end +if platform ~= 'JME' then + for i,v in ipairs(TWOARGS_JSE) do + print( '---------- math.'..v..' (jse only) ----------' ) + for j,x in ipairs(BINOPVALUES) do + eval( 'math.'..v..'('..x[1]..','..x[2]..')' ) + end + end +end + +-- var-arg math functions +for i,v in ipairs(VARARGSFUNCS) do + print( '---------- math.'..v..' ----------' ) + for j,x in ipairs(VARARGSVALUES) do + eval( 'math.'..v..'('..table.concat(x,',')..')' ) + end +end + +-- random tests +print("----------- Random number tests") +local function testrandom(string,lo,hi) + local c,e = loadstring('return '..string) + for i=1,5 do + local s,e = pcall(c) + if s then + print( string, s and type(e) or e, (e>=lo) and (e<=hi) ) + else + print( string, 'error', e ) + end + end +end +testrandom('math.random()',0,1) +testrandom('math.random(5,10)',5,10) +testrandom('math.random(30)',0,30) +testrandom('math.random(-4,-2)',-4,-2) +local t = {} +print( math.randomseed(20) ) +for i=1,20 do + t[i] = math.random() +end +print( '-- comparing new numbers') +for i=1,20 do + print( t[i] == math.random(), t[i] == t[0] ) +end +print( '-- resetting seed') + +print( math.randomseed(20) ) +for i=1,20 do + print( t[i] == math.random() ) +end +--]] diff --git a/luaj-2.0.3/test/lua/metatags.lua b/luaj-2.0.3/test/lua/metatags.lua new file mode 100644 index 0000000000..676590be5b --- /dev/null +++ b/luaj-2.0.3/test/lua/metatags.lua @@ -0,0 +1,286 @@ +local anumber,bnumber = 111,23.45 +local astring,bstring = "abc","def" +local anumstr,bnumstr = tostring(anumber),tostring(bnumber) +local aboolean,bboolean = false,true +local afunction,bfunction = function() end, function() end +local athread,bthead = coroutine.create(afunction),coroutine.create(bfunction) +local atable,btable = {},{} +local values = { anumber, aboolean, afunction, athread, atable } +local groups +local ts = tostring +local tb,count = {},0 + +tostring = function(o) + local t = type(o) + if t~='thread' and t~='function' and t~='table' then return ts(o) end + if not tb[o] then + count = count + 1 + tb[o] = t..'.'..count + end + return tb[o] +end + +local buildop = function(name) + return function(a,b) + print( 'mt.__'..name..'()', a, b ) + return '__'..name..'-result' + end +end +local buildop3 = function(name) + return function(a,b,c) + print( 'mt.__'..name..'()', a, b, c ) + return '__'..name..'-result' + end +end +local buildop1 = function(name) + return function(a) + print( 'mt.__'..name..'()', a ) + return '__'..name..'-result' + end +end + +local mt = { + __call=buildop('call'), + __add=buildop('add'), + __sub=buildop('sub'), + __mul=buildop('mul'), + __div=buildop('div'), + __pow=buildop('pow'), + __mod=buildop('mod'), + __unm=buildop1('unm'), + __len=buildop1('len'), + __lt=buildop('lt'), + __le=buildop('le'), + __index=buildop('index'), + __newindex=buildop3('newindex'), + __concat=buildop('concat'), +} + +-- pcall a function and check for a pattern in the error string +ecall = function(pattern, ...) + local s,e = pcall(...) + if not s then e = string.match(e,pattern) or e end + return s,e +end + +print( '---- __eq same types' ) +local eqmt = { __eq=buildop('eq'), } +groups = { {nil,nil}, {true,false}, {123,456}, {11,5.5}, {afunction,bfunction}, {athread,bthread}, {astring,bstring}, {anumber,anumstr} } +for i=1,#groups do + local a,b = groups[i][1], groups[i][2] + local amt,bmt = debug.getmetatable(a),debug.getmetatable(b) + print( type(a), type(b), 'before', pcall( function() return a==b end ) ) + print( type(a), type(b), 'before', pcall( function() return a~=b end ) ) + print( debug.setmetatable( a, eqmt ) ) + print( debug.setmetatable( b, eqmt ) ) + print( type(a), type(b), 'after', pcall( function() return a==b end ) ) + print( type(a), type(b), 'after', pcall( function() return a~=b end ) ) + print( debug.setmetatable( a, amt ) ) + print( debug.setmetatable( b, bmt ) ) +end + +print( '---- __eq, tables - should invoke metatag comparison' ) +groups = { {atable,btable} } +for i=1,#groups do + local a,b = groups[i][1], groups[i][2] + local amt,bmt = debug.getmetatable(a),debug.getmetatable(b) + print( type(a), type(b), 'before', pcall( function() return a==b end ) ) + print( type(a), type(b), 'before', pcall( function() return a~=b end ) ) + print( debug.setmetatable( a, eqmt ) ) + print( debug.setmetatable( b, eqmt ) ) + print( type(a), type(b), 'after-a', pcall( function() return a==b end ) ) + print( type(a), type(b), 'after-a', pcall( function() return a~=b end ) ) + print( debug.setmetatable( a, amt ) ) + print( debug.setmetatable( b, bmt ) ) +end + + +print( 'nilmt', debug.getmetatable(nil) ) +print( 'boolmt', debug.getmetatable(true) ) +print( 'number', debug.getmetatable(1) ) +print( 'function', debug.getmetatable(afunction) ) +print( 'thread', debug.getmetatable(athread) ) + +print( '---- __call' ) +for i=1,#values do + local a = values[i] + local amt = debug.getmetatable(a) + print( type(a), 'before', ecall( 'attempt to call', function() return a('a','b') end ) ) + print( debug.setmetatable( a, mt ) ) + print( type(a), 'after', pcall( function() return a() end ) ) + print( type(a), 'after', pcall( function() return a('a') end ) ) + print( type(a), 'after', pcall( function() return a('a','b') end ) ) + print( type(a), 'after', pcall( function() return a('a','b','c') end ) ) + print( type(a), 'after', pcall( function() return a('a','b','c','d') end ) ) + print( debug.setmetatable( a, amt ) ) +end + +print( '---- __add, __sub, __mul, __div, __pow, __mod' ) +local groups = { {aboolean, aboolean}, {aboolean, athread}, {aboolean, afunction}, {aboolean, "abc"}, {aboolean, atable} } +for i=1,#groups do + local a,b = groups[i][1], groups[i][2] + local amt,bmt = debug.getmetatable(a),debug.getmetatable(b) + print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return a+b end ) ) + print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return b+a end ) ) + print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return a-b end ) ) + print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return b-a end ) ) + print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return a*b end ) ) + print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return b*a end ) ) + print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return a^b end ) ) + print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return b^a end ) ) + print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return a%b end ) ) + print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return b%a end ) ) + print( debug.setmetatable( a, mt ) ) + print( type(a), type(b), 'after', pcall( function() return a+b end ) ) + print( type(a), type(b), 'after', pcall( function() return b+a end ) ) + print( type(a), type(b), 'after', pcall( function() return a-b end ) ) + print( type(a), type(b), 'after', pcall( function() return b-a end ) ) + print( type(a), type(b), 'after', pcall( function() return a*b end ) ) + print( type(a), type(b), 'after', pcall( function() return b*a end ) ) + print( type(a), type(b), 'after', pcall( function() return a^b end ) ) + print( type(a), type(b), 'after', pcall( function() return b^a end ) ) + print( type(a), type(b), 'after', pcall( function() return a%b end ) ) + print( type(a), type(b), 'after', pcall( function() return b%a end ) ) + print( debug.setmetatable( a, amt ) ) + print( debug.setmetatable( b, bmt ) ) +end + +print( '---- __len' ) +values = { aboolean, afunction, athread, anumber } +for i=1,#values do + local a = values[i] + local amt = debug.getmetatable(a) + print( type(a), 'before', ecall( 'attempt to get length of ', function() return #a end ) ) + print( debug.setmetatable( a, mt ) ) + print( type(a), 'after', pcall( function() return #a end ) ) + print( debug.setmetatable( a, amt ) ) +end +-- +print( '---- __neg' ) +values = { aboolean, afunction, athread, "abcd", atable, anumber } +for i=1,#values do + local a = values[i] + local amt = debug.getmetatable(a) + print( type(v), 'before', ecall( 'attempt to perform arithmetic ', function() return -a end ) ) + print( debug.setmetatable( a, mt ) ) + print( type(v), 'after', pcall( function() return -a end ) ) + print( debug.setmetatable( a, amt ) ) +end + +print( '---- __lt, __le, same types' ) +local bfunction = function() end +local bthread = coroutine.create( bfunction ) +local btable = {} +local groups +groups = { {true, true}, {true, false}, {afunction, bfunction}, {athread, bthread}, {atable, atable}, {atable, btable} } +for i=1,#groups do + local a,b = groups[i][1], groups[i][2] + local amt,bmt = debug.getmetatable(a),debug.getmetatable(b) + print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return ab end ) ) + print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return a>=b end ) ) + print( debug.setmetatable( a, mt ) ) + print( debug.setmetatable( b, mt ) ) + print( type(a), type(b), 'after', pcall( function() return ab end ) ) + print( type(a), type(b), 'after', pcall( function() return a>=b end ) ) + print( debug.setmetatable( a, amt ) ) + print( debug.setmetatable( b, bmt ) ) +end + +print( '---- __lt, __le, different types' ) +groups = { {aboolean, athread}, } +for i=1,#groups do + local a,b = groups[i][1], groups[i][2] + local amt,bmt = debug.getmetatable(a),debug.getmetatable(b) + print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return ab end ) ) + print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return a>=b end ) ) + print( debug.setmetatable( a, mt ) ) + print( debug.setmetatable( b, mt ) ) + print( type(a), type(b), 'after-a', ecall( 'attempt to compare', function() return ab end ) ) + print( type(a), type(b), 'after-a', ecall( 'attempt to compare', function() return a>=b end ) ) + print( debug.setmetatable( a, amt ) ) + print( debug.setmetatable( b, bmt ) ) +end + +print( '---- __tostring' ) +values = { aboolean, afunction, athread, atable, "abc" } +local strmt = { __tostring=function(a) + return 'mt.__tostring('..type(a)..')' + end, +} +for i=1,#values do + local a = values[i] + local amt = debug.getmetatable(a) + print( debug.setmetatable( a, strmt ) ) + print( type(a), 'after', pcall( function() return ts(a) end ) ) + print( debug.setmetatable( a, amt ) ) +end + +print( '---- __index, __newindex' ) +values = { aboolean, anumber, afunction, athread } +for i=1,#values do + local a = values[i] + local amt = debug.getmetatable(a) + print( type(a), 'before', ecall( 'attempt to index', function() return a.foo end ) ) + print( type(a), 'before', ecall( 'attempt to index', function() return a[123] end ) ) + print( type(a), 'before', ecall( 'index', function() a.foo = 'bar' end ) ) + print( type(a), 'before', ecall( 'index', function() a[123] = 'bar' end ) ) + print( type(a), 'before', ecall( 'attempt to index', function() return a:foo() end ) ) + print( debug.setmetatable( a, mt ) ) + print( type(a), 'after', pcall( function() return a.foo end ) ) + print( type(a), 'after', pcall( function() return a[123] end ) ) + print( type(a), 'after', pcall( function() a.foo = 'bar' end ) ) + print( type(a), 'after', pcall( function() a[123] = 'bar' end ) ) + print( type(a), 'after', ecall( 'attempt to call', function() return a:foo() end ) ) + print( debug.setmetatable( a, amt ) ) +end + +print( '---- __concat' ) +groups = { {atable, afunction}, {afunction, atable}, {123, nil}, {nil, 123} } +local s,t,u = 'sss',777 +local concatresult = setmetatable( { '__concat-result' }, { + __tostring=function() + return 'concat-string-result' + end } ) +local concatmt = { + __concat=function(a,b) + print( 'mt.__concat('..type(a)..','..type(b)..')', a, b ) + return concatresult + end +} +for i=1,#groups do + local a,b = groups[i][1], groups[i][2] + local amt,bmt = debug.getmetatable(a),debug.getmetatable(b) + print( type(a), type(b), 'before', ecall( 'attempt to concatenate ', function() return a..b end ) ) + print( type(a), type(b), 'before', ecall( 'attempt to concatenate ', function() return b..a end ) ) + print( type(a), type(s), type(t), 'before', ecall( 'attempt to concatenate ', function() return a..s..t end ) ) + print( type(s), type(a), type(t), 'before', ecall( 'attempt to concatenate ', function() return s..a..t end ) ) + print( type(s), type(t), type(a), 'before', ecall( 'attempt to concatenate ', function() return s..t..a end ) ) + print( debug.setmetatable( a, concatmt ) ) + print( type(a), type(b), 'after', pcall( function() return a..b end ) ) + print( type(a), type(b), 'after', pcall( function() return b..a end ) ) + print( type(a), type(s), type(t), 'before', pcall( function() return a..s..t end ) ) + print( type(s), type(a), type(t), 'before', ecall( 'attempt to concatenate ', function() return s..a..t end ) ) + print( type(s), type(t), type(a), 'before', ecall( 'attempt to concatenate ', function() return s..t..a end ) ) + print( debug.setmetatable( a, amt ) ) + print( debug.setmetatable( b, bmt ) ) +end + +print( '---- __metatable' ) +values = { aboolean, afunction, athread, atable, "abc" } +local mtmt = { __metatable={}, } +for i=1,#values do + local a = values[i] + local amt = debug.getmetatable(a) + print( type(a), 'before', pcall( function() return debug.getmetatable(a), getmetatable(a) end ) ) + print( debug.setmetatable( a, mtmt ) ) + print( type(a), 'after', pcall( function() return debug.getmetatable(a), getmetatable(a) end ) ) + print( debug.setmetatable( a, amt ) ) +end diff --git a/luaj-2.0.3/test/lua/oslib.lua b/luaj-2.0.3/test/lua/oslib.lua new file mode 100644 index 0000000000..a46c4bdb4d --- /dev/null +++ b/luaj-2.0.3/test/lua/oslib.lua @@ -0,0 +1,40 @@ +-- simple os-library tests +-- +-- because the nature of the "os" library is to provide os-specific behavior, +-- the compatibility tests must be extremely loose, and can really only +-- compare things like return value type to be meaningful. +-- +-- actual os behavior needs to go in an oslib function test +-- +local pcall = function(...) + local s,e,f = pcall(...) + return s,type(e) +end +print( 'os', type(os) ) +print( 'os.clock()', pcall( os.clock ) ) +print( 'os.date()', pcall( os.date ) ) +print( 'os.difftime(123000, 21500)', pcall( os.difftime, 123000, 21250 ) ) +print( 'os.execute("bogus")', pcall( os.execute, '' ) ) +print( 'os.getenv()', pcall( os.getenv ) ) +print( 'os.getenv("bogus.key")', pcall( os.getenv, 'bogus.key' ) ) +local s,p = pcall( os.tmpname ) +local s,q = pcall( os.tmpname ) +print( 'os.tmpname()', s, p ) +print( 'os.tmpname()', s, q ) +-- permission denied on windows +--print( 'os.remove(p)', pcall( os.remove, p ) ) +--print( 'os.rename(p,q)', pcall( os.rename, p, q ) ) +local s,f = pcall( io.open, p,"w" ) +print( 'io.open', s, f ) +print( 'write', pcall( f.write, f, "abcdef 12345" ) ) +print( 'close', pcall( f.close, f ) ) +print( 'os.rename(p,q)', pcall( os.rename, p, q ) ) +print( 'os.remove(q)', pcall( os.remove, q ) ) +print( 'os.remove(q)', pcall( os.remove, q ) ) +-- setlocale not supported on jse yet +-- print( 'os.setlocale()', pcall( os.setlocale ) ) +-- print( 'os.setlocale("jp")', pcall( os.setlocale, "jp" ) ) +-- print( 'os.setlocale("us","monetary")', pcall( os.setlocale, "us", "monetary" ) ) +-- print( 'os.setlocale(nil,"all")', pcall( os.setlocale, nil, "all" ) ) +print( 'os.setlocale("C")', pcall( os.setlocale, "C" ) ) +print( 'os.exit', type(os.exit) ) diff --git a/luaj-2.0.3/test/lua/perf/binarytrees.lua b/luaj-2.0.3/test/lua/perf/binarytrees.lua new file mode 100644 index 0000000000..04ca7eee0a --- /dev/null +++ b/luaj-2.0.3/test/lua/perf/binarytrees.lua @@ -0,0 +1,50 @@ +-- The Computer Language Benchmarks Game +-- http://shootout.alioth.debian.org/ +-- contributed by Mike Pall + +local function BottomUpTree(item, depth) + if depth > 0 then + local i = item + item + depth = depth - 1 + local left, right = BottomUpTree(i-1, depth), BottomUpTree(i, depth) + return { item, left, right } + else + return { item } + end +end + +local function ItemCheck(tree) + if tree[2] then + return tree[1] + ItemCheck(tree[2]) - ItemCheck(tree[3]) + else + return tree[1] + end +end + +local N = tonumber(arg and arg[1]) or 0 +local mindepth = 4 +local maxdepth = mindepth + 2 +if maxdepth < N then maxdepth = N end + +do + local stretchdepth = maxdepth + 1 + local stretchtree = BottomUpTree(0, stretchdepth) + io.write(string.format("stretch tree of depth %d\t check: %d\n", + stretchdepth, ItemCheck(stretchtree))) +end + +local longlivedtree = BottomUpTree(0, maxdepth) + +for depth=mindepth,maxdepth,2 do + local iterations = 2 ^ (maxdepth - depth + mindepth) + local check = 0 + for i=1,iterations do + check = check + ItemCheck(BottomUpTree(1, depth)) + + ItemCheck(BottomUpTree(-1, depth)) + end + io.write(string.format("%d\t trees of depth %d\t check: %d\n", + iterations*2, depth, check)) +end + +io.write(string.format("long lived tree of depth %d\t check: %d\n", + maxdepth, ItemCheck(longlivedtree))) diff --git a/luaj-2.0.3/test/lua/perf/fannkuch.lua b/luaj-2.0.3/test/lua/perf/fannkuch.lua new file mode 100644 index 0000000000..4fd7b5111b --- /dev/null +++ b/luaj-2.0.3/test/lua/perf/fannkuch.lua @@ -0,0 +1,51 @@ +-- The Computer Language Benchmarks Game +-- http://shootout.alioth.debian.org/ +-- contributed by Mike Pall + +local function fannkuch(n) + local p, q, s, odd, check, maxflips = {}, {}, {}, true, 0, 0 + for i=1,n do p[i] = i; q[i] = i; s[i] = i end + repeat + -- Print max. 30 permutations. + if check < 30 then + if not p[n] then return maxflips end -- Catch n = 0, 1, 2. + io.write(unpack(p)); io.write("\n") + check = check + 1 + end + -- Copy and flip. + local q1 = p[1] -- Cache 1st element. + if p[n] ~= n and q1 ~= 1 then -- Avoid useless work. + for i=2,n do q[i] = p[i] end -- Work on a copy. + for flips=1,1000000 do -- Flip ... + local qq = q[q1] + if qq == 1 then -- ... until 1st element is 1. + if flips > maxflips then maxflips = flips end -- New maximum? + break + end + q[q1] = q1 + if q1 >= 4 then + local i, j = 2, q1 - 1 + repeat q[i], q[j] = q[j], q[i]; i = i + 1; j = j - 1; until i >= j + end + q1 = qq + end + end + -- Permute. + if odd then + p[2], p[1] = p[1], p[2]; odd = false -- Rotate 1<-2. + else + p[2], p[3] = p[3], p[2]; odd = true -- Rotate 1<-2 and 1<-2<-3. + for i=3,n do + local sx = s[i] + if sx ~= 1 then s[i] = sx-1; break end + if i == n then return maxflips end -- Out of permutations. + s[i] = i + -- Rotate 1<-...<-i+1. + local t = p[1]; for j=1,i do p[j] = p[j+1] end; p[i+1] = t + end + end + until false +end + +local n = tonumber(arg and arg[1]) or 1 +io.write("Pfannkuchen(", n, ") = ", fannkuch(n), "\n") diff --git a/luaj-2.0.3/test/lua/perf/nbody.lua b/luaj-2.0.3/test/lua/perf/nbody.lua new file mode 100644 index 0000000000..91d7d5c6f9 --- /dev/null +++ b/luaj-2.0.3/test/lua/perf/nbody.lua @@ -0,0 +1,123 @@ +-- The Great Computer Language Shootout +-- http://shootout.alioth.debian.org/ +-- contributed by Isaac Gouy, tuned by Mike Pall + +local sqrt = math.sqrt + +local PI = 3.141592653589793 +local SOLAR_MASS = 4 * PI * PI +local DAYS_PER_YEAR = 365.24 + +local Jupiter = { + x = 4.84143144246472090e+00 + ,y = -1.16032004402742839e+00 + ,z = -1.03622044471123109e-01 + ,vx = 1.66007664274403694e-03 * DAYS_PER_YEAR + ,vy = 7.69901118419740425e-03 * DAYS_PER_YEAR + ,vz = -6.90460016972063023e-05 * DAYS_PER_YEAR + ,mass = 9.54791938424326609e-04 * SOLAR_MASS +} + +local Saturn = { + x = 8.34336671824457987e+00 + ,y = 4.12479856412430479e+00 + ,z = -4.03523417114321381e-01 + ,vx = -2.76742510726862411e-03 * DAYS_PER_YEAR + ,vy = 4.99852801234917238e-03 * DAYS_PER_YEAR + ,vz = 2.30417297573763929e-05 * DAYS_PER_YEAR + ,mass = 2.85885980666130812e-04 * SOLAR_MASS +} + +local Uranus = { + x = 1.28943695621391310e+01 + ,y = -1.51111514016986312e+01 + ,z = -2.23307578892655734e-01 + ,vx = 2.96460137564761618e-03 * DAYS_PER_YEAR + ,vy = 2.37847173959480950e-03 * DAYS_PER_YEAR + ,vz = -2.96589568540237556e-05 * DAYS_PER_YEAR + ,mass = 4.36624404335156298e-05 * SOLAR_MASS +} + +local Neptune = { + x = 1.53796971148509165e+01 + ,y = -2.59193146099879641e+01 + ,z = 1.79258772950371181e-01 + ,vx = 2.68067772490389322e-03 * DAYS_PER_YEAR + ,vy = 1.62824170038242295e-03 * DAYS_PER_YEAR + ,vz = -9.51592254519715870e-05 * DAYS_PER_YEAR + ,mass = 5.15138902046611451e-05 * SOLAR_MASS +} + +local Sun = { x = 0, y = 0, z = 0, + vx = 0, vy = 0, vz = 0, mass = SOLAR_MASS } + +local function advance(bodies, nbody, dt) + for i=1,nbody do + local bi = bodies[i] + local bix, biy, biz, bimass = bi.x, bi.y, bi.z, bi.mass + local bivx, bivy, bivz = bi.vx, bi.vy, bi.vz + for j=i+1,nbody do + local bj = bodies[j] + local dx, dy, dz = bix-bj.x, biy-bj.y, biz-bj.z + local distance = sqrt(dx*dx + dy*dy + dz*dz) + local mag = dt / (distance * distance * distance) + local bim, bjm = bimass*mag, bj.mass*mag + bivx = bivx - (dx * bjm) + bivy = bivy - (dy * bjm) + bivz = bivz - (dz * bjm) + bj.vx = bj.vx + (dx * bim) + bj.vy = bj.vy + (dy * bim) + bj.vz = bj.vz + (dz * bim) + end + bi.vx = bivx + bi.vy = bivy + bi.vz = bivz + end + for i=1,nbody do + local bi = bodies[i] + bi.x = bi.x + (dt * bi.vx) + bi.y = bi.y + (dt * bi.vy) + bi.z = bi.z + (dt * bi.vz) + end +end + + +local function energy(bodies, nbody) + local e = 0 + for i=1,nbody do + local bi = bodies[i] + local vx, vy, vz, bim = bi.vx, bi.vy, bi.vz, bi.mass + e = e + (0.5 * bim * (vx*vx + vy*vy + vz*vz)) + for j=i+1,nbody do + local bj = bodies[j] + local dx, dy, dz = bi.x-bj.x, bi.y-bj.y, bi.z-bj.z + local distance = sqrt(dx*dx + dy*dy + dz*dz) + e = e - ((bim * bj.mass) / distance) + end + end + return e +end + + +local function offsetMomentum(b, nbody) + local px, py, pz = 0, 0, 0 + for i=1,nbody do + local bi = b[i] + local bim = bi.mass + px = px + (bi.vx * bim) + py = py + (bi.vy * bim) + pz = pz + (bi.vz * bim) + end + b[1].vx = -px / SOLAR_MASS + b[1].vy = -py / SOLAR_MASS + b[1].vz = -pz / SOLAR_MASS +end + +local N = tonumber(arg and arg[1]) or 1000 +local bodies = { Sun, Jupiter, Saturn, Uranus, Neptune } +local nbody = table.getn(bodies) + +offsetMomentum(bodies, nbody) +io.write( string.format("%0.9f",energy(bodies, nbody)), "\n") +for i=1,N do advance(bodies, nbody, 0.01) end +io.write( string.format("%0.9f",energy(bodies, nbody)), "\n") diff --git a/luaj-2.0.3/test/lua/perf/nsieve.lua b/luaj-2.0.3/test/lua/perf/nsieve.lua new file mode 100644 index 0000000000..475a05b469 --- /dev/null +++ b/luaj-2.0.3/test/lua/perf/nsieve.lua @@ -0,0 +1,35 @@ +-- The Computer Language Shootout +-- http://shootout.alioth.debian.org/ +-- contributed by Isaac Gouy +-- modified by Mike Pall + + +local function nsieve(m,isPrime) + for i=2,m do + isPrime[i] = true + end + local count = 0 + + for i=2,m do + if isPrime[i] then + for k=i+i, m, i do + if isPrime[k] then isPrime[k] = false end + end + count = count + 1 + end + end + return count +end + + +local n = tonumber(arg and arg[1]) or 1 +local flags = {} + +local m = (2^n)*10000 +print( string.format("Primes up to %8d %8d", m, nsieve(m,flags))) + +m = (2^(n-1))*10000 +print( string.format("Primes up to %8d %8d", m, nsieve(m,flags))) + +m = (2^(n-2))*10000 +print( string.format("Primes up to %8d %8d", m, nsieve(m,flags))) diff --git a/luaj-2.0.3/test/lua/repack.sh b/luaj-2.0.3/test/lua/repack.sh new file mode 100644 index 0000000000..de30ed2e6e --- /dev/null +++ b/luaj-2.0.3/test/lua/repack.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# +# unpack the luaj test archive, compile and run it locally, and repack the results +# +if [ ! -x "$LUA51" -o ! -x "$LUA51C" ]; then + echo "LUA51 and LUA51C must be set to version 5.1 lua and luac" + exit -1 +fi + +# unzip existing archive +ZIP="luaj2.0-tests.zip" +unzip -n ${ZIP} +rm *.lc *.out */*.lc */*.out + +# compile tests for compiler and save binary files +for DIR in "lua5.1-tests" "regressions"; do + cd ${DIR} + FILES=`ls -1 *.lua | awk 'BEGIN { FS="." } ; { print $1 }'` + for FILE in $FILES ; do + echo 'compiling' `pwd` $FILE + ${LUA51C} ${FILE}.lua + mv luac.out ${FILE}.lc + done + cd .. +done + +# run test lua scripts and save output +for DIR in "errors" "perf" "."; do + cd ${DIR} + FILES=`ls -1 *.lua | awk 'BEGIN { FS="." } ; { print $1 }'` + for FILE in $FILES ; do + echo 'executing' `pwd` $FILE + ${LUA51} ${FILE}.lua JSE > ${FILE}.out + done + cd .. +done +cd lua + +# create new zipfile +rm -f ${ZIP} +zip ${ZIP} *.lua *.lc *.out */*.lua */*.lc */*.out + +# cleanup +rm *.out */*.lc */*.out *.txt */*.txt +rm -r lua5.1-tests +rm -r regressions diff --git a/luaj-2.0.3/test/lua/stringlib.lua b/luaj-2.0.3/test/lua/stringlib.lua new file mode 100644 index 0000000000..83cce2dbce --- /dev/null +++ b/luaj-2.0.3/test/lua/stringlib.lua @@ -0,0 +1,184 @@ +print( string.find("1234567890", ".", 0, true) ) +print( string.find( 'alo alx 123 b\0o b\0o', '(..*) %1' ) ) +print( string.find( 'aloALO', '%l*' ) ) +print( string.find( ' \n isto � assim', '%S%S*' ) ) + +print( string.find( "", "" ) ) +print( string.find( "ababaabbaba", "abb" ) ) +print( string.find( "ababaabbaba", "abb", 7 ) ) + +print( string.match( "aabaa", "a*" ) ) +print( string.match( "aabaa", "a*", 3 ) ) +print( string.match( "aabaa", "a*b" ) ) +print( string.match( "aabaa", "a*b", 3 ) ) + +print( string.match( "abbaaababaabaaabaa", "b(a*)b" ) ) + +print( string.match( "abbaaababaabaaabaa", "b(a*)()b" ) ) +print( string.match( "abbaaababaabaaabaa", "b(a*)()b", 3 ) ) +print( string.match( "abbaaababaabaaabaa", "b(a*)()b", 8 ) ) +print( string.match( "abbaaababaabaaabaa", "b(a*)()b", 12 ) ) + +print( string.byte("hi", -3) ) + +print( string.gsub("ABC", "@(%x+)", function(s) return "|abcd" end) ) +print( string.gsub("@123", "@(%x+)", function(s) return "|abcd" end) ) +print( string.gsub("ABC@123", "@(%x+)", function(s) return "|abcd" end) ) +print( string.gsub("ABC@123@def", "@(%x+)", function(s) return "|abcd" end) ) +print( string.gsub("ABC@123@qrs@def@tuv", "@(%x+)", function(s) return "|abcd" end) ) +print( string.gsub("ABC@123@qrs@def@tuv", "@(%x+)", function(s) return "@ab" end) ) + +print( tostring(1234567890123) ) +print( tostring(1234567890124) ) +print( tostring(1234567890125) ) + +function f1(s, p) + print(p) + p = string.gsub(p, "%%([0-9])", function (s) return "%" .. (s+1) end) + print(p) + p = string.gsub(p, "^(^?)", "%1()", 1) + print(p) + p = string.gsub(p, "($?)$", "()%1", 1) + print(p) + local t = {string.match(s, p)} + return string.sub(s, t[1], t[#t] - 1) +end + +print( pcall( f1, 'alo alx 123 b\0o b\0o', '(..*) %1' ) ) + +local function badpat() + print( string.gsub( "alo", "(.)", "%2" ) ) +end + +print( ( pcall( badpat ) ) ) + +for k, v in string.gmatch("w=200&h=150", "(%w+)=(%w+)") do + print(k, v) +end + +-- string.sub +function t(str) + local i = { 0, 1, 2, 8, -1 } + for ki,vi in ipairs(i) do + local s,v = pcall( string.sub, str, vi ) + print( 'string.sub("'..str..'",'..tostring(vi)..')='..tostring(s)..',"'..tostring(v)..'"' ) + local j = { 0, 1, 2, 4, 8, -1 } + for kj,vj in ipairs(j) do + local s,v = pcall( string.sub, str, vi, vj ) + print( 'string.sub("'..str..'",'..tostring(vi)..','..tostring(vj)..')='..tostring(s)..',"'..tostring(v)..'"' ) + end + end +end +t( 'abcdefghijklmn' ) +t( 'abcdefg' ) +t( 'abcd' ) +t( 'abc' ) +t( 'ab' ) +t( 'a' ) +t( '' ) + +print(string.len("Hello, world")) +print(#"Hello, world") +print(string.len("\0\0\0")) +print(#"\0\0\0") +print(string.len("\0\1\2\3")) +print(#"\0\1\2\3") +local s = "My JaCk-O-lAnTeRn CaSe TeXt" +print(s, string.len(s), #s) + + +-- string.format +print(string.format("(%.0d) (%.0d) (%.0d)", 0, -5, 9)) +print(string.format("(%.1d) (%.1d) (%.1d)", 0, -5, 9)) +print(string.format("(%.2d) (%.2d) (%.2d)", 0, -5, 9)) + +print(string.format("(%+.0d) (%+.0d) (%+.0d)", 0, -5, 9)) +print(string.format("(%+.1d) (%+.1d) (%+.1d)", 0, -5, 9)) +print(string.format("(%+.2d) (%+.2d) (%+.2d)", 0, -5, 9)) + +print(string.format("(%+3d) (% 3d) (%+ 3d)", 55, 55, 55)) + +print(string.format("(%-1d) (%-1d) (%-1d)", 1, 12, -12)) +print(string.format("(%-2d) (%-2d) (%-2d)", 1, 12, -12)) +print(string.format("(%-3d) (%-3d) (%-3d)", 1, 12, -12)) + + +print(string.format("(%8x) (%8d) (%8o)", 255, 255, 255)) +print(string.format("(%08x) (%08d) (%08o)", 255, 255, 255)) + +print(string.format("simple%ssimple", " simple ")) + +local testformat = function(message,fmt,...) + local s,e = pcall( string.format, fmt, ... ) + if s then + print( message, string.byte(e,1,#e) ) + else + print( message, 'error', e ) + end +end + +specials = "\"specials\": %% \000 \r \n" +testformat('plain %', "%%") +testformat("specials (%s)", "---%s---", specials) +testformat("specials (%q)", "---%q---", specials) +testformat("controls (%q)", "---%q---", ' \a \b \f \t \v \\ ') +testformat("extended (%q)", "---%q---", ' \222 \223 \224 ') +testformat("embedded newlines", "%s\r%s\n%s", '===', '===', '===') + +-- format long string +print("this is a %s long string", string.rep("really, ", 30)) + +local function pc(...) + local s,e = pcall(...) + return s and e or 'false-'..type(e) +end + +local function strtests(name,func,...) + print(name, 'good', pc( func, ... ) ) + print(name, 'empty', pc( func ) ) + print(name, 'table', pc( func, {} ) ) + print(name, 'nil', pc( func, nil ) ) +end + +strtests('lower', string.lower, s ) +strtests('upper', string.upper, s ) +strtests('reverse', string.reverse, s ) +strtests('char', string.char, 92, 60, 61, 93 ) +strtests('dump', string.dump, loadstring('print("hello, world")', 'sample') ) + + +-- floating point formats (not supported yet) +--[==[ +local prefixes = {'','+','-'} +local lengths = {'7','2','0','1',''} +local letters = {'f','e','g'} +local fmt, spec, desc +for i,letter in ipairs(letters) do + for k,before in ipairs(lengths) do + for j,prefix in ipairs(prefixes) do + spec = '(%'..prefix..before..letter..')' + fmt = spec..'\t'..spec..'\t'..spec..'\t'..spec..'\t'..spec..'\t'..spec + print(spec, string.format(fmt, 12.34, -12.34, 1/11, -1/11, 300/11, -300/11) ) + for l,after in ipairs(lengths) do + spec = '(%'..prefix..before..'.'..after..letter..')' + fmt = spec..' '..spec..' '..spec..' '..spec..' '..spec..' '..spec + print(spec, string.format(fmt, 12.34, -12.34, 1/11, -1/11, 300/11, -300/11) ) + end + end + end +end +--]==] + +local function fmterr(...) + local r, s = pcall(...) + if r then + return s + else + s = string.gsub(s, "stringlib.lua:%d+:%s*", "") + return s + end +end + +print(fmterr(string.find, "ab%c)0(", "%")) +print(fmterr(string.find, "ab%c)0(", "(")) +print(pcall(string.find, "ab%c)0(", ")")) diff --git a/luaj-2.0.3/test/lua/tablelib.lua b/luaj-2.0.3/test/lua/tablelib.lua new file mode 100644 index 0000000000..da69efb980 --- /dev/null +++ b/luaj-2.0.3/test/lua/tablelib.lua @@ -0,0 +1,274 @@ +local func = function(t,...) + return (...) +end +local tbl = setmetatable({},{__index=func}) +print( tbl[2] ) + + +-- tostring replacement that assigns ids +local ts,id,nid,types = tostring,{},0,{table='tbl',thread='thr',userdata='uda',['function']='func'} +tostring = function(x) + if not x or not types[type(x)] then return ts(x) end + if not id[x] then nid=nid+1; id[x]=types[type(x)]..'.'..nid end + return id[x] +end + +local t = { "one", "two", "three", a='aaa', b='bbb', c='ccc' } + +table.insert(t,'six'); +table.insert(t,1,'seven'); +table.insert(t,4,'eight'); +table.insert(t,7,'nine'); +table.insert(t,10,'ten'); print( #t ) + +-- concat +print( '-- concat tests' ) +function tryconcat(t) + print( table.concat(t) ) + print( table.concat(t,'--') ) + print( table.concat(t,',',2) ) + print( table.concat(t,',',2,2) ) + print( table.concat(t,',',5,2) ) +end +tryconcat( { "one", "two", "three", a='aaa', b='bbb', c='ccc' } ) +tryconcat( { "one", "two", "three", "four", "five" } ) +function tryconcat(t) + print( table.concat(t) ) + print( table.concat(t,'--') ) + print( table.concat(t,',',2) ) +end +tryconcat( { a='aaa', b='bbb', c='ccc', d='ddd', e='eee' } ) +tryconcat( { [501]="one", [502]="two", [503]="three", [504]="four", [505]="five" } ) +tryconcat( {} ) + +-- print the elements of a table in a platform-independent way +function eles(t,f) + f = f or pairs + all = {} + for k,v in f(t) do + table.insert( all, "["..tostring(k).."]="..tostring(v) ) + end + table.sort( all ) + return "{"..table.concat(all,',').."}" +end + +-- insert, maxn +print( '-- insert, len tests' ) +local t = { "one", "two", "three", a='aaa', b='bbb', c='ccc' } + +print( eles(t), #t ) +table.insert(t,'six'); print( eles(t), #t ) +table.insert(t,1,'seven'); print( eles(t), #t ) +table.insert(t,4,'eight'); print( eles(t), #t ) +table.insert(t,7,'nine'); print( eles(t), #t ) +table.insert(t,10,'ten'); print( eles(t), #t ) +print( '#{}', #{} ) +print( '#{"a"}', #{"a"} ) +print( '#{"a","b"}', #{"a","b"} ) +print( '#{"a",nil}', #{"a",nil} ) +print( '#{nil,nil}', #{nil,nil} ) +print( '#{nil,"b"}', #{nil,"b"}==0 or #{nil,"b"}==2 ) +print( '#{"a","b","c"}', #{"a","b","c"} ) +print( '#{"a","b",nil}', #{"a","b",nil} ) +print( '#{"a",nil,nil}', #{"a",nil,nil} ) +print( '#{nil,nil,nil}', #{nil,nil,nil} ) +print( '#{nil,nil,"c"}', #{nil,nil,"c"}==0 or #{nil,nil,"c"}==3 ) +print( '#{nil,"b","c"}', #{nil,"b","c"}==0 or #{nil,"b","c"}==3 ) +print( '#{nil,"b",nil}', #{nil,"b",nil}==0 or #{nil,"b",nil}==2 ) +print( '#{"a",nil,"c"}', #{"a",nil,"c"}==1 or #{"a",nil,"c"}==3 ) + +-- remove +print( '-- remove tests' ) +t = { "one", "two", "three", "four", "five", "six", "seven", [10]="ten", a='aaa', b='bbb', c='ccc' } +print( eles(t), #t ) +print( 'table.remove(t)', table.remove(t) ); print( eles(t), #t ) +print( 'table.remove(t,1)', table.remove(t,1) ); print( eles(t), #t ) +print( 'table.remove(t,3)', table.remove(t,3) ); print( eles(t), #t ) +print( 'table.remove(t,5)', table.remove(t,5) ); print( eles(t), #t ) +print( 'table.remove(t,10)', table.remove(t,10) ); print( eles(t), #t ) +print( 'table.remove(t,-1)', table.remove(t,-1) ); print( eles(t), #t ) +print( 'table.remove(t,-1)', table.remove(t,-1) ) ; print( eles(t), #t ) + +-- sort +print( '-- sort tests' ) +function sorttest(t,f) + t = (t) + print( table.concat(t,'-') ) + if f then + table.sort(t,f) + else + table.sort(t) + end + print( table.concat(t,'-') ) +end +sorttest{ "one", "two", "three" } +sorttest{ "www", "vvv", "uuu", "ttt", "sss", "zzz", "yyy", "xxx" } +sorttest( { "www", "vvv", "uuu", "ttt", "sss", "zzz", "yyy", "xxx" }, function(a,b) return b0, returning f2(n-1,n,...)", n-1,n,... ) + return f2(n-1,n,...) +end + +local function f3(n,...) + if n <= 0 then + return sum(...) + end + print( " f3,n-1,n,...", f3,n-1,n,... ) + return pcall(f3,n-1,n,...) +end + +local function all(f) + for n=0,3 do + t = {} + for m=1,5 do + print( "--f, n, unpack(t)", f, n, unpack(t) ) + print( pcall( f, n, unpack(t)) ) + t[m] = m + end + end +end + +all(f1) +all(f2) +all(f3) + + +local function f(x) + -- tailcall to a builtin + return math.abs(x) +end + +local function factorial(i) + local function helper(product, n) + if n <= 0 then + return product + else + -- tail call to a nested Lua function + return helper(n * product, n - 1) + end + end + return helper(1, i) +end + +local result1 = factorial(5) +print(result1) +print(factorial(5)) + +local result2 = f(-1234) +print( result2 ) + +local function fib_bad(n) + local function helper(i, a, b) + if i >= n then + return a + else + -- not recognized by luac as a tailcall! + local result = helper(i + 1, b, a + b) + return result + end + end + return helper(1, 1, 1) +end + +local function fib_good(n) + local function helper(i, a, b) + if i >= n then + return a + else + -- must be a tail call! + return helper(i + 1, b, a + b) + end + end + return helper(1, 1, 1) +end + +local aliases = { + ['1.#INF'] = 'inf', + ['-1.#INF'] = '-inf', + ['1.#IND'] = 'nan', + ['-1.#IND'] = 'nan', +} + +local p = function( s,e ) + print( s, e and aliases[tostring(e)] or e ) +end +p(pcall(fib_bad, 30)) +--p((pcall(fib_bad, 25000))) +p(pcall(fib_good, 30)) +p(pcall(fib_good, 25000)) + +local function fib_all(n, i, a, b) + i = i or 1 + a = a or 1 + b = b or 1 + if i >= n then + return + else + return a, fib_all(n, i+1, b, a+b) + end +end + +print(fib_all(10)) diff --git a/luaj-2.0.3/test/lua/upvalues.lua b/luaj-2.0.3/test/lua/upvalues.lua new file mode 100644 index 0000000000..2c263dd84a --- /dev/null +++ b/luaj-2.0.3/test/lua/upvalues.lua @@ -0,0 +1,97 @@ + +print( '-------- simple upvalues tests --------' ) +local function simpleupvalues() + function test() + local x = 5 + function f() + x = x + 1 + return x + end + function g() + x = x - 1 + return x + end + print(f()) + print(g()) + return f, g + end + + f1, g1 = test() + print("f1()=", f1()) + print("g1()=", g1()) + + f2, g2 = test() + print("f2()=", f2()) + print("g2()=", g2()) + + print("g1()=", g1()) + print("f1()=", f1()) +end +print( 'simplevalues result:', pcall( simpleupvalues ) ) + + +-- The point of this test is that when an upvalue is created, it may +-- need to be inserted in the middle of the list, rather than always +-- appended at the end. Otherwise, it may not be found when it is +-- needed by another closure. +print( '----------- upvalued in middle ------------' ) +local function middleupvaluestest() + local function test() + local x = 3 + local y = 5 + local z = 7 + + local function f() + print("y=", y) + end + + local function g() + print("z=", z) + end + + local function h() + print("x=", x) + end + + local function setter(x1, y1, z1) + x = x1 + y = y1 + z = z1 + end + + return f, g, h, setter + end + + local f, g, h, setter = test() + + h() + f() + g() + + setter("x", "y", "z") + + h() + f() + g() +end +print( pcall( middleupvaluestest ) ) + + +print( '--------- nested upvalues ----------' ) +local function nestedupvaluestest() + local f + do + local x = 10 + function g() + print(x, f()) + end + end + + function f() + return 20 + end + + g() +end +print( 'nestedupvaluestest result:', pcall( nestedupvaluestest ) ) + diff --git a/luaj-2.0.3/test/lua/vm.lua b/luaj-2.0.3/test/lua/vm.lua new file mode 100644 index 0000000000..735ccfb175 --- /dev/null +++ b/luaj-2.0.3/test/lua/vm.lua @@ -0,0 +1,250 @@ + +print( '-------- basic vm tests --------' ) + +print( '-- boolean tests' ) +local function booleantests() + t = true + f = false + n = nil + s = "Hello" + z = 0 + one = 1 + + print(t) + print(f) + + print(not t) + print(not f) + print(not n) + print(not z) + print(not s) + print(not(not(t))) + print(not(not(z))) + print(not(not(n))) + + print(t and f) + print(t or f) + print(f and t) + print(f or t) + + print(f or one) + print(f or z) + print(f or n) + + print(t and one) + print(t and z) + print(t and n) +end +print( 'booleantests result:', pcall( booleantests ) ) + + +print( '------------- varargs' ) +local function varargstest() + function p(a,...) + print("a",a) + print("...",...) + print("...,a",...,a) + print("a,...",a,...) + end + function q(a,...) + print("a,arg[1],arg[2],arg[3]",a,arg.n,arg[1],arg[2],arg[3]) + end + function r(a,...) + print("a,arg",a,arg) + print("a",a) + print("...",...) + print("...,a",...,a) + print("a,...",a,...) + end + function s(a) + local arg = { '1', '2', '3' } + print("a,arg[1],arg[2],arg[3]",a,arg[1],arg[2],arg[3]) + print("a",a) + end + function t(a,...) + local arg = { '1', '2', '3' } + print("a,arg[1],arg[2],arg[3]",a,arg[1],arg[2],arg[3]) + print("a",a) + print("...",...) + print("...,a",...,a) + print("a,...",a,...) + end + function u(arg) + print( 'arg', arg ) + end + function v(arg,...) + print( 'arg', arg ) + print("...",...) + print("arg,...",arg,...) + end + arg = { "global-1", "global-2", "global-3" } + function tryall(f,name) + print( '---- function '..name..'()' ) + print( '--'..name..'():' ) + print( ' ->', pcall( f ) ) + print( '--'..name..'("q"):' ) + print( ' ->', pcall( f, "q" ) ) + print( '--'..name..'("q","r"):' ) + print( ' ->', pcall( f, "q", "r" ) ) + print( '--'..name..'("q","r","s"):' ) + print( ' ->', pcall( f, "q", "r", "s" ) ) + end + tryall(p,'p') + tryall(q,'q') + tryall(r,'r') + tryall(s,'s') + tryall(t,'t') + tryall(u,'u') + tryall(v,'v') +end +print( 'varargstest result:', pcall( varargstest ) ) + +-- The purpose of this test case is to demonstrate that +-- basic metatable operations on non-table types work. +-- i.e. that s.sub(s,...) could be used in place of string.sub(s,...) +print( '---------- metatable tests' ) +local function metatabletests() + + -- tostring replacement that assigns ids + local ts,id,nid,types = tostring,{},0,{table='tbl',thread='thr',userdata='uda',['function']='func'} + tostring = function(x) + if not x or not types[type(x)] then return ts(x) end + if not id[x] then nid=nid+1; id[x]=types[type(x)]..'.'..nid end + return id[x] + end + local results = function(s,e,...) + if s then return e,... end + return false,type(e) + end + local pcall = function(...) + return results( pcall(...) ) + end + + + local s = "hello" + print(s:sub(2,4)) + + local t = {} + function op(name,...) + local a,b = pcall( setmetatable, t, ... ) + print( name, t, getmetatable(t), a, b ) + end + op('set{} ',{}) + op('set-nil',nil) + op('set{} ',{}) + op('set') + op('set{} ',{}) + op('set{} ',{}) + op('set{}{}',{},{}) + op('set-nil',nil) + op('set{__}',{__metatable={}}) + op('set{} ',{}) + op('set-nil',nil) + t = {} + op('set{} ',{}) + op('set-nil',nil) + op('set{__}',{__metatable='abc'}) + op('set{} ',{}) + op('set-nil',nil) + + + local i = 1234 + local t = setmetatable( {}, { + __mode="v", + __index=function(t,k) + local v = i + i = i + 1 + rawset(t,k,v) + return v + end, + } ) + + local l = { 'a', 'b', 'a', 'b', 'c', 'a', 'b', 'c', 'd' } + for i,key in ipairs(l) do + print( 't.'..key, t[key] ) + end +end +print( 'metatabletests result:', pcall( metatabletests ) ) + +-- test tables with more than 50 elements +print( '------------ huge tables' ) +local function hugetables() + local t = { 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1, + } + print ("#t=",#t,'t[1,50,51,59]', t[1], t[50], t[51], t[59]) + print (table.concat(t,',')) + + local t2= { 0,3,4,7,9,8,12,15,23,5, + 10,13,14,17,19,18,112,115,123,15, + 20,33,24,27,29,28,212,215,223,25, + 40,43,44,47,49,48,412,415,423,45, + 50,53,54,57,59,58,512,515,523,55, + 60,63,64,67,69,68,612,615,623,65, + 70,73,74,77,79,78,72,715,723,75, + } + + print ("#t2=",#t2,'t[1,50,51,59]', t[1], t[50], t[51], t[59]) + print (table.concat(t2,',')) + + local t = { + [2000]='a', [2001]='b', [2002]='c', [2003]='d', [2004]='e', [2005]='f', [2006]='g', [2007]='h', [2008]='i', [2009]='j', + [3000]='a', [3001]='b', [3002]='c', [3003]='d', [3004]='e', [3005]='f', [3006]='g', [3007]='h', [3008]='i', [3009]='j', + [4000]='a', [4001]='b', [4002]='c', [4003]='d', [4004]='e', [4005]='f', [4006]='g', [4007]='h', [4008]='i', [4009]='j', + [5000]='a', [5001]='b', [5002]='c', [5003]='d', [5004]='e', [5005]='f', [5006]='g', [5007]='h', [5008]='i', [5009]='j', + [6000]='a', [6001]='b', [6002]='c', [6003]='d', [6004]='e', [6005]='f', [6006]='g', [6007]='h', [6008]='i', [6009]='j', + [7000]='a', [7001]='b', [7002]='c', [7003]='d', [7004]='e', [7005]='f', [7006]='g', [7007]='h', [7008]='i', [7009]='j', + [8000]='a', [8001]='b', [8002]='c', [8003]='d', [8004]='e', [8005]='f', [8006]='g', [8007]='h', [8008]='i', [8009]='j', + } + + for i=2000,8000,1000 do + for j=0,9,1 do + print( 't['..tostring(i+j)..']', t[i+j] ) + end + end +end +print( 'hugetables result:', pcall( hugetables ) ) + +print( '--------- many locals' ) +local function manylocals() + -- test program with more than 50 non-sequential integer elements + local t0000='a'; local t0001='b'; local t0002='c'; local t0003='d'; local t0004='e'; local t0005='f'; local t0006='g'; local t0007='h'; local t0008='i'; local t0009='j'; + local t1000='a'; local t1001='b'; local t1002='c'; local t1003='d'; local t1004='e'; local t1005='f'; local t1006='g'; local t1007='h'; local t1008='i'; local t1009='j'; + local t2000='a'; local t2001='b'; local t2002='c'; local t2003='d'; local t2004='e'; local t2005='f'; local t2006='g'; local t2007='h'; local t2008='i'; local t2009='j'; + local t3000='a'; local t3001='b'; local t3002='c'; local t3003='d'; local t3004='e'; local t3005='f'; local t3006='g'; local t3007='h'; local t3008='i'; local t3009='j'; + local t4000='a'; local t4001='b'; local t4002='c'; local t4003='d'; local t4004='e'; local t4005='f'; local t4006='g'; local t4007='h'; local t4008='i'; local t4009='j'; + local t5000='a'; local t5001='b'; local t5002='c'; local t5003='d'; local t5004='e'; local t5005='f'; local t5006='g'; local t5007='h'; local t5008='i'; local t5009='j'; + local t6000='a'; local t6001='b'; local t6002='c'; local t6003='d'; local t6004='e'; local t6005='f'; local t6006='g'; local t6007='h'; local t6008='i'; local t6009='j'; + local t7000='a'; local t7001='b'; local t7002='c'; local t7003='d'; local t7004='e'; local t7005='f'; local t7006='g'; local t7007='h'; local t7008='i'; local t7009='j'; + local t8000='a'; local t8001='b'; local t8002='c'; local t8003='d'; local t8004='e'; local t8005='f'; local t8006='g'; local t8007='h'; local t8008='i'; local t8009='j'; + local t9000='a'; local t9001='b'; local t9002='c'; local t9003='d'; local t9004='e'; local t9005='f'; local t9006='g'; local t9007='h'; local t9008='i'; local t9009='j'; + local t10000='a'; local t10001='b'; local t10002='c'; local t10003='d'; local t10004='e'; local t10005='f'; local t10006='g'; local t10007='h'; local t10008='i'; local t10009='j'; + local t11000='a'; local t11001='b'; local t11002='c'; local t11003='d'; local t11004='e'; local t11005='f'; local t11006='g'; local t11007='h'; local t11008='i'; local t11009='j'; + local t12000='a'; local t12001='b'; local t12002='c'; local t12003='d'; local t12004='e'; local t12005='f'; local t12006='g'; local t12007='h'; local t12008='i'; local t12009='j'; + local t13000='a'; local t13001='b'; local t13002='c'; local t13003='d'; local t13004='e'; local t13005='f'; local t13006='g'; local t13007='h'; local t13008='i'; local t13009='j'; + + -- print the variables + print(t0000,'a'); print(t0001,'b'); print(t0002,'c'); print(t0003,'d'); print(t0004,'e'); print(t0005,'f'); print(t0006,'g'); print(t0007,'h'); print(t0008,'i'); print(t0009,'j'); + print(t1000,'a'); print(t1001,'b'); print(t1002,'c'); print(t1003,'d'); print(t1004,'e'); print(t1005,'f'); print(t1006,'g'); print(t1007,'h'); print(t1008,'i'); print(t1009,'j'); + print(t2000,'a'); print(t2001,'b'); print(t2002,'c'); print(t2003,'d'); print(t2004,'e'); print(t2005,'f'); print(t2006,'g'); print(t2007,'h'); print(t2008,'i'); print(t2009,'j'); + print(t3000,'a'); print(t3001,'b'); print(t3002,'c'); print(t3003,'d'); print(t3004,'e'); print(t3005,'f'); print(t3006,'g'); print(t3007,'h'); print(t3008,'i'); print(t3009,'j'); + print(t4000,'a'); print(t4001,'b'); print(t4002,'c'); print(t4003,'d'); print(t4004,'e'); print(t4005,'f'); print(t4006,'g'); print(t4007,'h'); print(t4008,'i'); print(t4009,'j'); + print(t5000,'a'); print(t5001,'b'); print(t5002,'c'); print(t5003,'d'); print(t5004,'e'); print(t5005,'f'); print(t5006,'g'); print(t5007,'h'); print(t5008,'i'); print(t5009,'j'); + print(t6000,'a'); print(t6001,'b'); print(t6002,'c'); print(t6003,'d'); print(t6004,'e'); print(t6005,'f'); print(t6006,'g'); print(t6007,'h'); print(t6008,'i'); print(t6009,'j'); + print(t7000,'a'); print(t7001,'b'); print(t7002,'c'); print(t7003,'d'); print(t7004,'e'); print(t7005,'f'); print(t7006,'g'); print(t7007,'h'); print(t7008,'i'); print(t7009,'j'); + print(t8000,'a'); print(t8001,'b'); print(t8002,'c'); print(t8003,'d'); print(t8004,'e'); print(t8005,'f'); print(t8006,'g'); print(t8007,'h'); print(t8008,'i'); print(t8009,'j'); + print(t9000,'a'); print(t9001,'b'); print(t9002,'c'); print(t9003,'d'); print(t9004,'e'); print(t9005,'f'); print(t9006,'g'); print(t9007,'h'); print(t9008,'i'); print(t9009,'j'); + print(t10000,'a'); print(t10001,'b'); print(t10002,'c'); print(t10003,'d'); print(t10004,'e'); print(t10005,'f'); print(t10006,'g'); print(t10007,'h'); print(t10008,'i'); print(t10009,'j'); + print(t11000,'a'); print(t11001,'b'); print(t11002,'c'); print(t11003,'d'); print(t11004,'e'); print(t11005,'f'); print(t11006,'g'); print(t11007,'h'); print(t11008,'i'); print(t11009,'j'); + print(t12000,'a'); print(t12001,'b'); print(t12002,'c'); print(t12003,'d'); print(t12004,'e'); print(t12005,'f'); print(t12006,'g'); print(t12007,'h'); print(t12008,'i'); print(t12009,'j'); + print(t13000,'a'); print(t13001,'b'); print(t13002,'c'); print(t13003,'d'); print(t13004,'e'); print(t13005,'f'); print(t13006,'g'); print(t13007,'h'); print(t13008,'i'); print(t13009,'j'); +end +print( 'manylocals result:', pcall( manylocals ) ) diff --git a/luaj-2.0.3/version.properties b/luaj-2.0.3/version.properties new file mode 100644 index 0000000000..e83376fb96 --- /dev/null +++ b/luaj-2.0.3/version.properties @@ -0,0 +1 @@ +version: 2.0.3 \ No newline at end of file diff --git a/luaj-2.0.3/wtk.xml b/luaj-2.0.3/wtk.xml new file mode 100644 index 0000000000..afeaef79ac --- /dev/null +++ b/luaj-2.0.3/wtk.xml @@ -0,0 +1,25 @@ + + + + WTK_HOME from env ${env.WTK_HOME} + + + + + + + + + + + + + + Using WTK found in ${wtk.home} + + + + + + + diff --git a/setup.sh b/setup.sh new file mode 100755 index 0000000000..4ae0579c58 --- /dev/null +++ b/setup.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +echo "Setting permissions..." +chmod +x build_luaj.sh +chmod +x deploy.sh +chmod +x gradlew + +echo "Setting up IntelliJ development environment with gradle..." +rm -rf build +./gradlew setupDecompWorkspace --refresh-dependencies +./gradlew cleanIdea idea + +echo "Done." diff --git a/src/main/java/dan200/computercraft/ComputerCraft.java b/src/main/java/dan200/computercraft/ComputerCraft.java new file mode 100644 index 0000000000..dc5d1240a9 --- /dev/null +++ b/src/main/java/dan200/computercraft/ComputerCraft.java @@ -0,0 +1,790 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft; + +import dan200.computercraft.api.filesystem.IMount; +import dan200.computercraft.api.filesystem.IWritableMount; +import dan200.computercraft.api.media.IMedia; +import dan200.computercraft.api.media.IMediaProvider; +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.api.peripheral.IPeripheralProvider; +import dan200.computercraft.api.permissions.ITurtlePermissionProvider; +import dan200.computercraft.api.redstone.IBundledRedstoneProvider; +import dan200.computercraft.api.turtle.ITurtleUpgrade; +import dan200.computercraft.core.filesystem.ComboMount; +import dan200.computercraft.core.filesystem.FileMount; +import dan200.computercraft.core.filesystem.JarMount; +import dan200.computercraft.shared.common.DefaultBundledRedstoneProvider; +import dan200.computercraft.shared.computer.blocks.BlockCommandComputer; +import dan200.computercraft.shared.computer.blocks.BlockComputer; +import dan200.computercraft.shared.computer.blocks.TileComputer; +import dan200.computercraft.shared.computer.core.ClientComputerRegistry; +import dan200.computercraft.shared.computer.core.ServerComputerRegistry; +import dan200.computercraft.shared.media.items.ItemDiskExpanded; +import dan200.computercraft.shared.media.items.ItemDiskLegacy; +import dan200.computercraft.shared.media.items.ItemPrintout; +import dan200.computercraft.shared.media.items.ItemTreasureDisk; +import dan200.computercraft.shared.network.ComputerCraftPacket; +import dan200.computercraft.shared.network.PacketHandler; +import dan200.computercraft.shared.peripheral.common.BlockCable; +import dan200.computercraft.shared.peripheral.common.BlockPeripheral; +import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive; +import dan200.computercraft.shared.peripheral.modem.BlockAdvancedModem; +import dan200.computercraft.shared.peripheral.modem.WirelessNetwork; +import dan200.computercraft.shared.peripheral.printer.TilePrinter; +import dan200.computercraft.shared.pocket.items.ItemPocketComputer; +import dan200.computercraft.shared.proxy.ICCTurtleProxy; +import dan200.computercraft.shared.proxy.IComputerCraftProxy; +import dan200.computercraft.shared.turtle.blocks.BlockTurtle; +import dan200.computercraft.shared.turtle.blocks.TileTurtle; +import dan200.computercraft.shared.turtle.upgrades.*; +import dan200.computercraft.shared.util.CreativeTabMain; +import dan200.computercraft.shared.util.IDAssigner; +import dan200.computercraft.shared.util.IEntityDropConsumer; +import dan200.computercraft.shared.util.WorldUtil; +import io.netty.buffer.Unpooled; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; +import net.minecraftforge.common.config.Configuration; +import net.minecraftforge.common.config.Property; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.SidedProxy; +import net.minecraftforge.fml.common.event.*; +import net.minecraftforge.fml.common.network.FMLEventChannel; +import net.minecraftforge.fml.common.network.NetworkRegistry; +import net.minecraftforge.fml.common.network.internal.FMLProxyPacket; +import net.minecraftforge.fml.relauncher.Side; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/////////////// +// UNIVERSAL // +/////////////// + +@Mod( modid = "ComputerCraft", name = "ComputerCraft", version = "${version}" ) +public class ComputerCraft +{ + // GUI IDs + public static final int diskDriveGUIID = 100; + public static final int computerGUIID = 101; + public static final int printerGUIID = 102; + public static final int turtleGUIID = 103; + // ComputerCraftEdu uses ID 104 + public static final int printoutGUIID = 105; + public static final int pocketComputerGUIID = 106; + + // Configuration options + public static boolean http_enable = true; + public static String http_whitelist = "*"; + public static boolean disable_lua51_features = false; + public static String default_computer_settings = ""; + + public static boolean enableCommandBlock = false; + public static boolean turtlesNeedFuel = true; + public static int turtleFuelLimit = 20000; + public static int advancedTurtleFuelLimit = 100000; + public static boolean turtlesObeyBlockProtection = true; + public static boolean turtlesCanPush = true; + + public static final int terminalWidth_computer = 51; + public static final int terminalHeight_computer = 19; + + public static final int terminalWidth_turtle = 39; + public static final int terminalHeight_turtle = 13; + + public static final int terminalWidth_pocketComputer = 26; + public static final int terminalHeight_pocketComputer = 20; + + public static int modem_range = 64; + public static int modem_highAltitudeRange = 384; + public static int modem_rangeDuringStorm = 64; + public static int modem_highAltitudeRangeDuringStorm = 384; + + public static int computerSpaceLimit = 1000 * 1000; + public static int floppySpaceLimit = 125 * 1000; + + public static int treasureDiskLootFrequency = 1; + + // Blocks and Items + public static class Blocks + { + public static BlockComputer computer; + public static BlockPeripheral peripheral; + public static BlockCable cable; + public static BlockTurtle turtle; + public static BlockTurtle turtleExpanded; + public static BlockTurtle turtleAdvanced; + public static BlockCommandComputer commandComputer; + public static BlockAdvancedModem advancedModem; + } + + public static class Items + { + public static ItemDiskLegacy disk; + public static ItemDiskExpanded diskExpanded; + public static ItemPrintout printout; + public static ItemTreasureDisk treasureDisk; + public static ItemPocketComputer pocketComputer; + } + + public static class Upgrades + { + public static TurtleModem wirelessModem; + public static TurtleCraftingTable craftingTable; + public static TurtleSword diamondSword; + public static TurtleShovel diamondShovel; + public static TurtleTool diamondPickaxe; + public static TurtleAxe diamondAxe; + public static TurtleHoe diamondHoe; + public static TurtleModem advancedModem; + } + + // Registries + public static ClientComputerRegistry clientComputerRegistry = new ClientComputerRegistry(); + public static ServerComputerRegistry serverComputerRegistry = new ServerComputerRegistry(); + + // Networking + public static FMLEventChannel networkEventChannel; + + // Creative + public static CreativeTabMain mainCreativeTab; + + // API users + private static List peripheralProviders = new ArrayList(); + private static List bundledRedstoneProviders = new ArrayList(); + private static List mediaProviders = new ArrayList(); + private static List permissionProviders = new ArrayList(); + + // Implementation + @Mod.Instance( value = "ComputerCraft" ) + public static ComputerCraft instance; + + @SidedProxy( clientSide = "dan200.computercraft.client.proxy.ComputerCraftProxyClient", serverSide = "dan200.computercraft.server.proxy.ComputerCraftProxyServer" ) + public static IComputerCraftProxy proxy; + + @SidedProxy( clientSide = "dan200.computercraft.client.proxy.CCTurtleProxyClient", serverSide = "dan200.computercraft.server.proxy.CCTurtleProxyServer" ) + public static ICCTurtleProxy turtleProxy; + + public ComputerCraft() + { + } + + @Mod.EventHandler + public void preInit( FMLPreInitializationEvent event ) + { + // Load config + Configuration config = new Configuration( event.getSuggestedConfigurationFile() ); + config.load(); + + // Setup general + + Property prop = config.get(Configuration.CATEGORY_GENERAL, "http_enable", http_enable); + prop.comment = "Enable the \"http\" API on Computers (see \"http_whitelist\" for more fine grained control than this)"; + http_enable = prop.getBoolean(http_enable); + + prop = config.get(Configuration.CATEGORY_GENERAL, "http_whitelist", http_whitelist ); + prop.comment = "A semicolon limited list of wildcards for domains that can be accessed through the \"http\" API on Computers. Set this to \"*\" to access to the entire internet. Example: \"*.pastebin.com;*.github.com;*.computercraft.info\" will restrict access to just those 3 domains."; + http_whitelist = prop.getString(); + + prop = config.get(Configuration.CATEGORY_GENERAL, "disable_lua51_features", disable_lua51_features ); + prop.comment = "Set this to true to disable Lua 5.1 functions that will be removed in a future update. Useful for ensuring forward compatibility of your programs now."; + disable_lua51_features = prop.getBoolean( disable_lua51_features ); + + prop = config.get( Configuration.CATEGORY_GENERAL, "default_computer_settings", default_computer_settings ); + prop.comment = "A comma seperated list of default system settings to set on new computers. Example: \"shell.autocomplete=false,lua.autocomplete=false,edit.autocomplete=false\" will disable all autocompletion"; + default_computer_settings = prop.getString(); + + prop = config.get(Configuration.CATEGORY_GENERAL, "enableCommandBlock", enableCommandBlock); + prop.comment = "Enable Command Block peripheral support"; + enableCommandBlock = prop.getBoolean(enableCommandBlock); + + prop = config.get(Configuration.CATEGORY_GENERAL, "modem_range", modem_range); + prop.comment = "The range of Wireless Modems at low altitude in clear weather, in meters"; + modem_range = Math.min( prop.getInt(), 100000 ); + + prop = config.get(Configuration.CATEGORY_GENERAL, "modem_highAltitudeRange", modem_highAltitudeRange); + prop.comment = "The range of Wireless Modems at maximum altitude in clear weather, in meters"; + modem_highAltitudeRange = Math.min( prop.getInt(), 100000 ); + + prop = config.get(Configuration.CATEGORY_GENERAL, "modem_rangeDuringStorm", modem_rangeDuringStorm); + prop.comment = "The range of Wireless Modems at low altitude in stormy weather, in meters"; + modem_rangeDuringStorm = Math.min( prop.getInt(), 100000 ); + + prop = config.get(Configuration.CATEGORY_GENERAL, "modem_highAltitudeRangeDuringStorm", modem_highAltitudeRangeDuringStorm); + prop.comment = "The range of Wireless Modems at maximum altitude in stormy weather, in meters"; + modem_highAltitudeRangeDuringStorm = Math.min( prop.getInt(), 100000 ); + + prop = config.get(Configuration.CATEGORY_GENERAL, "computerSpaceLimit", computerSpaceLimit); + prop.comment = "The disk space limit for computers and turtles, in bytes"; + computerSpaceLimit = prop.getInt(); + + prop = config.get(Configuration.CATEGORY_GENERAL, "floppySpaceLimit", floppySpaceLimit); + prop.comment = "The disk space limit for floppy disks, in bytes"; + floppySpaceLimit = prop.getInt(); + + prop = config.get(Configuration.CATEGORY_GENERAL, "treasureDiskLootFrequency", treasureDiskLootFrequency); + prop.comment = "The frequency that treasure disks will be found in dungeon chests, from 0 to 100. Increase this value if running a modpack with lots of mods that add dungeon loot, or you just want more treasure disks. Set to 0 to disable treasure disks."; + treasureDiskLootFrequency = prop.getInt(); + + prop = config.get(Configuration.CATEGORY_GENERAL, "turtlesNeedFuel", turtlesNeedFuel); + prop.comment = "Set whether Turtles require fuel to move"; + turtlesNeedFuel = prop.getBoolean( turtlesNeedFuel ); + + prop = config.get(Configuration.CATEGORY_GENERAL, "turtleFuelLimit", turtleFuelLimit); + prop.comment = "The fuel limit for Turtles"; + turtleFuelLimit = prop.getInt( turtleFuelLimit ); + + prop = config.get(Configuration.CATEGORY_GENERAL, "advancedTurtleFuelLimit", advancedTurtleFuelLimit); + prop.comment = "The fuel limit for Advanced Turtles"; + advancedTurtleFuelLimit = prop.getInt(advancedTurtleFuelLimit); + + prop = config.get(Configuration.CATEGORY_GENERAL, "turtlesObeyBlockProtection", turtlesObeyBlockProtection); + prop.comment = "If set to true, Turtles will be unable to build, dig, or enter protected areas (such as near the server spawn point)"; + turtlesObeyBlockProtection = prop.getBoolean( turtlesObeyBlockProtection ); + + prop = config.get(Configuration.CATEGORY_GENERAL, "turtlesCanPush", turtlesCanPush); + prop.comment = "If set to true, Turtles will push entities out of the way instead of stopping if there is space to do so"; + turtlesCanPush = prop.getBoolean(turtlesCanPush); + + config.save(); + + // Setup network + networkEventChannel = NetworkRegistry.INSTANCE.newEventDrivenChannel( "CC" ); + networkEventChannel.register( new PacketHandler() ); + + proxy.preInit(); + turtleProxy.preInit(); + } + + @Mod.EventHandler + public void init( FMLInitializationEvent event ) + { + proxy.init(); + turtleProxy.init(); + } + + @Mod.EventHandler + public void onServerStarting( FMLServerStartingEvent event ) + { + ItemTreasureDisk.registerDungeonLoot(); + } + + @Mod.EventHandler + public void onServerStart( FMLServerStartedEvent event ) + { + if( FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER ) + { + ComputerCraft.serverComputerRegistry.reset(); + WirelessNetwork.resetNetworks(); + } + } + + @Mod.EventHandler + public void onServerStopped( FMLServerStoppedEvent event ) + { + if( FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER ) + { + ComputerCraft.serverComputerRegistry.reset(); + WirelessNetwork.resetNetworks(); + } + } + + public static String getVersion() + { + return "${version}"; + } + + public static boolean isClient() + { + return proxy.isClient(); + } + + public static boolean getGlobalCursorBlink() + { + return proxy.getGlobalCursorBlink(); + } + + public static long getRenderFrame() + { + return proxy.getRenderFrame(); + } + + public static void deleteDisplayLists( int list, int range ) + { + proxy.deleteDisplayLists( list, range ); + } + + public static Object getFixedWidthFontRenderer() + { + return proxy.getFixedWidthFontRenderer(); + } + + public static void playRecord( String record, String recordInfo, World world, BlockPos pos ) + { + proxy.playRecord( record, recordInfo, world, pos ); + } + + public static String getRecordInfo( ItemStack recordStack ) + { + return proxy.getRecordInfo( recordStack ); + } + + public static void openDiskDriveGUI( EntityPlayer player, TileDiskDrive drive ) + { + BlockPos pos = drive.getPos(); + player.openGui( ComputerCraft.instance, ComputerCraft.diskDriveGUIID, player.getEntityWorld(), pos.getX(), pos.getY(), pos.getZ() ); + } + + public static void openComputerGUI( EntityPlayer player, TileComputer computer ) + { + BlockPos pos = computer.getPos(); + player.openGui( ComputerCraft.instance, ComputerCraft.computerGUIID, player.getEntityWorld(), pos.getX(), pos.getY(), pos.getZ() ); + } + + public static void openPrinterGUI( EntityPlayer player, TilePrinter printer ) + { + BlockPos pos = printer.getPos(); + player.openGui( ComputerCraft.instance, ComputerCraft.printerGUIID, player.getEntityWorld(), pos.getX(), pos.getY(), pos.getZ() ); + } + + public static void openTurtleGUI( EntityPlayer player, TileTurtle turtle ) + { + BlockPos pos = turtle.getPos(); + player.openGui( instance, ComputerCraft.turtleGUIID, player.getEntityWorld(), pos.getX(), pos.getY(), pos.getZ() ); + } + + public static void openPrintoutGUI( EntityPlayer player ) + { + player.openGui( ComputerCraft.instance, ComputerCraft.printoutGUIID, player.getEntityWorld(), 0, 0, 0 ); + } + + public static void openPocketComputerGUI( EntityPlayer player ) + { + player.openGui( ComputerCraft.instance, ComputerCraft.pocketComputerGUIID, player.getEntityWorld(), 0, 0, 0 ); + } + + public static File getBaseDir() + { + return FMLCommonHandler.instance().getMinecraftServerInstance().getFile("."); + } + + public static File getResourcePackDir() + { + return new File( getBaseDir(), "resourcepacks" ); + } + + public static File getWorldDir( World world ) + { + return proxy.getWorldDir( world ); + } + + private static FMLProxyPacket encode( ComputerCraftPacket packet ) + { + PacketBuffer buffer = new PacketBuffer( Unpooled.buffer() ); + packet.toBytes( buffer ); + return new FMLProxyPacket( buffer, "CC" ); + } + + public static void sendToPlayer( EntityPlayer player, ComputerCraftPacket packet ) + { + networkEventChannel.sendTo( encode( packet ), (EntityPlayerMP)player ); + } + + public static void sendToAllPlayers( ComputerCraftPacket packet ) + { + networkEventChannel.sendToAll( encode( packet ) ); + } + + public static void sendToServer( ComputerCraftPacket packet ) + { + networkEventChannel.sendToServer( encode( packet ) ); + } + + public static void handlePacket( ComputerCraftPacket packet, EntityPlayer player ) + { + proxy.handlePacket( packet, player ); + } + + public static boolean canPlayerUseCommands( EntityPlayer player ) + { + MinecraftServer server = MinecraftServer.getServer(); + if( server != null ) + { + return server.getConfigurationManager().canSendCommands( player.getGameProfile() ); + } + return false; + } + + public static boolean isPlayerOpped( EntityPlayer player ) + { + MinecraftServer server = MinecraftServer.getServer(); + if( server != null ) + { + return server.getConfigurationManager().getOppedPlayers().getEntry( player.getGameProfile() ) != null; + } + return false; + } + + public static void registerPermissionProvider( ITurtlePermissionProvider provider ) + { + if( provider != null && !permissionProviders.contains( provider ) ) + { + permissionProviders.add( provider ); + } + } + + public static boolean isBlockEnterable( World world, BlockPos pos, EntityPlayer player ) + { + MinecraftServer server = MinecraftServer.getServer(); + if( server != null && !world.isRemote ) + { + if( server.isBlockProtected( world, pos, player ) ) + { + return false; + } + } + + for( int i=0; i it = peripheralProviders.iterator(); + while( it.hasNext() ) + { + try + { + IPeripheralProvider handler = it.next(); + IPeripheral peripheral = handler.getPeripheral( world, pos, side ); + if( peripheral != null ) + { + return peripheral; + } + } + catch( Exception e ) + { + // mod misbehaved, ignore it + } + } + return null; + } + + public static int getDefaultBundledRedstoneOutput( World world, BlockPos pos, EnumFacing side ) + { + if( WorldUtil.isBlockInWorld( world, pos ) ) + { + return DefaultBundledRedstoneProvider.getDefaultBundledRedstoneOutput( world, pos, side ); + } + return -1; + } + + public static int getBundledRedstoneOutput( World world, BlockPos pos, EnumFacing side ) + { + int y = pos.getY(); + if( y < 0 || y >= world.getHeight() ) + { + return -1; + } + + // Try the handlers in order: + int combinedSignal = -1; + Iterator it = bundledRedstoneProviders.iterator(); + while( it.hasNext() ) + { + try + { + IBundledRedstoneProvider handler = it.next(); + int signal = handler.getBundledRedstoneOutput( world, pos, side ); + if( signal >= 0 ) + { + if( combinedSignal < 0 ) + { + combinedSignal = (signal & 0xffff); + } + else + { + combinedSignal = combinedSignal | (signal & 0xffff); + } + } + } + catch( Exception e ) + { + // mod misbehaved, ignore it + } + } + return combinedSignal; + } + + public static IMedia getMedia( ItemStack stack ) + { + if( stack != null ) + { + // Try the handlers in order: + Iterator it = mediaProviders.iterator(); + while( it.hasNext() ) + { + try + { + IMediaProvider handler = it.next(); + IMedia media = handler.getMedia( stack ); + if( media != null ) + { + return media; + } + } + catch( Exception e ) + { + // mod misbehaved, ignore it + } + } + return null; + } + return null; + } + + public static int createUniqueNumberedSaveDir( World world, String parentSubPath ) + { + return IDAssigner.getNextIDFromDirectory(new File(getWorldDir(world), parentSubPath)); + } + + public static IWritableMount createSaveDirMount( World world, String subPath, long capacity ) + { + try + { + return new FileMount( new File( getWorldDir( world ), subPath ), capacity ); + } + catch( Exception e ) + { + return null; + } + } + + public static IMount createResourceMount( Class modClass, String domain, String subPath ) + { + // Start building list of mounts + List mounts = new ArrayList(); + subPath = "assets/" + domain + "/" + subPath; + + // Mount from debug dir + File codeDir = getDebugCodeDir( modClass ); + if( codeDir != null ) + { + File subResource = new File( codeDir, subPath ); + if( subResource.exists() ) + { + IMount resourcePackMount = new FileMount( subResource, 0 ); + mounts.add( resourcePackMount ); + } + } + + // Mount from mod jar + File modJar = getContainingJar( modClass ); + if( modJar != null ) + { + try + { + IMount jarMount = new JarMount( modJar, subPath ); + mounts.add( jarMount ); + } + catch( IOException e ) + { + // Ignore + } + } + + // Mount from resource packs + File resourcePackDir = getResourcePackDir(); + if( resourcePackDir.exists() && resourcePackDir.isDirectory() ) + { + String[] resourcePacks = resourcePackDir.list(); + for( int i=0; i= 2 ) + { + IMount[] mountArray = new IMount[ mounts.size() ]; + mounts.toArray( mountArray ); + return new ComboMount( mountArray ); + } + else if( mounts.size() == 1 ) + { + return mounts.get( 0 ); + } + else + { + return null; + } + } + + private static File getContainingJar( Class modClass ) + { + String path = modClass.getProtectionDomain().getCodeSource().getLocation().getPath(); + int bangIndex = path.indexOf( "!" ); + if( bangIndex >= 0 ) + { + path = path.substring( 0, bangIndex ); + } + + URL url; + try { + url = new URL( path ); + } catch (MalformedURLException e1) { + return null; + } + + File file; + try { + file = new File( url.toURI() ); + } catch(URISyntaxException e) { + file = new File( url.getPath() ); + } + return file; + } + + private static File getDebugCodeDir( Class modClass ) + { + String path = modClass.getProtectionDomain().getCodeSource().getLocation().getPath(); + int bangIndex = path.indexOf("!"); + if( bangIndex >= 0 ) + { + return null; + } + return new File( new File( path ).getParentFile(), "../.." ); + } + + public static void registerTurtleUpgrade( ITurtleUpgrade upgrade ) + { + turtleProxy.registerTurtleUpgrade( upgrade ); + } + + public static ITurtleUpgrade getTurtleUpgrade( String id ) + { + return turtleProxy.getTurtleUpgrade( id ); + } + + public static ITurtleUpgrade getTurtleUpgrade( int legacyID ) + { + return turtleProxy.getTurtleUpgrade( legacyID ); + } + + public static ITurtleUpgrade getTurtleUpgrade( ItemStack item ) + { + return turtleProxy.getTurtleUpgrade( item ); + } + + public static void addAllUpgradedTurtles( List list ) + { + turtleProxy.addAllUpgradedTurtles( list ); + } + + public static void setEntityDropConsumer( Entity entity, IEntityDropConsumer consumer ) + { + turtleProxy.setEntityDropConsumer( entity, consumer ); + } + + public static void clearEntityDropConsumer( Entity entity ) + { + turtleProxy.clearEntityDropConsumer( entity ); + } +} diff --git a/src/main/java/dan200/computercraft/api/ComputerCraftAPI.java b/src/main/java/dan200/computercraft/api/ComputerCraftAPI.java new file mode 100644 index 0000000000..48cf870142 --- /dev/null +++ b/src/main/java/dan200/computercraft/api/ComputerCraftAPI.java @@ -0,0 +1,317 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api; + +import dan200.computercraft.api.filesystem.IMount; +import dan200.computercraft.api.filesystem.IWritableMount; +import dan200.computercraft.api.media.IMediaProvider; +import dan200.computercraft.api.peripheral.IPeripheralProvider; +import dan200.computercraft.api.permissions.ITurtlePermissionProvider; +import dan200.computercraft.api.redstone.IBundledRedstoneProvider; +import dan200.computercraft.api.turtle.ITurtleUpgrade; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +import java.lang.reflect.Method; + +/** + * The static entry point to the ComputerCraft API. + * Members in this class must be called after mod_ComputerCraft has been initialised, + * but may be called before it is fully loaded. + */ +public final class ComputerCraftAPI +{ + public static boolean isInstalled() + { + findCC(); + return computerCraft != null; + } + + public static String getInstalledVersion() + { + findCC(); + if( computerCraft_getVersion != null ) + { + try { + return (String)computerCraft_getVersion.invoke( null ); + } catch (Exception e) { + // It failed + } + } + return ""; + } + + public static String getAPIVersion() + { + return "${version}"; + } + + /** + * Creates a numbered directory in a subfolder of the save directory for a given world, and returns that number.
+ * Use in conjuction with createSaveDirMount() to create a unique place for your peripherals or media items to store files.
+ * @param world The world for which the save dir should be created. This should be the serverside world object. + * @param parentSubPath The folder path within the save directory where the new directory should be created. eg: "computercraft/disk" + * @return The numerical value of the name of the new folder, or -1 if the folder could not be created for some reason.
+ * eg: if createUniqueNumberedSaveDir( world, "computer/disk" ) was called returns 42, then "computer/disk/42" is now available for writing. + * @see #createSaveDirMount(World, String, long) + */ + public static int createUniqueNumberedSaveDir( World world, String parentSubPath ) + { + findCC(); + if( computerCraft_createUniqueNumberedSaveDir != null ) + { + try { + return (Integer)computerCraft_createUniqueNumberedSaveDir.invoke( null, world, parentSubPath ); + } catch (Exception e) { + // It failed + } + } + return -1; + } + + /** + * Creates a file system mount that maps to a subfolder of the save directory for a given world, and returns it.
+ * Use in conjuction with IComputerAccess.mount() or IComputerAccess.mountWritable() to mount a folder from the + * users save directory onto a computers file system.
+ * @param world The world for which the save dir can be found. This should be the serverside world object. + * @param subPath The folder path within the save directory that the mount should map to. eg: "computer/disk/42".
+ * Use createUniqueNumberedSaveDir() to create a new numbered folder to use. + * @param capacity The ammount of data that can be stored in the directory before it fills up, in bytes. + * @return The mount, or null if it could be created for some reason. Use IComputerAccess.mount() or IComputerAccess.mountWritable() + * to mount this on a Computers' file system. + * @see #createUniqueNumberedSaveDir(World, String) + * @see dan200.computercraft.api.peripheral.IComputerAccess#mount(String, dan200.computercraft.api.filesystem.IMount) + * @see dan200.computercraft.api.peripheral.IComputerAccess#mountWritable(String, dan200.computercraft.api.filesystem.IWritableMount) + * @see dan200.computercraft.api.filesystem.IMount + * @see IWritableMount + */ + public static IWritableMount createSaveDirMount( World world, String subPath, long capacity ) + { + findCC(); + if( computerCraft_createSaveDirMount != null ) + { + try { + return (IWritableMount)computerCraft_createSaveDirMount.invoke( null, world, subPath, capacity ); + } catch (Exception e){ + // It failed + } + } + return null; + } + + /** + * Creates a file system mount to a resource folder, and returns it.
+ * Use in conjuction with IComputerAccess.mount() or IComputerAccess.mountWritable() to mount a resource folder onto a computers file system.
+ * The files in this mount will be a combination of files in the specified mod jar, and resource packs that contain resources with the same domain and path.
+ * @param modClass A class in whose jar to look first for the resources to mount. Using your main mod class is recommended. eg: MyMod.class + * @param domain The domain under which to look for resources. eg: "mymod" + * @param subPath The domain under which to look for resources. eg: "mymod/lua/myfiles" + * @return The mount, or null if it could be created for some reason. Use IComputerAccess.mount() or IComputerAccess.mountWritable() + * to mount this on a Computers' file system. + * @see dan200.computercraft.api.peripheral.IComputerAccess#mount(String, dan200.computercraft.api.filesystem.IMount) + * @see dan200.computercraft.api.peripheral.IComputerAccess#mountWritable(String, IWritableMount) + * @see dan200.computercraft.api.filesystem.IMount + */ + public static IMount createResourceMount( Class modClass, String domain, String subPath ) + { + findCC(); + if( computerCraft_createResourceMount != null ) + { + try { + return (IMount)computerCraft_createResourceMount.invoke( null, modClass, domain, subPath ); + } catch (Exception e){ + // It failed + } + } + return null; + } + + /** + * Registers a peripheral handler to convert blocks into IPeripheral implementations. + * @see dan200.computercraft.api.peripheral.IPeripheral + * @see dan200.computercraft.api.peripheral.IPeripheralProvider + */ + public static void registerPeripheralProvider( IPeripheralProvider handler ) + { + findCC(); + if ( computerCraft_registerPeripheralProvider != null) + { + try { + computerCraft_registerPeripheralProvider.invoke( null, handler ); + } catch (Exception e){ + // It failed + } + } + } + + /** + * Registers a new turtle turtle for use in ComputerCraft. After calling this, + * users should be able to craft Turtles with your new turtle. It is recommended to call + * this during the load() method of your mod. + * @see dan200.computercraft.api.turtle.ITurtleUpgrade + */ + public static void registerTurtleUpgrade( ITurtleUpgrade upgrade ) + { + if( upgrade != null ) + { + findCC(); + if( computerCraft_registerTurtleUpgrade != null ) + { + try { + computerCraft_registerTurtleUpgrade.invoke( null, upgrade ); + } catch( Exception e ) { + // It failed + } + } + } + } + + /** + * Registers a bundled redstone handler to provide bundled redstone output for blocks + * @see dan200.computercraft.api.redstone.IBundledRedstoneProvider + */ + public static void registerBundledRedstoneProvider( IBundledRedstoneProvider handler ) + { + findCC(); + if( computerCraft_registerBundledRedstoneProvider != null ) + { + try { + computerCraft_registerBundledRedstoneProvider.invoke( null, handler ); + } catch (Exception e) { + // It failed + } + } + } + + /** + * If there is a Computer or Turtle at a certain position in the world, get it's bundled redstone output. + * @see dan200.computercraft.api.redstone.IBundledRedstoneProvider + * @return If there is a block capable of emitting bundled redstone at the location, it's signal (0-65535) will be returned. + * If there is no block capable of emitting bundled redstone at the location, -1 will be returned. + */ + public static int getBundledRedstoneOutput( World world, BlockPos pos, EnumFacing side ) + { + findCC(); + if( computerCraft_getDefaultBundledRedstoneOutput != null ) + { + try { + return (Integer)computerCraft_getDefaultBundledRedstoneOutput.invoke( null, world, pos, side ); + } catch (Exception e){ + // It failed + } + } + return -1; + } + + /** + * Registers a media handler to provide IMedia implementations for Items + * @see dan200.computercraft.api.media.IMediaProvider + */ + public static void registerMediaProvider( IMediaProvider handler ) + { + findCC(); + if( computerCraft_registerMediaProvider != null ) + { + try { + computerCraft_registerMediaProvider.invoke( null, handler ); + } catch (Exception e){ + // It failed + } + } + } + + /** + * Registers a permission handler to restrict where turtles can move or build + * @see dan200.computercraft.api.permissions.ITurtlePermissionProvider + */ + public static void registerPermissionProvider( ITurtlePermissionProvider handler ) + { + findCC(); + if( computerCraft_registerPermissionProvider != null ) + { + try { + computerCraft_registerPermissionProvider.invoke( null, handler ); + } catch (Exception e) { + // It failed + } + } + } + + // The functions below here are private, and are used to interface with the non-API ComputerCraft classes. + // Reflection is used here so you can develop your mod without decompiling ComputerCraft and including + // it in your solution, and so your mod won't crash if ComputerCraft is installed. + + private static void findCC() + { + if( !ccSearched ) { + try { + computerCraft = Class.forName( "dan200.computercraft.ComputerCraft" ); + computerCraft_getVersion = findCCMethod( "getVersion", new Class[]{ + } ); + computerCraft_createUniqueNumberedSaveDir = findCCMethod( "createUniqueNumberedSaveDir", new Class[]{ + World.class, String.class + } ); + computerCraft_createSaveDirMount = findCCMethod( "createSaveDirMount", new Class[] { + World.class, String.class, Long.TYPE + } ); + computerCraft_createResourceMount = findCCMethod( "createResourceMount", new Class[] { + Class.class, String.class, String.class + } ); + computerCraft_registerPeripheralProvider = findCCMethod( "registerPeripheralProvider", new Class[] { + IPeripheralProvider.class + } ); + computerCraft_registerTurtleUpgrade = findCCMethod( "registerTurtleUpgrade", new Class[] { + ITurtleUpgrade.class + } ); + computerCraft_registerBundledRedstoneProvider = findCCMethod( "registerBundledRedstoneProvider", new Class[] { + IBundledRedstoneProvider.class + } ); + computerCraft_getDefaultBundledRedstoneOutput = findCCMethod( "getDefaultBundledRedstoneOutput", new Class[] { + World.class, BlockPos.class, EnumFacing.class + } ); + computerCraft_registerMediaProvider = findCCMethod( "registerMediaProvider", new Class[] { + IMediaProvider.class + } ); + computerCraft_registerPermissionProvider = findCCMethod( "registerPermissionProvider", new Class[] { + ITurtlePermissionProvider.class + } ); + } catch( Exception e ) { + System.out.println( "ComputerCraftAPI: ComputerCraft not found." ); + } finally { + ccSearched = true; + } + } + } + + private static Method findCCMethod( String name, Class[] args ) + { + try { + if( computerCraft != null ) + { + return computerCraft.getMethod( name, args ); + } + return null; + } catch( NoSuchMethodException e ) { + System.out.println( "ComputerCraftAPI: ComputerCraft method " + name + " not found." ); + return null; + } + } + + private static boolean ccSearched = false; + private static Class computerCraft = null; + private static Method computerCraft_getVersion = null; + private static Method computerCraft_createUniqueNumberedSaveDir = null; + private static Method computerCraft_createSaveDirMount = null; + private static Method computerCraft_createResourceMount = null; + private static Method computerCraft_registerPeripheralProvider = null; + private static Method computerCraft_registerTurtleUpgrade = null; + private static Method computerCraft_registerBundledRedstoneProvider = null; + private static Method computerCraft_getDefaultBundledRedstoneOutput = null; + private static Method computerCraft_registerMediaProvider = null; + private static Method computerCraft_registerPermissionProvider = null; +} diff --git a/src/main/java/dan200/computercraft/api/filesystem/IMount.java b/src/main/java/dan200/computercraft/api/filesystem/IMount.java new file mode 100644 index 0000000000..1538edbed5 --- /dev/null +++ b/src/main/java/dan200/computercraft/api/filesystem/IMount.java @@ -0,0 +1,57 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.filesystem; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +/** + * Represents a read only part of a virtual filesystem that can be mounted onto a computercraft using IComputerAccess.mount(). + * Ready made implementations of this interface can be created using ComputerCraftAPI.createSaveDirMount() or ComputerCraftAPI.createResourceMount(), or you're free to implement it yourselves! + * @see dan200.computercraft.api.ComputerCraftAPI#createSaveDirMount(World, String) + * @see dan200.computercraft.api.ComputerCraftAPI#createResourceMount(Class, String, String) + * @see dan200.computercraft.api.peripheral.IComputerAccess#mount(String, IMount) + * @see IWritableMount + */ +public interface IMount +{ + /** + * Returns whether a file with a given path exists or not. + * @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram" + * @return true if the file exists, false otherwise + */ + public boolean exists( String path ) throws IOException; + + /** + * Returns whether a file with a given path is a directory or not. + * @param path A file path in normalised format, relative to the mount location. ie: "programs/myprograms" + * @return true if the file exists and is a directory, false otherwise + */ + public boolean isDirectory( String path ) throws IOException; + + /** + * Returns the file names of all the files in a directory. + * @param path A file path in normalised format, relative to the mount location. ie: "programs/myprograms" + * @param contents A list of strings. Add all the file names to this list + */ + public void list( String path, List contents ) throws IOException; + + /** + * Returns the size of a file with a given path, in bytes + * @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram" + * @return the size of the file, in bytes + */ + public long getSize( String path ) throws IOException; + + /** + * Opens a file with a given path, and returns an inputstream representing it's contents. + * @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram" + * @return a stream representing the contents of the file + */ + public InputStream openForRead( String path ) throws IOException; +} diff --git a/src/main/java/dan200/computercraft/api/filesystem/IWritableMount.java b/src/main/java/dan200/computercraft/api/filesystem/IWritableMount.java new file mode 100644 index 0000000000..f8053d070a --- /dev/null +++ b/src/main/java/dan200/computercraft/api/filesystem/IWritableMount.java @@ -0,0 +1,52 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.filesystem; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * Represents a part of a virtual filesystem that can be mounted onto a computercraft using IComputerAccess.mount() or IComputerAccess.mountWritable(), that can also be written to. + * Ready made implementations of this interface can be created using ComputerCraftAPI.createSaveDirMount(), or you're free to implement it yourselves! + * @see dan200.computercraft.api.ComputerCraftAPI#createSaveDirMount(World, String) + * @see dan200.computercraft.api.peripheral.IComputerAccess#mountWritable(String, dan200.computercraft.api.filesystem.IMount) + * @see dan200.computercraft.api.filesystem.IMount + */ +public interface IWritableMount extends IMount +{ + /** + * Creates a directory at a given path inside the virtual file system. + * @param path A file path in normalised format, relative to the mount location. ie: "programs/mynewprograms" + */ + public void makeDirectory( String path ) throws IOException; + + /** + * Deletes a directory at a given path inside the virtual file system. + * @param path A file path in normalised format, relative to the mount location. ie: "programs/myoldprograms" + */ + public void delete( String path ) throws IOException; + + /** + * Opens a file with a given path, and returns an outputstream for writing to it. + * @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram" + * @return a stream for writing to + */ + public OutputStream openForWrite( String path ) throws IOException; + + /** + * Opens a file with a given path, and returns an outputstream for appending to it. + * @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram" + * @return a stream for writing to + */ + public OutputStream openForAppend( String path ) throws IOException; + + /** + * Get the ammount of free space on the mount, in bytes. You should decrease this value as the user writes to the mount, and write operations should fail once it reaches zero. + * @return The ammount of free space, in bytes. + */ + public long getRemainingSpace() throws IOException; +} diff --git a/src/main/java/dan200/computercraft/api/filesystem/package-info.java b/src/main/java/dan200/computercraft/api/filesystem/package-info.java new file mode 100644 index 0000000000..bd0b57710f --- /dev/null +++ b/src/main/java/dan200/computercraft/api/filesystem/package-info.java @@ -0,0 +1,10 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +@API( owner="ComputerCraft", provides="ComputerCraft|API|FileSystem", apiVersion="${version}" ) +package dan200.computercraft.api.filesystem; + +import net.minecraftforge.fml.common.API; \ No newline at end of file diff --git a/src/main/java/dan200/computercraft/api/lua/ILuaContext.java b/src/main/java/dan200/computercraft/api/lua/ILuaContext.java new file mode 100644 index 0000000000..fe821e90ce --- /dev/null +++ b/src/main/java/dan200/computercraft/api/lua/ILuaContext.java @@ -0,0 +1,58 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.lua; + +/** + * An interface passed to peripherals and ILuaObjects' by computers or turtles, providing methods + * that allow the peripheral call to wait for events before returning, just like in lua. + * This is very useful if you need to signal work to be performed on the main thread, and don't want to return + * until the work has been completed. + */ +public interface ILuaContext +{ + /** + * Wait for an event to occur on the computercraft, suspending the thread until it arises. This method is exactly equivalent to os.pullEvent() in lua. + * @param filter A specific event to wait for, or null to wait for any event + * @return An object array containing the name of the event that occurred, and any event parameters + * @throws Exception If the user presses CTRL+T to terminate the current program while pullEvent() is waiting for an event, a "Terminated" exception will be thrown here. + * Do not attempt to common this exception, unless you wish to prevent termination, which is not recommended. + * @throws InterruptedException If the user shuts down or reboots the computercraft while pullEvent() is waiting for an event, InterruptedException will be thrown. This exception must not be caught or intercepted, or the computercraft will leak memory and end up in a broken state. + */ + public Object[] pullEvent( String filter ) throws LuaException, InterruptedException; + + /** + * The same as pullEvent(), except "terminated" events are ignored. Only use this if you want to prevent program termination, which is not recommended. This method is exactly equivalent to os.pullEventRaw() in lua. + * @param filter A specific event to wait for, or null to wait for any event + * @return An object array containing the name of the event that occurred, and any event parameters + * @throws InterruptedException If the user shuts down or reboots the computercraft while pullEventRaw() is waiting for an event, InterruptedException will be thrown. This exception must not be caught or intercepted, or the computercraft will leak memory and end up in a broken state. + * @see #pullEvent(String) + */ + public Object[] pullEventRaw( String filter ) throws InterruptedException; + + /** + * Yield the current coroutine with some arguments until it is resumed. This method is exactly equivalent to coroutine.yield() in lua. Use pullEvent() if you wish to wait for events. + * @param arguments An object array containing the arguments to pass to coroutine.yield() + * @return An object array containing the return values from coroutine.yield() + * @throws InterruptedException If the user shuts down or reboots the computercraft the coroutine is suspended, InterruptedException will be thrown. This exception must not be caught or intercepted, or the computercraft will leak memory and end up in a broken state. + * @see #pullEvent(String) + */ + public Object[] yield( Object[] arguments ) throws InterruptedException; + + /** + * TODO: Document me + * @param task + * @return + */ + public Object[] executeMainThreadTask( ILuaTask task ) throws LuaException, InterruptedException; + + /** + * TODO: Document me + * @param task + * @return + */ + public long issueMainThreadTask( ILuaTask task ) throws LuaException; +} diff --git a/src/main/java/dan200/computercraft/api/lua/ILuaObject.java b/src/main/java/dan200/computercraft/api/lua/ILuaObject.java new file mode 100644 index 0000000000..e795a36aad --- /dev/null +++ b/src/main/java/dan200/computercraft/api/lua/ILuaObject.java @@ -0,0 +1,26 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.lua; + +/** + * An interface for representing custom objects returned by IPeripheral.callMethod() calls. + * Return objects implementing this interface to expose objects with methods to lua. + */ +public interface ILuaObject +{ + /** + * Get the names of the methods that this object implements. This works the same as IPeripheral.getMethodNames(). See that method for detailed documentation. + * @see dan200.computercraft.api.peripheral.IPeripheral#getMethodNames() + */ + public String[] getMethodNames(); + + /** + * Called when a user calls one of the methods that this object implements. This works the same as IPeripheral.callMethod(). See that method for detailed documentation. + * @see dan200.computercraft.api.peripheral.IPeripheral#callMethod(dan200.computercraft.api.peripheral.IComputerAccess, ILuaContext, int, Object[]) + */ + public Object[] callMethod( ILuaContext context, int method, Object[] arguments ) throws LuaException, InterruptedException; +} diff --git a/src/main/java/dan200/computercraft/api/lua/ILuaTask.java b/src/main/java/dan200/computercraft/api/lua/ILuaTask.java new file mode 100644 index 0000000000..fa7df16345 --- /dev/null +++ b/src/main/java/dan200/computercraft/api/lua/ILuaTask.java @@ -0,0 +1,12 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.lua; + +public interface ILuaTask +{ + public Object[] execute() throws LuaException; +} diff --git a/src/main/java/dan200/computercraft/api/lua/LuaException.java b/src/main/java/dan200/computercraft/api/lua/LuaException.java new file mode 100644 index 0000000000..75741d1e41 --- /dev/null +++ b/src/main/java/dan200/computercraft/api/lua/LuaException.java @@ -0,0 +1,36 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.lua; + +/** + * An exception representing an error in Lua, like that raised by the error() function + */ +public class LuaException extends Exception +{ + private final int m_level; + + public LuaException() + { + this( "error", 1 ); + } + + public LuaException( String message ) + { + this( message, 1 ); + } + + public LuaException( String message, int level ) + { + super( message ); + m_level = level; + } + + public int getLevel() + { + return m_level; + } +} diff --git a/src/main/java/dan200/computercraft/api/lua/package-info.java b/src/main/java/dan200/computercraft/api/lua/package-info.java new file mode 100644 index 0000000000..0d418d3c3c --- /dev/null +++ b/src/main/java/dan200/computercraft/api/lua/package-info.java @@ -0,0 +1,10 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +@API( owner="ComputerCraft", provides="ComputerCraft|API|Lua", apiVersion="${version}" ) +package dan200.computercraft.api.lua; + +import net.minecraftforge.fml.common.API; diff --git a/src/main/java/dan200/computercraft/api/media/IMedia.java b/src/main/java/dan200/computercraft/api/media/IMedia.java new file mode 100644 index 0000000000..75c6b64333 --- /dev/null +++ b/src/main/java/dan200/computercraft/api/media/IMedia.java @@ -0,0 +1,59 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.media; + +import dan200.computercraft.api.filesystem.IMount; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; + +/** + * Represents an item that can be placed in a disk drive and used by a Computer. + * Implement this interface on your Item class to allow it to be used in the drive. + */ +public interface IMedia +{ + /** + * Get a string representing the label of this item. Will be called vi disk.getLabel() in lua. + * @param stack The itemstack to inspect + * @return The label. ie: "Dan's Programs" + */ + public String getLabel( ItemStack stack ); + + /** + * Set a string representing the label of this item. Will be called vi disk.setLabel() in lua. + * @param stack The itemstack to modify. + * @param label The string to set the label to. + * @return true if the label was updated, false if the label may not be modified. + */ + public boolean setLabel( ItemStack stack, String label ); + + /** + * If this disk represents an item with audio (like a record), get the readable name of the audio track. ie: "Jonathon Coulton - Still Alive" + * @param stack The itemstack to inspect. + * @return The name, or null if this item does not represent an item with audio. + */ + public String getAudioTitle( ItemStack stack ); + + /** + * If this disk represents an item with audio (like a record), get the resource name of the audio track to play. + * @param stack The itemstack to inspect. + * @return The name, or null if this item does not represent an item with audio. + */ + public String getAudioRecordName( ItemStack stack ); + + /** + * If this disk represents an item with data (like a floppy disk), get a mount representing it's contents. This will be mounted onto the filesystem of the computercraft while the media is in the disk drive. + * @param stack The itemstack to inspect. + * @param world The world in which the item and disk drive reside. + * @return The mount, or null if this item does not represent an item with data. If the IMount returned also implements IWritableMount, it will mounted using mountWritable() + * @see dan200.computercraft.api.filesystem.IMount + * @see dan200.computercraft.api.filesystem.IWritableMount + * @see dan200.computercraft.api.ComputerCraftAPI#createSaveDirMount(World, String, long) + * @see dan200.computercraft.api.ComputerCraftAPI#createResourceMount(Class, String, String) + */ + public IMount createDataMount( ItemStack stack, World world ); +} diff --git a/src/main/java/dan200/computercraft/api/media/IMediaProvider.java b/src/main/java/dan200/computercraft/api/media/IMediaProvider.java new file mode 100644 index 0000000000..3abe1d49fb --- /dev/null +++ b/src/main/java/dan200/computercraft/api/media/IMediaProvider.java @@ -0,0 +1,23 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.media; + +import net.minecraft.item.ItemStack; + +/** + * This interface is used to provide IMedia implementations for ItemStack + * @see dan200.computercraft.api.ComputerCraftAPI#registerMediaProvider(IMediaProvider) + */ +public interface IMediaProvider +{ + /** + * Produce an IMedia implementation from an ItemStack. + * @see dan200.computercraft.api.ComputerCraftAPI#registerMediaProvider(IMediaProvider) + * @return an IMedia implementation, or null if the item is not something you wish to handle + */ + public IMedia getMedia( ItemStack stack ); +} diff --git a/src/main/java/dan200/computercraft/api/media/package-info.java b/src/main/java/dan200/computercraft/api/media/package-info.java new file mode 100644 index 0000000000..856053bb42 --- /dev/null +++ b/src/main/java/dan200/computercraft/api/media/package-info.java @@ -0,0 +1,10 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +@API( owner="ComputerCraft", provides="ComputerCraft|API|Media", apiVersion="${version}" ) +package dan200.computercraft.api.media; + +import net.minecraftforge.fml.common.API; diff --git a/src/main/java/dan200/computercraft/api/package-info.java b/src/main/java/dan200/computercraft/api/package-info.java new file mode 100644 index 0000000000..83ef25e579 --- /dev/null +++ b/src/main/java/dan200/computercraft/api/package-info.java @@ -0,0 +1,10 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +@API( owner="ComputerCraft", provides="ComputerCraft|API", apiVersion="${version}" ) +package dan200.computercraft.api; + +import net.minecraftforge.fml.common.API; \ No newline at end of file diff --git a/src/main/java/dan200/computercraft/api/peripheral/IComputerAccess.java b/src/main/java/dan200/computercraft/api/peripheral/IComputerAccess.java new file mode 100644 index 0000000000..baca44395b --- /dev/null +++ b/src/main/java/dan200/computercraft/api/peripheral/IComputerAccess.java @@ -0,0 +1,102 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.peripheral; + +import dan200.computercraft.api.filesystem.IMount; +import dan200.computercraft.api.filesystem.IWritableMount; + +/** + * The interface passed to peripherals by computers or turtles, providing methods + * that they can call. This should not be implemented by your classes. Do not interact + * with computers except via this interface. + */ +public interface IComputerAccess +{ + /** + * Mount a mount onto the computers' file system in a read only mode.
+ * @param desiredLocation The location on the computercraft's file system where you would like the mount to be mounted. + * @param mount The mount object to mount on the computercraft. These can be obtained by calling ComputerCraftAPI.createSaveDirMount(), ComputerCraftAPI.createResourceMount() or by creating your own objects that implement the IMount interface. + * @return The location on the computercraft's file system where you the mount mounted, or null if there was already a file in the desired location. Store this value if you wish to unmount the mount later. + * @see dan200.computercraft.api.ComputerCraftAPI#createSaveDirMount(World, String) + * @see dan200.computercraft.api.ComputerCraftAPI#createResourceMount(Class, String, String) + * @see #mountWritable(String, dan200.computercraft.api.filesystem.IWritableMount) + * @see #unmount(String) + * @see dan200.computercraft.api.filesystem.IMount + */ + public String mount( String desiredLocation, IMount mount ); + + /** + * TODO: Document me + */ + public String mount( String desiredLocation, IMount mount, String driveName ); + + /** + * Mount a mount onto the computers' file system in a writable mode.
+ * @param desiredLocation The location on the computercraft's file system where you would like the mount to be mounted. + * @param mount The mount object to mount on the computercraft. These can be obtained by calling ComputerCraftAPI.createSaveDirMount() or by creating your own objects that implement the IWritableMount interface. + * @return The location on the computercraft's file system where you the mount mounted, or null if there was already a file in the desired location. Store this value if you wish to unmount the mount later. + * @see dan200.computercraft.api.ComputerCraftAPI#createSaveDirMount(World, String) + * @see dan200.computercraft.api.ComputerCraftAPI#createResourceMount(Class, String, String) + * @see #mount(String, IMount) + * @see #unmount(String) + * @see IMount + */ + public String mountWritable( String desiredLocation, IWritableMount mount ); + + /** + * TODO: Document me + */ + public String mountWritable( String desiredLocation, IWritableMount mount, String driveName ); + + /** + * Unmounts a directory previously mounted onto the computers file system by mount() or mountWritable().
+ * When a directory is unmounted, it will disappear from the computers file system, and the user will no longer be able to + * access it. All directories mounted by a mount or mountWritable are automatically unmounted when the peripheral + * is attached if they have not been explicitly unmounted. + * @param location The desired location in the computers file system of the directory to unmount. + * This must be the location of a directory previously mounted by mount() or mountWritable(), as + * indicated by their return value. + * @see #mount(String, IMount) + * @see #mountWritable(String, IWritableMount) + */ + public void unmount( String location ); + + /** + * Returns the numerical ID of this computercraft.
+ * This is the same number obtained by calling os.getComputerID() or running the "id" program from lua, + * and is guarunteed unique. This number will be positive. + * @return The identifier. + */ + public int getID(); + + /** + * Causes an event to be raised on this computercraft, which the computercraft can respond to by calling + * os.pullEvent(). This can be used to notify the computercraft when things happen in the world or to + * this peripheral. + * @param event A string identifying the type of event that has occurred, this will be + * returned as the first value from os.pullEvent(). It is recommended that you + * you choose a name that is unique, and recognisable as originating from your + * peripheral. eg: If your peripheral type is "button", a suitable event would be + * "button_pressed". + * @param arguments In addition to a name, you may pass an array of extra arguments to the event, that will + * be supplied as extra return values to os.pullEvent(). Objects in the array will be converted + * to lua data types in the same fashion as the return values of IPeripheral.callMethod().
+ * You may supply null to indicate that no arguments are to be supplied. + * @see dan200.computercraft.api.peripheral.IPeripheral#callMethod + */ + public void queueEvent( String event, Object[] arguments ); + + /** + * Get a string, unique to the computercraft, by which the computercraft refers to this peripheral. + * For directly attached peripherals this will be "left","right","front","back",etc, but + * for peripherals attached remotely it will be different. It is good practice to supply + * this string when raising events to the computercraft, so that the computercraft knows from + * which peripheral the event came. + * @return A string unique to the computercraft, but not globally. + */ + public String getAttachmentName(); +} diff --git a/src/main/java/dan200/computercraft/api/peripheral/IPeripheral.java b/src/main/java/dan200/computercraft/api/peripheral/IPeripheral.java new file mode 100644 index 0000000000..12381814ae --- /dev/null +++ b/src/main/java/dan200/computercraft/api/peripheral/IPeripheral.java @@ -0,0 +1,98 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.peripheral; + +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.LuaException; + +/** + * The interface that defines a peripheral. See IPeripheralProvider for how to associate blocks with peripherals. + */ +public interface IPeripheral +{ + /** + * Should return a string that uniquely identifies this type of peripheral. + * This can be queried from lua by calling peripheral.getType() + * @return A string identifying the type of peripheral. + */ + public String getType(); + + /** + * Should return an array of strings that identify the methods that this + * peripheral exposes to Lua. This will be called once before each attachment, + * and should not change when called multiple times. + * @return An array of strings representing method names. + * @see #callMethod + */ + public String[] getMethodNames(); + + /** + * This is called when a lua program on an attached computercraft calls peripheral.call() with + * one of the methods exposed by getMethodNames().
+ *
+ * Be aware that this will be called from the ComputerCraft Lua thread, and must be thread-safe + * when interacting with minecraft objects. + * @param computer The interface to the computercraft that is making the call. Remember that multiple + * computers can be attached to a peripheral at once. + * @param context The context of the currently running lua thread. This can be used to wait for events + * or otherwise yield. + * @param method An integer identifying which of the methods from getMethodNames() the computercraft + * wishes to call. The integer indicates the index into the getMethodNames() table + * that corresponds to the string passed into peripheral.call() + * @param arguments An array of objects, representing the arguments passed into peripheral.call().
+ * Lua values of type "string" will be represented by Object type String.
+ * Lua values of type "number" will be represented by Object type Double.
+ * Lua values of type "boolean" will be represented by Object type Boolean.
+ * Lua values of any other type will be represented by a null object.
+ * This array will be empty if no arguments are passed. + * @return An array of objects, representing values you wish to return to the lua program.
+ * Integers, Doubles, Floats, Strings, Booleans and null be converted to their corresponding lua type.
+ * All other types will be converted to nil.
+ * You may return null to indicate no values should be returned. + * @throws Exception If you throw any exception from this function, a lua error will be raised with the + * same message as your exception. Use this to throw appropriate errors if the wrong + * arguments are supplied to your method. + * @see #getMethodNames + */ + public Object[] callMethod( IComputerAccess computer, ILuaContext context, int method, Object[] arguments ) throws LuaException, InterruptedException; + + /** + * Is called when canAttachToSide has returned true, and a computercraft is attaching to the peripheral. + * This will occur when a peripheral is placed next to an active computercraft, when a computercraft is turned on next to a peripheral, + * or when a turtle travels into a square next to a peripheral. + * Between calls to attach() and detach(), the attached computercraft can make method calls on the peripheral using peripheral.call(). + * This method can be used to keep track of which computers are attached to the peripheral, or to take action when attachment + * occurs.
+ *
+ * Be aware that this will be called from the ComputerCraft Lua thread, and must be thread-safe + * when interacting with minecraft objects. + * @param computer The interface to the computercraft that is being attached. Remember that multiple + * computers can be attached to a peripheral at once. + * @see #detach + */ + public void attach( IComputerAccess computer ); + + /** + * Is called when a computercraft is detaching from the peripheral. + * This will occur when a computercraft shuts down, when the peripheral is removed while attached to computers, + * or when a turtle moves away from a square attached to a peripheral. + * This method can be used to keep track of which computers are attached to the peripheral, or to take action when detachment + * occurs.
+ *
+ * Be aware that this will be called from the ComputerCraft Lua thread, and must be thread-safe + * when interacting with minecraft objects. + * @param computer The interface to the computercraft that is being detached. Remember that multiple + * computers can be attached to a peripheral at once. + * @see #detach + */ + public void detach( IComputerAccess computer ); + + /** + * TODO: Document me + */ + public boolean equals( IPeripheral other ); +} diff --git a/src/main/java/dan200/computercraft/api/peripheral/IPeripheralProvider.java b/src/main/java/dan200/computercraft/api/peripheral/IPeripheralProvider.java new file mode 100644 index 0000000000..49ce88e119 --- /dev/null +++ b/src/main/java/dan200/computercraft/api/peripheral/IPeripheralProvider.java @@ -0,0 +1,25 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.peripheral; + +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +/** + * This interface is used to create peripheral implementations for blocks + * @see dan200.computercraft.api.ComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider) + */ +public interface IPeripheralProvider +{ + /** + * Produce an peripheral implementation from a block location. + * @see dan200.computercraft.api.ComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider) + * @return a peripheral, or null if there is not a peripheral here you'd like to handle. + */ + public IPeripheral getPeripheral( World world, BlockPos pos, EnumFacing side ); +} diff --git a/src/main/java/dan200/computercraft/api/peripheral/package-info.java b/src/main/java/dan200/computercraft/api/peripheral/package-info.java new file mode 100644 index 0000000000..7536867b60 --- /dev/null +++ b/src/main/java/dan200/computercraft/api/peripheral/package-info.java @@ -0,0 +1,10 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +@API( owner="ComputerCraft", provides="ComputerCraft|API|Peripheral", apiVersion="${version}" ) +package dan200.computercraft.api.peripheral; + +import net.minecraftforge.fml.common.API; diff --git a/src/main/java/dan200/computercraft/api/permissions/ITurtlePermissionProvider.java b/src/main/java/dan200/computercraft/api/permissions/ITurtlePermissionProvider.java new file mode 100644 index 0000000000..1afc0fea6d --- /dev/null +++ b/src/main/java/dan200/computercraft/api/permissions/ITurtlePermissionProvider.java @@ -0,0 +1,20 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.permissions; + +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +/** + * This interface is used to restrict where turtles can move or build + * @see dan200.computercraft.api.ComputerCraftAPI#registerPermissionProvider(ITurtlePermissionProvider) + */ +public interface ITurtlePermissionProvider +{ + public boolean isBlockEnterable( World world, BlockPos pos ); + public boolean isBlockEditable( World world, BlockPos pos ); +} diff --git a/src/main/java/dan200/computercraft/api/permissions/package-info.java b/src/main/java/dan200/computercraft/api/permissions/package-info.java new file mode 100755 index 0000000000..d39021728a --- /dev/null +++ b/src/main/java/dan200/computercraft/api/permissions/package-info.java @@ -0,0 +1,10 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +@API( owner="ComputerCraft", provides="ComputerCraft|API|Permissions", apiVersion="${version}" ) +package dan200.computercraft.api.permissions; + +import net.minecraftforge.fml.common.API; \ No newline at end of file diff --git a/src/main/java/dan200/computercraft/api/redstone/IBundledRedstoneProvider.java b/src/main/java/dan200/computercraft/api/redstone/IBundledRedstoneProvider.java new file mode 100644 index 0000000000..8893ec6951 --- /dev/null +++ b/src/main/java/dan200/computercraft/api/redstone/IBundledRedstoneProvider.java @@ -0,0 +1,25 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.redstone; + +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +/** + * This interface is used to provide bundled redstone output for blocks + * @see dan200.computercraft.api.ComputerCraftAPI#registerBundledRedstoneProvider(IBundledRedstoneProvider) + */ +public interface IBundledRedstoneProvider +{ + /** + * Produce an bundled redstone output from a block location. + * @see dan200.computercraft.api.ComputerCraftAPI#registerBundledRedstoneProvider(IBundledRedstoneProvider) + * @return a number in the range 0-65535 to indicate this block is providing output, or -1 if you do not wish to handle this block + */ + public int getBundledRedstoneOutput( World world, BlockPos pos, EnumFacing side ); +} diff --git a/src/main/java/dan200/computercraft/api/redstone/package-info.java b/src/main/java/dan200/computercraft/api/redstone/package-info.java new file mode 100644 index 0000000000..292873e909 --- /dev/null +++ b/src/main/java/dan200/computercraft/api/redstone/package-info.java @@ -0,0 +1,10 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +@API( owner="ComputerCraft", provides="ComputerCraft|API|Redstone", apiVersion="${version}" ) +package dan200.computercraft.api.redstone; + +import net.minecraftforge.fml.common.API; diff --git a/src/main/java/dan200/computercraft/api/turtle/ITurtleAccess.java b/src/main/java/dan200/computercraft/api/turtle/ITurtleAccess.java new file mode 100644 index 0000000000..f30032efa0 --- /dev/null +++ b/src/main/java/dan200/computercraft/api/turtle/ITurtleAccess.java @@ -0,0 +1,169 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.turtle; + +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.peripheral.IPeripheral; +import net.minecraft.inventory.IInventory; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +/** + * The interface passed to turtle by turtles, providing methods that they can call. + * This should not be implemented by your classes. Do not interact with turtles except via this interface and ITurtleUpgrade. + */ +public interface ITurtleAccess +{ + /** + * Returns the world in which the turtle resides. + * @return the world in which the turtle resides. + */ + public World getWorld(); + + /** + * Returns a vector containing the integer co-ordinates at which the turtle resides. + * @return a vector containing the integer co-ordinates at which the turtle resides. + */ + public BlockPos getPosition(); + + /** + * TODO: Document me + */ + public boolean teleportTo( World world, BlockPos pos ); + + /** + * Returns a vector containing the floating point co-ordinates at which the turtle is rendered. + * This will shift when the turtle is moving. + * @param f The subframe fraction + * @return a vector containing the floating point co-ordinates at which the turtle resides. + */ + public Vec3 getVisualPosition( float f ); + + /** + * TODO: Document me + */ + public float getVisualYaw( float f ); + + /** + * Returns the world direction the turtle is currently facing. + * @return the world direction the turtle is currently facing. + */ + public EnumFacing getDirection(); + + /** + * TODO: Document me + */ + public void setDirection( EnumFacing dir ); + + /** + * TODO: Document me + */ + public int getSelectedSlot(); + + /** + * TODO: Document me + */ + public void setSelectedSlot( int slot ); + + /** + * Sets the colour of the turtle, as if the player had dyed it with a dye item. + * @param dyeColour 0-15 to dye the turtle one of the 16 standard minecraft colours, or -1 to remove the dye from the turtle. + */ + public void setDyeColour( int dyeColour ); + + /** + * Gets the colour the turtle has been dyed. + * @return 0-15 if the turtle has been dyed one of the 16 standard minecraft colours, -1 if the turtle is clean. + */ + public int getDyeColour(); + + /** + * TODO: Document me + */ + public IInventory getInventory(); + + /** + * TODO: Document me + */ + public boolean isFuelNeeded(); + + /** + * TODO: Document me + */ + public int getFuelLevel(); + + /** + * TODO: Document me + */ + public void setFuelLevel( int fuel ); + + /** + * TODO: Document me + */ + public int getFuelLimit(); + + /** + * Removes some fuel from the turtles fuel supply. Negative numbers can be passed in to INCREASE the fuel level of the turtle. + * @return Whether the turtle was able to consume the ammount of fuel specified. Will return false if you supply a number + * greater than the current fuel level of the turtle. + */ + public boolean consumeFuel( int fuel ); + + /** + * TODO: Document me + */ + public void addFuel( int fuel ); + + /** + * Adds a custom command to the turtles command queue. Unlike peripheral methods, these custom commands will be executed + * on the main thread, so are guaranteed to be able to access Minecraft objects safely, and will be queued up + * with the turtles standard movement and tool commands. An issued command will return an unique integer, which will + * be supplied as a parameter to a "turtle_response" event issued to the turtle after the command has completed. Look at the + * lua source code for "rom/apis/turtle" for how to build a lua wrapper around this functionality. + * @param command an object which will execute the custom command when its point in the queue is reached + * @return the objects the command returned when executed. you should probably return these to the player + * unchanged if called from a peripheral method. + * @see ITurtleCommand + */ + public Object[] executeCommand( ILuaContext context, ITurtleCommand command ) throws LuaException, InterruptedException; + + /** + * TODO: Document me + */ + public void playAnimation( TurtleAnimation animation ); + + /** + * Returns the turtle on the specified side of the turtle, if there is one. + * @return the turtle on the specified side of the turtle, if there is one. + */ + public ITurtleUpgrade getUpgrade( TurtleSide side ); + + /** + * TODO: Document me + */ + public void setUpgrade( TurtleSide side, ITurtleUpgrade upgrade ); + + /** + * Returns the peripheral created by the upgrade on the specified side of the turtle, if there is one. + * @return the peripheral created by the upgrade on the specified side of the turtle, if there is one. + */ + public IPeripheral getPeripheral( TurtleSide side ); + + /** + * TODO: Document me + */ + public NBTTagCompound getUpgradeNBTData( TurtleSide side ); + + /** + * TODO: Document me + */ + public void updateUpgradeNBTData( TurtleSide side ); +} diff --git a/src/main/java/dan200/computercraft/api/turtle/ITurtleCommand.java b/src/main/java/dan200/computercraft/api/turtle/ITurtleCommand.java new file mode 100644 index 0000000000..370f7707eb --- /dev/null +++ b/src/main/java/dan200/computercraft/api/turtle/ITurtleCommand.java @@ -0,0 +1,25 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.turtle; + +/** + * An interface for objects executing custom turtle commands, used with ITurtleAccess.issueCommand + * @see ITurtleAccess#executeCommand(dan200.computercraft.api.lua.ILuaContext,ITurtleCommand) + */ +public interface ITurtleCommand +{ + /** + * Will be called by the turtle on the main thread when it is time to execute the custom command. + * The handler should either perform the work of the command, and return success, or return + * failure with an error message to indicate the command cannot be executed at this time. + * @param turtle access to the turtle for whom the command was issued + * @return TurtleCommandResult.success() or TurtleCommandResult.failure( errorMessage ) + * @see ITurtleAccess#executeCommand(dan200.computercraft.api.lua.ILuaContext,ITurtleCommand) + * @see dan200.computercraft.api.turtle.TurtleCommandResult + */ + public TurtleCommandResult execute( ITurtleAccess turtle ); +} diff --git a/src/main/java/dan200/computercraft/api/turtle/ITurtleUpgrade.java b/src/main/java/dan200/computercraft/api/turtle/ITurtleUpgrade.java new file mode 100644 index 0000000000..5de721541e --- /dev/null +++ b/src/main/java/dan200/computercraft/api/turtle/ITurtleUpgrade.java @@ -0,0 +1,108 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.turtle; + +import dan200.computercraft.api.peripheral.IPeripheral; +import net.minecraft.client.resources.model.IBakedModel; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.apache.commons.lang3.tuple.Pair; + +import javax.vecmath.Matrix4f; + + +/** + * The primary interface for defining an update for Turtles. A turtle update + * can either be a new tool, or a new peripheral. + * @see dan200.computercraft.api.ComputerCraftAPI#registerTurtleUpgrade( dan200.computercraft.api.turtle.ITurtleUpgrade ) + */ +public interface ITurtleUpgrade +{ + /** + * Gets a unique identifier representing this type of turtle upgrade. eg: "computercraft:wireless_modem" or "my_mod:my_upgrade". + * You should use a unique resource domain to ensure this upgrade is uniquely identified. + * The turtle will fail registration if an already used ID is specified. + * @see dan200.computercraft.api.ComputerCraftAPI#registerTurtleUpgrade( dan200.computercraft.api.turtle.ITurtleUpgrade ) + */ + public ResourceLocation getUpgradeID(); + + /** + * Gets a numerical identifier representing this type of turtle upgrade, + * for backwards compatibility with pre-1.76 worlds. If your upgrade was + * not released for older ComputerCraft versions, you can return -1 here. + * The turtle will fail registration if an already used positive ID is specified. + * @see dan200.computercraft.api.ComputerCraftAPI#registerTurtleUpgrade( dan200.computercraft.api.turtle.ITurtleUpgrade ) + */ + public int getLegacyUpgradeID(); + + /** + * Return a String to describe this type of turtle in turtle item names. + * Examples of built-in adjectives are "Wireless", "Mining" and "Crafty". + */ + public String getUnlocalisedAdjective(); + + /** + * Return whether this turtle adds a tool or a peripheral to the turtle. + * @see TurtleUpgradeType for the differences between the two. + */ + public TurtleUpgradeType getType(); + + /** + * Return an item stack representing the type of item that a turtle must be crafted + * with to create a turtle which holds this upgrade. This item stack is also used + * to determine the upgrade given by turtle.equip() + */ + public ItemStack getCraftingItem(); + + /** + * Will only be called for peripheral upgrades. Creates a peripheral for a turtle + * being placed using this upgrade. The peripheral created will be stored + * for the lifetime of the upgrade, will have update() called once-per-tick, and will be + * attached, detached and have methods called in the same manner as a Computer peripheral. + * + * @param turtle Access to the turtle that the peripheral is being created for. + * @param side Which side of the turtle (left or right) that the upgrade resides on. + * @return The newly created peripheral. You may return null if this upgrade is a Tool + * and this method is not expected to be called. + */ + public IPeripheral createPeripheral( ITurtleAccess turtle, TurtleSide side ); + + /** + * Will only be called for Tool turtle. Called when turtle.dig() or turtle.attack() is called + * by the turtle, and the tool is required to do some work. + * @param turtle Access to the turtle that the tool resides on. + * @param side Which side of the turtle (left or right) the tool resides on. + * @param verb Which action (dig or attack) the turtle is being called on to perform. + * @param direction Which world direction the action should be performed in, relative to the turtles + * position. This will either be up, down, or the direction the turtle is facing, depending on + * whether dig, digUp or digDown was called. + * @return Whether the turtle was able to perform the action, and hence whether the turtle.dig() + * or turtle.attack() lua method should return true. If true is returned, the tool will perform + * a swinging animation. You may return null if this turtle is a Peripheral + * and this method is not expected to be called. + */ + public TurtleCommandResult useTool( ITurtleAccess turtle, TurtleSide side, TurtleVerb verb, EnumFacing direction ); + + /** + * Called to obtain the model to be used when rendering a turtle peripheral. + * @param turtle Access to the turtle that the upgrade resides on. This will be null when getting item models! + * @param side Which side of the turtle (left or right) the upgrade resides on. + * @return The model that you wish to be used to render your upgrade, and a transformation to apply to it. Returning a transformation of null has the same effect as the identify matrix. + */ + @SideOnly( Side.CLIENT ) + public Pair getModel( ITurtleAccess turtle, TurtleSide side ); + + /** + * Called once per tick for each turtle which has the upgrade equipped. + * @param turtle Access to the turtle that the upgrade resides on. + * @param side Which side of the turtle (left or right) the upgrade resides on. + */ + public void update( ITurtleAccess turtle, TurtleSide side ); +} diff --git a/src/main/java/dan200/computercraft/api/turtle/TurtleAnimation.java b/src/main/java/dan200/computercraft/api/turtle/TurtleAnimation.java new file mode 100644 index 0000000000..e720335a01 --- /dev/null +++ b/src/main/java/dan200/computercraft/api/turtle/TurtleAnimation.java @@ -0,0 +1,22 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.turtle; + +public enum TurtleAnimation +{ + None, + MoveForward, + MoveBack, + MoveUp, + MoveDown, + TurnLeft, + TurnRight, + SwingLeftTool, + SwingRightTool, + Wait, + ShortWait, +} diff --git a/src/main/java/dan200/computercraft/api/turtle/TurtleCommandResult.java b/src/main/java/dan200/computercraft/api/turtle/TurtleCommandResult.java new file mode 100644 index 0000000000..09c5288270 --- /dev/null +++ b/src/main/java/dan200/computercraft/api/turtle/TurtleCommandResult.java @@ -0,0 +1,73 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.turtle; + +public final class TurtleCommandResult +{ + private static final TurtleCommandResult s_success = new TurtleCommandResult( true, null, null ); + private static final TurtleCommandResult s_emptyFailure = new TurtleCommandResult( false, null, null ); + + public static TurtleCommandResult success() + { + return success( null ); + } + + public static TurtleCommandResult success( Object[] results ) + { + if( results == null || results.length == 0 ) + { + return s_success; + } + else + { + return new TurtleCommandResult( true, null, results ); + } + } + + public static TurtleCommandResult failure() + { + return failure( null ); + } + + public static TurtleCommandResult failure( String errorMessage ) + { + if( errorMessage == null ) + { + return s_emptyFailure; + } + else + { + return new TurtleCommandResult( false, errorMessage, null ); + } + } + + private final boolean m_success; + private final String m_errorMessage; + private final Object[] m_results; + + private TurtleCommandResult( boolean success, String errorMessage, Object[] results ) + { + m_success = success; + m_errorMessage = errorMessage; + m_results = results; + } + + public boolean isSuccess() + { + return m_success; + } + + public String getErrorMessage() + { + return m_errorMessage; + } + + public Object[] getResults() + { + return m_results; + } +} diff --git a/src/main/java/dan200/computercraft/api/turtle/TurtleSide.java b/src/main/java/dan200/computercraft/api/turtle/TurtleSide.java new file mode 100644 index 0000000000..410794c713 --- /dev/null +++ b/src/main/java/dan200/computercraft/api/turtle/TurtleSide.java @@ -0,0 +1,23 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.turtle; + +/** + * An enum representing the two sides of the turtle that a turtle turtle might reside. + */ +public enum TurtleSide +{ + /** + * The turtles left side (where the pickaxe usually is on a Wireless Mining Turtle) + */ + Left, + + /** + * The turtles right side (where the modem usually is on a Wireless Mining Turtle) + */ + Right, +} diff --git a/src/main/java/dan200/computercraft/api/turtle/TurtleUpgradeType.java b/src/main/java/dan200/computercraft/api/turtle/TurtleUpgradeType.java new file mode 100644 index 0000000000..b7c39d9594 --- /dev/null +++ b/src/main/java/dan200/computercraft/api/turtle/TurtleUpgradeType.java @@ -0,0 +1,27 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.turtle; + +/** + * An enum representing the two different types of turtle that an ITurtleUpgrade + * implementation can add to a turtle. + * @see ITurtleUpgrade + */ +public enum TurtleUpgradeType +{ + /** + * A tool is rendered as an item on the side of the turtle, and responds to the turtle.dig() + * and turtle.attack() methods (Such as pickaxe or sword on Mining and Melee turtles). + */ + Tool, + + /** + * A peripheral adds a special peripheral which is attached to the side of the turtle, + * and can be interacted with the peripheral API (Such as the modem on Wireless Turtles). + */ + Peripheral, +} diff --git a/src/main/java/dan200/computercraft/api/turtle/TurtleVerb.java b/src/main/java/dan200/computercraft/api/turtle/TurtleVerb.java new file mode 100644 index 0000000000..4471eff486 --- /dev/null +++ b/src/main/java/dan200/computercraft/api/turtle/TurtleVerb.java @@ -0,0 +1,26 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.turtle; + +/** + * An enum representing the two different actions that an ITurtleUpgrade of type + * Tool may be called on to perform by a turtle. + * @see ITurtleUpgrade + * @see ITurtleUpgrade#useTool + */ +public enum TurtleVerb +{ + /** + * The turtle called turtle.dig(), turtle.digUp() or turtle.digDown() + */ + Dig, + + /** + * The turtle called turtle.attack(), turtle.attackUp() or turtle.attackDown() + */ + Attack, +} diff --git a/src/main/java/dan200/computercraft/api/turtle/package-info.java b/src/main/java/dan200/computercraft/api/turtle/package-info.java new file mode 100644 index 0000000000..6953356382 --- /dev/null +++ b/src/main/java/dan200/computercraft/api/turtle/package-info.java @@ -0,0 +1,10 @@ +/** + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +@API( owner="ComputerCraft", provides="ComputerCraft|API|Turtle", apiVersion="${version}" ) +package dan200.computercraft.api.turtle; + +import net.minecraftforge.fml.common.API; diff --git a/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java b/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java new file mode 100644 index 0000000000..fb2d8b8b44 --- /dev/null +++ b/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java @@ -0,0 +1,151 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.client.gui; + +import dan200.computercraft.core.terminal.TextBuffer; +import dan200.computercraft.shared.util.Colour; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; + +public class FixedWidthFontRenderer +{ + public static ResourceLocation font = new ResourceLocation( "computercraft", "textures/gui/termFont.png" ); + public static ResourceLocation background = new ResourceLocation( "computercraft", "textures/gui/termBackground.png" ); + + public static int FONT_HEIGHT = 9; + public static int FONT_WIDTH = 6; + + private TextureManager m_textureManager; + + public FixedWidthFontRenderer( TextureManager textureManager ) + { + m_textureManager = textureManager; + } + + private void drawChar( WorldRenderer renderer, double x, double y, int index, int color ) + { + int column = index % 16; + int row = index / 16; + Colour colour = Colour.values()[ 15 - color ]; + renderer.pos( x, y + FONT_HEIGHT, 0.0 ).tex( (double) (column * FONT_WIDTH) / 256.0, (double) ((row + 1) * FONT_HEIGHT) / 256.0 ).color( colour.getR(), colour.getG(), colour.getB(), 1.0f ).endVertex(); + renderer.pos( x + FONT_WIDTH, y + FONT_HEIGHT, 0.0 ).tex( (double) ((column + 1) * FONT_WIDTH) / 256.0, (double) ((row + 1) * FONT_HEIGHT) / 256.0 ).color( colour.getR(), colour.getG(), colour.getB(), 1.0f ).endVertex(); + renderer.pos( x + FONT_WIDTH, y, 0.0 ).tex( (double) ((column + 1) * FONT_WIDTH) / 256.0, (double) (row * FONT_HEIGHT) / 256.0 ).color( colour.getR(), colour.getG(), colour.getB(), 1.0f ).endVertex(); + renderer.pos( x, y, 0.0 ).tex( (double) (column * FONT_WIDTH) / 256.0, (double) (row * FONT_HEIGHT ) / 256.0 ).color( colour.getR(), colour.getG(), colour.getB(), 1.0f ).endVertex(); + } + + private void drawQuad( WorldRenderer renderer, double x, double y, int color, double width ) + { + Colour colour = Colour.values()[ 15 - color ]; + renderer.pos( x, y + FONT_HEIGHT, 0.0 ).tex( 0.0, 1.0 ).color( colour.getR(), colour.getG(), colour.getB(), 1.0f ).endVertex(); + renderer.pos( x + width, y + FONT_HEIGHT, 0.0 ).tex( 1.0, 1.0 ).color( colour.getR(), colour.getG(), colour.getB(), 1.0f ).endVertex(); + renderer.pos( x + width, y, 0.0 ).tex( 1.0, 0.0 ).color( colour.getR(), colour.getG(), colour.getB(), 1.0f ).endVertex(); + renderer.pos( x, y, 0.0 ).tex( 0.0, 0.0 ).color( colour.getR(), colour.getG(), colour.getB(), 1.0f ).endVertex(); + } + + private boolean isGreyScale( int colour ) + { + return (colour == 0 || colour == 15 || colour == 7 || colour == 8); + } + + public void drawStringBackgroundPart( int x, int y, TextBuffer backgroundColour, double leftMarginSize, double rightMarginSize, boolean greyScale ) + { + // Draw the quads + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer renderer = tessellator.getWorldRenderer(); + renderer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR ); + if( leftMarginSize > 0.0 ) + { + int colour1 = "0123456789abcdef".indexOf( backgroundColour.charAt( 0 ) ); + if( colour1 < 0 || (greyScale && !isGreyScale(colour1)) ) + { + colour1 = 15; + } + drawQuad( renderer, x - leftMarginSize, y, colour1, leftMarginSize ); + } + if( rightMarginSize > 0.0 ) + { + int colour2 = "0123456789abcdef".indexOf( backgroundColour.charAt( backgroundColour.length() - 1 ) ); + if( colour2 < 0 || (greyScale && !isGreyScale(colour2)) ) + { + colour2 = 15; + } + drawQuad( renderer, x + backgroundColour.length() * FONT_WIDTH, y, colour2, rightMarginSize ); + } + for( int i = 0; i < backgroundColour.length(); i++ ) + { + int colour = "0123456789abcdef".indexOf( backgroundColour.charAt( i ) ); + if( colour < 0 || ( greyScale && !isGreyScale( colour ) ) ) + { + colour = 15; + } + drawQuad( renderer, x + i * FONT_WIDTH, y, colour, FONT_WIDTH ); + } + tessellator.draw(); + } + + public void drawStringTextPart( int x, int y, TextBuffer s, TextBuffer textColour, boolean greyScale ) + { + // Draw the quads + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer renderer = tessellator.getWorldRenderer(); + renderer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR ); + for( int i = 0; i < s.length(); i++ ) + { + // Switch colour + int colour = "0123456789abcdef".indexOf( textColour.charAt( i ) ); + if( colour < 0 || ( greyScale && !isGreyScale( colour ) ) ) + { + colour = 0; + } + + // Draw char + int index = (int)s.charAt( i ); + if( index < 0 || index > 255 ) + { + index = (int)'?'; + } + drawChar( renderer, x + i * FONT_WIDTH, y, index, colour ); + } + tessellator.draw(); + } + + public void drawString( TextBuffer s, int x, int y, TextBuffer textColour, TextBuffer backgroundColour, double leftMarginSize, double rightMarginSize, boolean greyScale ) + { + // Draw background + if( backgroundColour != null ) + { + // Bind the background texture + m_textureManager.bindTexture( background ); + + // Draw the quads + drawStringBackgroundPart( x, y, backgroundColour, leftMarginSize, rightMarginSize, greyScale ); + } + + // Draw text + if( s != null && textColour != null ) + { + // Bind the font texture + m_textureManager.bindTexture( font ); + + // Draw the quads + drawStringTextPart( x, y, s, textColour, greyScale ); + } + } + + public int getStringWidth(String s) + { + if(s == null) + { + return 0; + } + return s.length() * FONT_WIDTH; + } +} diff --git a/src/main/java/dan200/computercraft/client/gui/GuiComputer.java b/src/main/java/dan200/computercraft/client/gui/GuiComputer.java new file mode 100644 index 0000000000..81dcd3bcce --- /dev/null +++ b/src/main/java/dan200/computercraft/client/gui/GuiComputer.java @@ -0,0 +1,195 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.client.gui; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.client.gui.widgets.WidgetTerminal; +import dan200.computercraft.shared.computer.blocks.TileComputer; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.core.IComputer; +import dan200.computercraft.shared.computer.core.IComputerContainer; +import dan200.computercraft.shared.computer.inventory.ContainerComputer; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.inventory.Container; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; + +import java.io.IOException; + +public class GuiComputer extends GuiContainer +{ + private static final ResourceLocation background = new ResourceLocation( "computercraft", "textures/gui/corners.png" ); + private static final ResourceLocation backgroundAdvanced = new ResourceLocation( "computercraft", "textures/gui/corners2.png" ); + private static final ResourceLocation backgroundCommand = new ResourceLocation( "computercraft", "textures/gui/cornersCommand.png" ); + + private final ComputerFamily m_family; + private final IComputer m_computer; + private final int m_termWidth; + private final int m_termHeight; + private WidgetTerminal m_terminal; + + protected GuiComputer( Container container, ComputerFamily family, IComputer computer, int termWidth, int termHeight ) + { + super( container ); + m_family = family; + m_computer = computer; + m_termWidth = termWidth; + m_termHeight = termHeight; + m_terminal = null; + } + + public GuiComputer( TileComputer computer ) + { + this( + new ContainerComputer( computer ), + computer.getFamily(), + computer.createComputer(), + ComputerCraft.terminalWidth_computer, + ComputerCraft.terminalHeight_computer + ); + } + + @Override + public void initGui() + { + super.initGui(); + Keyboard.enableRepeatEvents( true ); + + m_terminal = new WidgetTerminal( 0, 0, m_termWidth, m_termHeight, new IComputerContainer() + { + @Override + public IComputer getComputer() + { + return m_computer; + } + }, 2, 2, 2, 2 ); + m_terminal.setAllowFocusLoss( false ); + xSize = m_terminal.getWidth() + 24; + ySize = m_terminal.getHeight() + 24; + } + + @Override + public void onGuiClosed() + { + super.onGuiClosed(); + Keyboard.enableRepeatEvents( false ); + } + + @Override + public boolean doesGuiPauseGame() + { + return false; + } + + @Override + public void updateScreen() + { + super.updateScreen(); + m_terminal.update(); + } + + @Override + protected void keyTyped(char c, int k) throws IOException + { + if( k == 1 ) + { + super.keyTyped( c, k ); + } + else + { + m_terminal.keyTyped( c, k ); + } + } + + @Override + protected void mouseClicked( int x, int y, int button ) + { + int startX = (width - m_terminal.getWidth()) / 2; + int startY = (height - m_terminal.getHeight()) / 2; + m_terminal.mouseClicked( x - startX, y - startY, button ); + } + + @Override + public void handleMouseInput() throws IOException + { + super.handleMouseInput(); + + int x = Mouse.getEventX() * width / mc.displayWidth; + int y = height - Mouse.getEventY() * height / mc.displayHeight - 1; + int startX = (width - m_terminal.getWidth()) / 2; + int startY = (height - m_terminal.getHeight()) / 2; + m_terminal.handleMouseInput( x - startX, y - startY ); + } + + @Override + public void handleKeyboardInput() throws IOException + { + super.handleKeyboardInput(); + m_terminal.handleKeyboardInput(); + } + + @Override + protected void drawGuiContainerForegroundLayer(int par1, int par2) + { + } + + @Override + protected void drawGuiContainerBackgroundLayer( float var1, int var2, int var3 ) + { + } + + @Override + public void drawScreen( int mouseX, int mouseY, float f ) + { + // Work out where to draw + int startX = (width - m_terminal.getWidth()) / 2; + int startY = (height - m_terminal.getHeight()) / 2; + int endX = startX + m_terminal.getWidth(); + int endY = startY + m_terminal.getHeight(); + + // Draw background + drawDefaultBackground(); + + // Draw terminal + m_terminal.draw( this.mc, startX, startY, mouseX, mouseY ); + + // Draw a border around the terminal + GlStateManager.color( 1.0f, 1.0f, 1.0f, 1.0f ); + switch( m_family ) + { + case Normal: + default: + { + this.mc.getTextureManager().bindTexture( background ); + break; + } + case Advanced: + { + this.mc.getTextureManager().bindTexture( backgroundAdvanced ); + break; + } + case Command: + { + this.mc.getTextureManager().bindTexture( backgroundCommand ); + break; + } + } + + drawTexturedModalRect(startX - 12, startY - 12, 12, 28, 12, 12); + drawTexturedModalRect(startX - 12, endY, 12, 40, 12, 16); + drawTexturedModalRect(endX, startY - 12, 24, 28, 12, 12); + drawTexturedModalRect(endX, endY, 24, 40, 12, 16); + + drawTexturedModalRect(startX, startY-12, 0, 0, endX - startX, 12); + drawTexturedModalRect(startX, endY, 0, 12, endX - startX, 16); + + drawTexturedModalRect(startX-12, startY, 0, 28, 12, endY - startY); + drawTexturedModalRect(endX, startY, 36, 28, 12, endY - startY); + } +} diff --git a/src/main/java/dan200/computercraft/client/gui/GuiDiskDrive.java b/src/main/java/dan200/computercraft/client/gui/GuiDiskDrive.java new file mode 100644 index 0000000000..51f5f554e4 --- /dev/null +++ b/src/main/java/dan200/computercraft/client/gui/GuiDiskDrive.java @@ -0,0 +1,46 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.client.gui; + +import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive; +import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.resources.I18n; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.util.ResourceLocation; + +public class GuiDiskDrive extends GuiContainer +{ + private static final ResourceLocation background = new ResourceLocation( "computercraft", "textures/gui/diskdrive.png" ); + + private TileDiskDrive m_diskDrive; + + public GuiDiskDrive( InventoryPlayer inventoryplayer, TileDiskDrive diskDrive ) + { + super( new ContainerDiskDrive(inventoryplayer, diskDrive) ); + m_diskDrive = diskDrive; + } + + @Override + protected void drawGuiContainerForegroundLayer(int par1, int par2) + { + String title = m_diskDrive.getDisplayName().getUnformattedText(); + fontRendererObj.drawString( title, (xSize - fontRendererObj.getStringWidth(title)) / 2, 6, 0x404040 ); + fontRendererObj.drawString( I18n.format("container.inventory"), 8, (ySize - 96) + 2, 0x404040 ); + } + + @Override + protected void drawGuiContainerBackgroundLayer(float f, int i, int j) + { + GlStateManager.color( 1.0F, 1.0F, 1.0F, 1.0F ); + this.mc.getTextureManager().bindTexture( background ); + int l = (width - xSize) / 2; + int i1 = (height - ySize) / 2; + drawTexturedModalRect(l, i1, 0, 0, xSize, ySize); + } +} diff --git a/src/main/java/dan200/computercraft/client/gui/GuiPocketComputer.java b/src/main/java/dan200/computercraft/client/gui/GuiPocketComputer.java new file mode 100644 index 0000000000..9e8b169d79 --- /dev/null +++ b/src/main/java/dan200/computercraft/client/gui/GuiPocketComputer.java @@ -0,0 +1,24 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.client.gui; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.media.inventory.ContainerHeldItem; + +public class GuiPocketComputer extends GuiComputer +{ + public GuiPocketComputer( ContainerHeldItem container ) + { + super( + container, + ComputerCraft.Items.pocketComputer.getFamily( container.getStack() ), + ComputerCraft.Items.pocketComputer.createClientComputer( container.getStack() ), + ComputerCraft.terminalWidth_pocketComputer, + ComputerCraft.terminalHeight_pocketComputer + ); + } +} diff --git a/src/main/java/dan200/computercraft/client/gui/GuiPrinter.java b/src/main/java/dan200/computercraft/client/gui/GuiPrinter.java new file mode 100644 index 0000000000..fa529fffd9 --- /dev/null +++ b/src/main/java/dan200/computercraft/client/gui/GuiPrinter.java @@ -0,0 +1,54 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.client.gui; + +import dan200.computercraft.shared.peripheral.printer.ContainerPrinter; +import dan200.computercraft.shared.peripheral.printer.TilePrinter; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.resources.I18n; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.util.ResourceLocation; + +public class GuiPrinter extends GuiContainer +{ + private static final ResourceLocation background = new ResourceLocation( "computercraft", "textures/gui/printer.png" ); + + private TilePrinter m_printer; + private ContainerPrinter m_container; + + public GuiPrinter(InventoryPlayer inventoryplayer, TilePrinter printer) + { + super(new ContainerPrinter(inventoryplayer, printer)); + m_printer = printer; + m_container = (ContainerPrinter)inventorySlots; + } + + @Override + protected void drawGuiContainerForegroundLayer(int par1, int par2) + { + String title = m_printer.getDisplayName().getUnformattedText(); + fontRendererObj.drawString( title, (xSize - fontRendererObj.getStringWidth(title)) / 2, 6, 0x404040 ); + fontRendererObj.drawString( I18n.format("container.inventory"), 8, (ySize - 96) + 2, 0x404040 ); + } + + @Override + protected void drawGuiContainerBackgroundLayer(float f, int i, int j) + { + GlStateManager.color( 1.0F, 1.0F, 1.0F, 1.0F ); + this.mc.getTextureManager().bindTexture( background ); + int startX = (width - xSize) / 2; + int startY = (height - ySize) / 2; + drawTexturedModalRect(startX, startY, 0, 0, xSize, ySize); + + boolean printing = m_container.isPrinting(); + if( printing ) + { + drawTexturedModalRect(startX + 34, startY + 21, 176, 0, 25, 45); + } + } +} diff --git a/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java b/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java new file mode 100644 index 0000000000..98f3cb9b11 --- /dev/null +++ b/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java @@ -0,0 +1,212 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.client.gui; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.core.terminal.TextBuffer; +import dan200.computercraft.shared.media.inventory.ContainerHeldItem; +import dan200.computercraft.shared.media.items.ItemPrintout; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; + +import java.io.IOException; + +public class GuiPrintout extends GuiContainer +{ + private static final ResourceLocation background = new ResourceLocation( "computercraft", "textures/gui/printout.png" ); + + private static final int xSize = 172; + private static final int ySize = 209; + + private final boolean m_book; + private final int m_pages; + private final TextBuffer[] m_text; + private final TextBuffer[] m_colours; + private int m_page; + + public GuiPrintout( ContainerHeldItem container ) + { + super( container ); + m_book = (ItemPrintout.getType( container.getStack() ) == ItemPrintout.Type.Book); + + String[] text = ItemPrintout.getText( container.getStack() ); + m_text = new TextBuffer[ text.length ]; + for( int i=0; i 0 ) + { + m_page = m_page - 1; + } + } + } + + @Override + public void handleMouseInput() throws IOException + { + super.handleMouseInput(); + + int mouseWheelChange = Mouse.getEventDWheel(); + if (mouseWheelChange < 0) + { + // Up + if( m_page < m_pages - 1 ) + { + m_page = m_page + 1; + } + } + else if (mouseWheelChange > 0) + { + // Down + if( m_page > 0 ) + { + m_page = m_page - 1; + } + } + } + + @Override + protected void drawGuiContainerForegroundLayer( int par1, int par2 ) + { + } + + @Override + protected void drawGuiContainerBackgroundLayer( float var1, int var2, int var3 ) + { + } + + @Override + public void drawScreen(int mouseX, int mouseY, float f) + { + // Draw background + drawDefaultBackground(); + + // Draw the printout + GlStateManager.color( 1.0f, 1.0f, 1.0f, 1.0f ); + this.mc.getTextureManager().bindTexture( background ); + + int startY = (height - ySize) / 2; + //int startX = (width - xSize) / 2 - (m_page * 8); + int startX = (width - (xSize + (m_pages - 1)*8)) / 2; + + if( m_book ) + { + // Border + drawTexturedModalRect( startX - 8, startY - 8, xSize + 48, 0, 12, ySize + 24); + drawTexturedModalRect( startX + xSize + (m_pages - 1)*8 - 4, startY - 8, xSize + 48 + 12, 0, 12, ySize + 24); + + drawTexturedModalRect( startX, startY - 8, 0, ySize, xSize, 12); + drawTexturedModalRect( startX, startY + ySize - 4, 0, ySize + 12, xSize, 12); + for( int n=1; n=m_page; --n ) + { + drawTexturedModalRect( startX + n*8 + (xSize - 12), startY, 24 + xSize, 0, 12, ySize); + } + drawTexturedModalRect( startX + m_page*8 + xSize/2, startY, 24 + xSize / 2, 0, xSize / 2, ySize); + } + + // Draw the text + FixedWidthFontRenderer fontRenderer = (FixedWidthFontRenderer)ComputerCraft.getFixedWidthFontRenderer(); + int x = startX + m_page * 8 + 13; + int y = startY + 11; + for( int line=0; line= 0 && lineIdx < m_text.length ) + { + fontRenderer.drawString( m_text[lineIdx], x, y, m_colours[lineIdx], null, 0, 0, false ); + } + y = y + FixedWidthFontRenderer.FONT_HEIGHT; + } + } +} diff --git a/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java b/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java new file mode 100644 index 0000000000..8a8e181ffe --- /dev/null +++ b/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java @@ -0,0 +1,166 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.client.gui; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.client.gui.widgets.WidgetTerminal; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.core.IComputer; +import dan200.computercraft.shared.computer.core.IComputerContainer; +import dan200.computercraft.shared.turtle.blocks.TileTurtle; +import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; + +import java.io.IOException; + +public class GuiTurtle extends GuiContainer +{ + private static final ResourceLocation background = new ResourceLocation( "computercraft", "textures/gui/turtle.png" ); + private static final ResourceLocation backgroundAdvanced = new ResourceLocation( "computercraft", "textures/gui/turtle2.png" ); + + protected World m_world; + protected ContainerTurtle m_container; + + protected final ComputerFamily m_family; + protected final ITurtleAccess m_turtle; + protected final IComputer m_computer; + protected WidgetTerminal m_terminalGui; + + public GuiTurtle( World world, InventoryPlayer inventoryplayer, TileTurtle turtle ) + { + this( world, turtle, new ContainerTurtle( inventoryplayer, turtle.getAccess() ) ); + } + + protected GuiTurtle( World world, TileTurtle turtle, ContainerTurtle container ) + { + super( container ); + + m_world = world; + m_container = container; + m_family = turtle.getFamily(); + m_turtle = turtle.getAccess(); + m_computer = turtle.createComputer(); + + xSize = 254; + ySize = 217; + } + + @Override + public void initGui() + { + super.initGui(); + Keyboard.enableRepeatEvents(true); + m_terminalGui = new WidgetTerminal( + ( width - xSize ) / 2 + 8, + ( height - ySize ) / 2 + 8, + ComputerCraft.terminalWidth_turtle, + ComputerCraft.terminalHeight_turtle, + new IComputerContainer() + { + @Override + public IComputer getComputer() + { + return m_computer; + } + }, + 2, 2, 2, 2 + ); + m_terminalGui.setAllowFocusLoss( false ); + } + + @Override + public void onGuiClosed() + { + super.onGuiClosed(); + Keyboard.enableRepeatEvents(false); + } + + @Override + public void updateScreen() + { + super.updateScreen(); + m_terminalGui.update(); + } + + @Override + protected void keyTyped(char c, int k) throws IOException + { + if( k == 1 ) + { + super.keyTyped( c, k ); + } + else + { + m_terminalGui.keyTyped( c, k ); + } + } + + @Override + protected void mouseClicked(int x, int y, int button) throws IOException + { + super.mouseClicked( x, y, button ); + m_terminalGui.mouseClicked( x, y, button ); + } + + @Override + public void handleMouseInput() throws IOException + { + super.handleMouseInput(); + int x = Mouse.getEventX() * this.width / mc.displayWidth; + int y = this.height - Mouse.getEventY() * this.height / mc.displayHeight - 1; + m_terminalGui.handleMouseInput( x, y ); + } + + @Override + public void handleKeyboardInput() throws IOException + { + super.handleKeyboardInput(); + m_terminalGui.handleKeyboardInput(); + } + + protected void drawSelectionSlot( boolean advanced ) + { + int x = (width - xSize) / 2; + int y = (height - ySize) / 2; + + // Draw selection slot + int slot = m_container.getSelectedSlot(); + if( slot >= 0 ) + { + GlStateManager.color( 1.0F, 1.0F, 1.0F, 1.0F ); + int slotX = (slot%4); + int slotY = (slot/4); + this.mc.getTextureManager().bindTexture( advanced ? backgroundAdvanced : background ); + drawTexturedModalRect(x + m_container.m_turtleInvStartX - 2 + slotX * 18, y + m_container.m_playerInvStartY - 2 + slotY * 18, 0, 217, 24, 24); + } + } + + @Override + protected void drawGuiContainerBackgroundLayer( float f, int mouseX, int mouseY ) + { + // Draw term + boolean advanced = (m_family == ComputerFamily.Advanced); + m_terminalGui.draw( Minecraft.getMinecraft(), 0, 0, mouseX, mouseY ); + + // Draw border/inventory + GlStateManager.color( 1.0F, 1.0F, 1.0F, 1.0F ); + this.mc.getTextureManager().bindTexture( advanced ? backgroundAdvanced : background ); + int x = (width - xSize) / 2; + int y = (height - ySize) / 2; + drawTexturedModalRect(x, y, 0, 0, xSize, ySize); + + drawSelectionSlot( advanced ); + } +} diff --git a/src/main/java/dan200/computercraft/client/gui/widgets/MousePos.java b/src/main/java/dan200/computercraft/client/gui/widgets/MousePos.java new file mode 100644 index 0000000000..c3c944f240 --- /dev/null +++ b/src/main/java/dan200/computercraft/client/gui/widgets/MousePos.java @@ -0,0 +1,19 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.client.gui.widgets; + +public class MousePos +{ + public int x; + public int y; + + public MousePos( int x, int y ) + { + this.x = x; + this.y = y; + } +} diff --git a/src/main/java/dan200/computercraft/client/gui/widgets/Widget.java b/src/main/java/dan200/computercraft/client/gui/widgets/Widget.java new file mode 100644 index 0000000000..efdb9ab704 --- /dev/null +++ b/src/main/java/dan200/computercraft/client/gui/widgets/Widget.java @@ -0,0 +1,386 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.client.gui.widgets; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.entity.RenderItem; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; + +public abstract class Widget extends Gui +{ + private WidgetContainer m_parent; + private boolean m_visible; + private int m_xPosition; + private int m_yPosition; + private int m_width; + private int m_height; + + protected Widget( int x, int y, int width, int height ) + { + m_parent = null; + m_visible = true; + m_xPosition = x; + m_yPosition = y; + m_width = width; + m_height = height; + } + + public WidgetContainer getRoot() + { + if( m_parent != null ) + { + return m_parent.getRoot(); + } + else if( this instanceof WidgetContainer ) + { + return (WidgetContainer)this; + } + return null; + } + + public WidgetContainer getParent() + { + return m_parent; + } + + public void setParent( WidgetContainer parent ) + { + m_parent = parent; + } + + public boolean isObscured() + { + if( m_parent != null ) + { + Widget parentModalWidget = m_parent.getModalWidget(); + if( parentModalWidget == null ) + { + return m_parent.isObscured(); + } + else + { + return (parentModalWidget != this); + } + } + return false; + } + + public boolean isVisible() + { + return m_visible && (m_parent == null || m_parent.isVisible()); + } + + public void setVisible( boolean visible ) + { + m_visible = visible; + } + + public int getXPosition() + { + return m_xPosition; + } + + public int getYPosition() + { + return m_yPosition; + } + + public int getAbsoluteXPosition() + { + return m_xPosition + (m_parent != null ? m_parent.getAbsoluteXPosition() : 0); + } + + public int getAbsoluteYPosition() + { + return m_yPosition + (m_parent != null ? m_parent.getAbsoluteYPosition() : 0); + } + + public int getWidth() + { + return m_width; + } + + public int getHeight() + { + return m_height; + } + + public void setPosition( int x, int y ) + { + m_xPosition = x; + m_yPosition = y; + } + + public void resize( int width, int height ) + { + m_width = width; + m_height = height; + } + + public void update() + { + } + + public void draw( Minecraft mc, int xOrigin, int yOrigin, int mouseX, int mouseY ) + { + } + + public void drawForeground( Minecraft mc, int xOrigin, int yOrigin, int mouseX, int mouseY ) + { + } + + public void modifyMousePosition( MousePos pos ) + { + } + + public void handleMouseInput( int mouseX, int mouseY ) + { + } + + public void handleKeyboardInput() + { + } + + public void mouseClicked( int mouseX, int mouseY, int mouseButton ) + { + } + + public void keyTyped( char c, int k ) + { + } + + public boolean suppressItemTooltips( Minecraft mc, int xOrigin, int yOrigin, int mouseX, int mouseY ) + { + return false; + } + + public boolean suppressKeyPress( char c, int k ) + { + return false; + } + + protected void drawFullImage( int x, int y, int w, int h ) + { + Tessellator tessellator = Tessellator.getInstance(); + tessellator.getWorldRenderer().begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX ); + tessellator.getWorldRenderer().pos( (double) ( x + 0 ), (double) ( y + h ), (double) this.zLevel ).tex( 0.0, 1.0 ).endVertex(); + tessellator.getWorldRenderer().pos( (double) ( x + w ), (double) ( y + h ), (double) this.zLevel ).tex( 1.0, 1.0 ).endVertex(); + tessellator.getWorldRenderer().pos( (double) ( x + w ), (double) ( y + 0 ), (double) this.zLevel ).tex( 1.0, 0.0 ).endVertex(); + tessellator.getWorldRenderer().pos( (double) ( x + 0 ), (double) ( y + 0 ), (double) this.zLevel ).tex( 0.0, 0.0 ).endVertex(); + tessellator.draw(); + } + + protected void drawT3( int x, int y, int w, int h, int u, int v, int uw, int vh ) + { + int partW = uw / 3; + + // Draw first bit + super.drawTexturedModalRect( x, y, u, v, partW, vh ); + + // Draw middle bits + int middleBits = Math.max( (w - 2 * partW) / partW, 0 ); + for( int j=0; j mc.currentScreen.width ) + { + startX -= width + 24; + if( startX < 24 ) + { + startX = 24; + } + } + + float oldZLevel = this.zLevel; + try + { + this.zLevel = 300.0F; + + int height = 10 * lines.length - 2; + int j1 = -267386864; + this.drawGradientRect( startX - 3, startY - 4, startX + width + 3, startY - 3, j1, j1 ); + this.drawGradientRect( startX - 3, startY + height + 3, startX + width + 3, startY + height + 4, j1, j1 ); + this.drawGradientRect( startX - 3, startY - 3, startX + width + 3, startY + height + 3, j1, j1 ); + this.drawGradientRect( startX - 4, startY - 3, startX - 3, startY + height + 3, j1, j1 ); + + this.drawGradientRect( startX + width + 3, startY - 3, startX + width + 4, startY + height + 3, j1, j1 ); + int k1 = 1347420415; + int l1 = ( k1 & 16711422 ) >> 1 | k1 & -16777216; + this.drawGradientRect( startX - 3, startY - 3 + 1, startX - 3 + 1, startY + height + 3 - 1, k1, l1 ); + this.drawGradientRect( startX + width + 2, startY - 3 + 1, startX + width + 3, startY + height + 3 - 1, k1, l1 ); + this.drawGradientRect( startX - 3, startY - 3, startX + width + 3, startY - 3 + 1, k1, k1 ); + this.drawGradientRect( startX - 3, startY + height + 2, startX + width + 3, startY + height + 3, l1, l1 ); + + GlStateManager.disableDepth(); + try + { + for( int i = 0; i < lines.length; ++i ) + { + String line = lines[ i ]; + fontRenderer.drawStringWithShadow( line, startX, startY + i * 10, 0xffffffff ); + } + } + finally + { + GlStateManager.color( 1.0f, 1.0f, 1.0f, 1.0f ); + GlStateManager.enableDepth(); + } + } + finally + { + this.zLevel = oldZLevel; + } + } + + protected void drawItemStack( int x, int y, ItemStack stack ) + { + if( stack != null ) + { + GlStateManager.color( 1.0f, 1.0f, 1.0f, 1.0f ); + GlStateManager.enableLighting(); + GlStateManager.enableRescaleNormal(); + RenderHelper.enableGUIStandardItemLighting(); + OpenGlHelper.setLightmapTextureCoords( OpenGlHelper.lightmapTexUnit, 240.0f, 240.0f ); + try + { + Minecraft mc = Minecraft.getMinecraft(); + RenderItem renderItem = mc.getRenderItem(); + if( renderItem != null ) + { + renderItem.renderItemAndEffectIntoGUI( stack, x, y ); + renderItem.renderItemOverlayIntoGUI( mc.fontRendererObj, stack, x, y, null ); + } + } + finally + { + RenderHelper.disableStandardItemLighting(); + GlStateManager.disableRescaleNormal(); + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc( GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA ); + GlStateManager.color( 1.0f, 1.0f, 1.0f, 1.0f ); + } + } + } + + protected void drawString( String s, int x, int y, int color ) + { + Minecraft mc = Minecraft.getMinecraft(); + try + { + mc.fontRendererObj.drawString( s, x, y, color ); + } + finally + { + GlStateManager.color( 1.0f, 1.0f, 1.0f, 1.0f ); + } + } + + protected int getStringWidth( String s ) + { + Minecraft mc = Minecraft.getMinecraft(); + return mc.fontRendererObj.getStringWidth( s ); + } + + protected void playClickSound() + { + Minecraft mc = Minecraft.getMinecraft(); + mc.getSoundHandler().playSound( PositionedSoundRecord.create( new ResourceLocation( "gui.button.press" ), 1.0F ) ); + } +} diff --git a/src/main/java/dan200/computercraft/client/gui/widgets/WidgetContainer.java b/src/main/java/dan200/computercraft/client/gui/widgets/WidgetContainer.java new file mode 100644 index 0000000000..17526c8835 --- /dev/null +++ b/src/main/java/dan200/computercraft/client/gui/widgets/WidgetContainer.java @@ -0,0 +1,344 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + + +package dan200.computercraft.client.gui.widgets; + +import dan200.computercraft.client.gui.widgets.Widget; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; + +import java.util.ArrayList; + +public class WidgetContainer extends Widget +{ + private ArrayList m_widgets; + private Widget m_modalWidget; + + public WidgetContainer( int x, int y, int w, int h ) + { + super( x, y, w, h ); + m_widgets = new ArrayList(); + m_modalWidget = null; + } + + public void addWidget( Widget widget ) + { + m_widgets.add( widget ); + widget.setParent( this ); + } + + public void setModalWidget( Widget widget ) + { + m_modalWidget = widget; + if( widget != null ) + { + widget.setParent( this ); + } + } + + public Widget getModalWidget() + { + return m_modalWidget; + } + + @Override + public void update() + { + for( int i=0; i m_keysDown; + + public WidgetTerminal( int x, int y, int termWidth, int termHeight, IComputerContainer computer, int leftMargin, int rightMargin, int topMargin, int bottomMargin ) + { + super( + x, y, + leftMargin + rightMargin + termWidth * FixedWidthFontRenderer.FONT_WIDTH, + topMargin + bottomMargin + termHeight * FixedWidthFontRenderer.FONT_HEIGHT + ); + + m_computer = computer; + m_terminateTimer = 0.0f; + m_rebootTimer = 0.0f; + m_shutdownTimer = 0.0f; + + m_lastClickButton = -1; + m_lastClickX = -1; + m_lastClickY = -1; + + m_focus = false; + m_allowFocusLoss = true; + m_locked = false; + + m_leftMargin = leftMargin; + m_rightMargin = rightMargin; + m_topMargin = topMargin; + m_bottomMargin = bottomMargin; + + m_keysDown = new ArrayList(); + } + + public void setAllowFocusLoss( boolean allowFocusLoss ) + { + m_allowFocusLoss = allowFocusLoss; + m_focus = m_focus || !allowFocusLoss; + } + + public void setLocked( boolean locked ) + { + m_locked = locked; + } + + @Override + public void keyTyped( char ch, int key ) + { + if( m_focus && !m_locked ) + { + // Ctrl+V for paste + if( ch == 22 ) + { + String clipboard = GuiScreen.getClipboardString(); + if( clipboard != null ) + { + // Clip to the first occurance of \r or \n + int newLineIndex1 = clipboard.indexOf( "\r" ); + int newLineIndex2 = clipboard.indexOf( "\n" ); + if( newLineIndex1 >= 0 && newLineIndex2 >= 0 ) + { + clipboard = clipboard.substring( 0, Math.min( newLineIndex1, newLineIndex2 ) ); + } + else if( newLineIndex1 >= 0 ) + { + clipboard = clipboard.substring( 0, newLineIndex1 ); + } + else if( newLineIndex2 >= 0 ) + { + clipboard = clipboard.substring( 0, newLineIndex2 ); + } + + // Filter the string + clipboard = ChatAllowedCharacters.filterAllowedCharacters( clipboard ); + + if( !clipboard.isEmpty() ) + { + // Clip to 512 characters + if( clipboard.length() > 512 ) + { + clipboard = clipboard.substring( 0, 512 ); + } + + // Queue the "paste" event + queueEvent( "paste", new Object[]{ + clipboard + } ); + } + } + return; + } + + // Regular keys normally + if( m_terminateTimer <= 0.0f && m_rebootTimer <= 0.0f && m_shutdownTimer <= 0.0f ) + { + boolean repeat = Keyboard.isRepeatEvent(); + if( key > 0 ) + { + if( !repeat ) + { + m_keysDown.add( key ); + } + + // Queue the "key" event + queueEvent( "key", new Object[]{ + key, repeat + } ); + } + + if( (ch >= 32 && ch <= 126) || (ch >= 160 && ch <= 255) ) // printable chars in byte range + { + // Queue the "char" event + queueEvent( "char", new Object[]{ + Character.toString( ch ) + } ); + } + } + } + } + + @Override + public void mouseClicked( int mouseX, int mouseY, int button ) + { + if( mouseX >= getXPosition() && mouseX < getXPosition() + getWidth() && + mouseY >= getYPosition() && mouseY < getYPosition() + getHeight() ) + { + if( !m_focus && button == 0) + { + m_focus = true; + } + + if( m_focus ) + { + IComputer computer = m_computer.getComputer(); + if( !m_locked && computer != null && computer.isColour() && button >= 0 && button <= 2 ) + { + Terminal term = computer.getTerminal(); + if( term != null ) + { + int charX = ( mouseX - ( getXPosition() + m_leftMargin ) ) / FixedWidthFontRenderer.FONT_WIDTH; + int charY = ( mouseY - ( getYPosition() + m_topMargin ) ) / FixedWidthFontRenderer.FONT_HEIGHT; + charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 ); + charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 ); + + computer.queueEvent( "mouse_click", new Object[]{ + button + 1, charX + 1, charY + 1 + } ); + + m_lastClickButton = button; + m_lastClickX = charX; + m_lastClickY = charY; + } + } + } + } + else + { + if( m_focus && button == 0 && m_allowFocusLoss ) + { + m_focus = false; + } + } + } + + @Override + public void handleKeyboardInput() + { + for( int i=m_keysDown.size()-1; i>=0; --i ) + { + int key = m_keysDown.get( i ); + if( !Keyboard.isKeyDown( key ) ) + { + m_keysDown.remove( i ); + if( m_focus && !m_locked ) + { + // Queue the "key_up" event + queueEvent( "key_up", new Object[]{ + key + } ); + } + } + } + } + + @Override + public void handleMouseInput( int mouseX, int mouseY ) + { + IComputer computer = m_computer.getComputer(); + if( mouseX >= getXPosition() && mouseX < getXPosition() + getWidth() && + mouseY >= getYPosition() && mouseY < getYPosition() + getHeight() && + computer != null && computer.isColour() ) + { + Terminal term = computer.getTerminal(); + if( term != null ) + { + int charX = ( mouseX - (getXPosition() + m_leftMargin)) / FixedWidthFontRenderer.FONT_WIDTH; + int charY = ( mouseY - (getYPosition() + m_topMargin)) / FixedWidthFontRenderer.FONT_HEIGHT; + charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 ); + charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 ); + + if( m_lastClickButton >= 0 && !Mouse.isButtonDown( m_lastClickButton ) ) + { + if( m_focus && !m_locked ) + { + computer.queueEvent( "mouse_up", new Object[]{ + m_lastClickButton + 1, charX + 1, charY + 1 + } ); + } + m_lastClickButton = -1; + } + + int wheelChange = Mouse.getEventDWheel(); + if( wheelChange == 0 && m_lastClickButton == -1 ) + { + return; + } + + if( m_focus && !m_locked ) + { + if( wheelChange < 0 ) + { + computer.queueEvent( "mouse_scroll", new Object[]{ + 1, charX + 1, charY + 1 + } ); + } + else if( wheelChange > 0 ) + { + computer.queueEvent( "mouse_scroll", new Object[]{ + -1, charX + 1, charY + 1 + } ); + } + + if( m_lastClickButton >= 0 && ( charX != m_lastClickX || charY != m_lastClickY ) ) + { + computer.queueEvent( "mouse_drag", new Object[]{ + m_lastClickButton + 1, charX + 1, charY + 1 + } ); + m_lastClickX = charX; + m_lastClickY = charY; + } + } + } + } + } + + @Override + public void update() + { + // Handle special keys + if( m_focus && !m_locked && (Keyboard.isKeyDown( 29 ) || Keyboard.isKeyDown( 157 )) ) + { + // Ctrl+T for terminate + if( Keyboard.isKeyDown( 20 ) ) + { + if( m_terminateTimer < TERMINATE_TIME ) + { + m_terminateTimer = m_terminateTimer + 0.05f; + if( m_terminateTimer >= TERMINATE_TIME ) + { + queueEvent( "terminate" ); + } + } + } + else + { + m_terminateTimer = 0.0f; + } + + // Ctrl+R for reboot + if( Keyboard.isKeyDown(19) ) + { + if( m_rebootTimer < TERMINATE_TIME ) + { + m_rebootTimer = m_rebootTimer + 0.05f; + if( m_rebootTimer >= TERMINATE_TIME ) + { + IComputer computer = m_computer.getComputer(); + if( computer != null ) + { + computer.reboot(); + } + } + } + } + else + { + m_rebootTimer = 0.0f; + } + + // Ctrl+S for shutdown + if( Keyboard.isKeyDown(31) ) + { + if( m_shutdownTimer < TERMINATE_TIME ) + { + m_shutdownTimer = m_shutdownTimer + 0.05f; + if( m_shutdownTimer >= TERMINATE_TIME ) + { + IComputer computer = m_computer.getComputer(); + if( computer != null ) + { + computer.shutdown(); + } + } + } + } + else + { + m_shutdownTimer = 0.0f; + } + } + else + { + m_terminateTimer = 0.0f; + m_rebootTimer = 0.0f; + m_shutdownTimer = 0.0f; + } + } + + @Override + public void draw( Minecraft mc, int xOrigin, int yOrigin, int mouseX, int mouseY ) + { + int startX = xOrigin + getXPosition(); + int startY = yOrigin + getYPosition(); + + // Draw the screen contents + IComputer computer = m_computer.getComputer(); + Terminal terminal = (computer != null) ? computer.getTerminal() : null; + if( terminal != null ) + { + // Draw the terminal + boolean greyscale = !computer.isColour(); + synchronized( terminal ) + { + // Get the data from the terminal first + // Unfortunately we have to keep the lock for the whole of drawing, so the text doesn't change under us. + FixedWidthFontRenderer fontRenderer = (FixedWidthFontRenderer)ComputerCraft.getFixedWidthFontRenderer(); + boolean tblink = m_focus && terminal.getCursorBlink() && ComputerCraft.getGlobalCursorBlink(); + int tw = terminal.getWidth(); + int th = terminal.getHeight(); + int tx = terminal.getCursorX(); + int ty = terminal.getCursorY(); + + int x = startX + m_leftMargin; + int y = startY + m_topMargin; + + // Draw margins + TextBuffer emptyLine = new TextBuffer( ' ', tw ); + if( m_topMargin > 0 ) + { + fontRenderer.drawString( emptyLine, x, startY, terminal.getTextColourLine( 0 ), terminal.getBackgroundColourLine( 0 ), m_leftMargin, m_rightMargin, greyscale ); + } + if( m_bottomMargin > 0 ) + { + fontRenderer.drawString( emptyLine, x, startY + 2 * m_bottomMargin + ( th - 1 ) * FixedWidthFontRenderer.FONT_HEIGHT, terminal.getTextColourLine( th - 1 ), terminal.getBackgroundColourLine( th - 1 ), m_leftMargin, m_rightMargin, greyscale ); + } + + // Draw lines + for( int line=0; line= 0 && tx < tw ) + { + TextBuffer cursor = new TextBuffer( '_', 1 ); + TextBuffer cursorColour = new TextBuffer( "0123456789abcdef".charAt( terminal.getTextColour() ), 1 ); + fontRenderer.drawString( + cursor, + x + FixedWidthFontRenderer.FONT_WIDTH * tx, + y, + cursorColour, null, + 0, 0, + greyscale + ); + } + } + y = y + FixedWidthFontRenderer.FONT_HEIGHT; + } + } + } + else + { + // Draw a black background + mc.getTextureManager().bindTexture( background ); + Colour black = Colour.Black; + GlStateManager.color( black.getR(), black.getG(), black.getB(), 1.0f ); + try + { + drawTexturedModalRect( startX, startY, 0, 0, getWidth(), getHeight() ); + } + finally + { + GlStateManager.color( 1.0f, 1.0f, 1.0f, 1.0f ); + } + } + } + + @Override + public boolean suppressKeyPress( char c, int k ) + { + if( m_focus ) + { + return k != 1; // escape + } + else + { + return false; + } + } + + private void queueEvent( String event ) + { + IComputer computer = m_computer.getComputer(); + if( computer != null ) + { + computer.queueEvent( event ); + } + } + + private void queueEvent( String event, Object[] args ) + { + IComputer computer = m_computer.getComputer(); + if( computer != null ) + { + computer.queueEvent( event, args ); + } + } +} diff --git a/src/main/java/dan200/computercraft/client/proxy/CCTurtleProxyClient.java b/src/main/java/dan200/computercraft/client/proxy/CCTurtleProxyClient.java new file mode 100644 index 0000000000..bddcdb3787 --- /dev/null +++ b/src/main/java/dan200/computercraft/client/proxy/CCTurtleProxyClient.java @@ -0,0 +1,190 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.client.proxy; + +import com.google.common.base.Function; +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.client.render.TileEntityTurtleRenderer; +import dan200.computercraft.client.render.TurtleSmartItemModel; +import dan200.computercraft.shared.proxy.CCTurtleProxyCommon; +import dan200.computercraft.shared.turtle.blocks.TileTurtle; +import dan200.computercraft.shared.turtle.core.TurtleBrain; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.ItemMeshDefinition; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.client.resources.SimpleReloadableResourceManager; +import net.minecraft.client.resources.model.IBakedModel; +import net.minecraft.client.resources.model.ModelBakery; +import net.minecraft.client.resources.model.ModelResourceLocation; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.event.ModelBakeEvent; +import net.minecraftforge.client.event.TextureStitchEvent; +import net.minecraftforge.client.model.IModel; +import net.minecraftforge.client.model.ISmartItemModel; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.client.registry.ClientRegistry; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.io.IOException; + +public class CCTurtleProxyClient extends CCTurtleProxyCommon +{ + public CCTurtleProxyClient() + { + } + + // IComputerCraftProxy implementation + + @Override + public void init() + { + super.init(); + + // Register item models + ItemMeshDefinition turtleMeshDefinition = new ItemMeshDefinition() + { + private ModelResourceLocation turtle_dynamic = new ModelResourceLocation( "computercraft:turtle_dynamic", "inventory" ); + + @Override + public ModelResourceLocation getModelLocation( ItemStack stack ) + { + return turtle_dynamic; + } + }; + String[] turtleModelNames = new String[] { + "turtle_dynamic", + "CC-Turtle", "CC-TurtleAdvanced", + "turtle_black", "turtle_red", "turtle_green", "turtle_brown", + "turtle_blue", "turtle_purple", "turtle_cyan", "turtle_lightGrey", + "turtle_grey", "turtle_pink", "turtle_lime", "turtle_yellow", + "turtle_lightBlue", "turtle_magenta", "turtle_orange", "turtle_white", + "turtle_elf_overlay" + }; + registerItemModel( ComputerCraft.Blocks.turtle, turtleMeshDefinition, turtleModelNames ); + registerItemModel( ComputerCraft.Blocks.turtleExpanded, turtleMeshDefinition, turtleModelNames ); + registerItemModel( ComputerCraft.Blocks.turtleAdvanced, turtleMeshDefinition, turtleModelNames ); + + // Setup renderers + ClientRegistry.bindTileEntitySpecialRenderer( TileTurtle.class, new TileEntityTurtleRenderer() ); + + // Setup client forge handlers + registerForgeHandlers(); + } + + private void registerItemModel( Block block, ItemMeshDefinition definition, String[] names ) + { + registerItemModel( Item.getItemFromBlock( block ), definition, names ); + } + + private void registerItemModel( Item item, ItemMeshDefinition definition, String[] names ) + { + for( int i=0; i() + { + @Override + public TextureAtlasSprite apply( ResourceLocation location ) + { + return Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite( location.toString() ); + } + } + ); + event.modelRegistry.putObject( + new ModelResourceLocation( "computercraft:" + name, "inventory" ), + bakedModel + ); + } + catch( IOException e ) + { + System.out.println( "Could not load model: name" ); + e.printStackTrace(); + } + } + + private void loadSmartModel( ModelBakeEvent event, String name, ISmartItemModel smartModel ) + { + event.modelRegistry.putObject( + new ModelResourceLocation( "computercraft:" + name, "inventory" ), + smartModel + ); + } + } +} diff --git a/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java b/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java new file mode 100644 index 0000000000..7c2c2aad8b --- /dev/null +++ b/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java @@ -0,0 +1,492 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.client.proxy; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.client.gui.*; +import dan200.computercraft.client.render.TileEntityMonitorRenderer; +import dan200.computercraft.shared.computer.blocks.TileComputer; +import dan200.computercraft.shared.computer.core.ClientComputer; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.items.ItemComputer; +import dan200.computercraft.shared.media.inventory.ContainerHeldItem; +import dan200.computercraft.shared.media.items.ItemPrintout; +import dan200.computercraft.shared.network.ComputerCraftPacket; +import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive; +import dan200.computercraft.shared.peripheral.monitor.TileMonitor; +import dan200.computercraft.shared.peripheral.printer.TilePrinter; +import dan200.computercraft.shared.pocket.items.ItemPocketComputer; +import dan200.computercraft.shared.proxy.ComputerCraftProxyCommon; +import dan200.computercraft.shared.turtle.blocks.TileTurtle; +import dan200.computercraft.shared.turtle.entity.TurtleVisionCamera; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.ItemMeshDefinition; +import net.minecraft.client.resources.model.ModelBakery; +import net.minecraft.client.resources.model.ModelResourceLocation; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.BlockPos; +import net.minecraft.util.IThreadListener; +import net.minecraft.world.World; +import net.minecraftforge.client.event.RenderGameOverlayEvent; +import net.minecraftforge.client.event.RenderHandEvent; +import net.minecraftforge.client.event.RenderPlayerEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.client.FMLClientHandler; +import net.minecraftforge.fml.client.registry.ClientRegistry; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import org.lwjgl.opengl.GL11; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +public class ComputerCraftProxyClient extends ComputerCraftProxyCommon +{ + private long m_tick; + private long m_renderFrame; + private FixedWidthFontRenderer m_fixedWidthFontRenderer; + + public ComputerCraftProxyClient() + { + } + + // IComputerCraftProxy implementation + + @Override + public void init() + { + super.init(); + m_tick = 0; + m_renderFrame = 0; + + // Load textures + Minecraft mc = Minecraft.getMinecraft(); + m_fixedWidthFontRenderer = new FixedWidthFontRenderer( mc.getTextureManager() ); + + // Register item models + registerItemModel( ComputerCraft.Blocks.computer, new ItemMeshDefinition() + { + private ModelResourceLocation computer = new ModelResourceLocation( "computercraft:CC-Computer", "inventory" ); + private ModelResourceLocation advanced_computer = new ModelResourceLocation( "computercraft:advanced_computer", "inventory" ); + + @Override + public ModelResourceLocation getModelLocation( ItemStack stack ) + { + ItemComputer itemComputer = (ItemComputer) stack.getItem(); + ComputerFamily family = itemComputer.getFamily( stack.getItemDamage() ); + return ( family == ComputerFamily.Advanced ) ? advanced_computer : computer; + } + }, new String[]{ "CC-Computer", "advanced_computer" } ); + registerItemModel( ComputerCraft.Blocks.peripheral, 0, "CC-Peripheral" ); + registerItemModel( ComputerCraft.Blocks.peripheral, 1, "wireless_modem" ); + registerItemModel( ComputerCraft.Blocks.peripheral, 2, "monitor" ); + registerItemModel( ComputerCraft.Blocks.peripheral, 3, "printer" ); + registerItemModel( ComputerCraft.Blocks.peripheral, 4, "advanced_monitor" ); + registerItemModel( ComputerCraft.Blocks.cable, 0, "CC-Cable" ); + registerItemModel( ComputerCraft.Blocks.cable, 1, "wired_modem" ); + registerItemModel( ComputerCraft.Blocks.commandComputer, "command_computer" ); + registerItemModel( ComputerCraft.Blocks.advancedModem, "advanced_modem" ); + + registerItemModel( ComputerCraft.Items.disk, "disk" ); + registerItemModel( ComputerCraft.Items.diskExpanded, "diskExpanded" ); + registerItemModel( ComputerCraft.Items.treasureDisk, "treasureDisk" ); + registerItemModel( ComputerCraft.Items.printout, 0, "printout" ); + registerItemModel( ComputerCraft.Items.printout, 1, "pages" ); + registerItemModel( ComputerCraft.Items.printout, 2, "book" ); + registerItemModel( ComputerCraft.Items.pocketComputer, new ItemMeshDefinition() + { + private ModelResourceLocation pocket_computer_off = new ModelResourceLocation( "computercraft:pocketComputer", "inventory" ); + private ModelResourceLocation pocket_computer_on = new ModelResourceLocation( "computercraft:pocket_computer_on", "inventory" ); + private ModelResourceLocation pocket_computer_blinking = new ModelResourceLocation( "computercraft:pocket_computer_blinking", "inventory" ); + private ModelResourceLocation pocket_computer_on_modem_on = new ModelResourceLocation( "computercraft:pocket_computer_on_modem_on", "inventory" ); + private ModelResourceLocation pocket_computer_blinking_modem_on = new ModelResourceLocation( "computercraft:pocket_computer_blinking_modem_on", "inventory" ); + private ModelResourceLocation advanced_pocket_computer_off = new ModelResourceLocation( "computercraft:advanced_pocket_computer_off", "inventory" ); + private ModelResourceLocation advanced_pocket_computer_on = new ModelResourceLocation( "computercraft:advanced_pocket_computer_on", "inventory" ); + private ModelResourceLocation advanced_pocket_computer_blinking = new ModelResourceLocation( "computercraft:advanced_pocket_computer_blinking", "inventory" ); + private ModelResourceLocation advanced_pocket_computer_on_modem_on = new ModelResourceLocation( "computercraft:advanced_pocket_computer_on_modem_on", "inventory" ); + private ModelResourceLocation advanced_pocket_computer_blinking_modem_on = new ModelResourceLocation( "computercraft:advanced_pocket_computer_blinking_modem_on", "inventory" ); + + @Override + public ModelResourceLocation getModelLocation( ItemStack stack ) + { + ItemPocketComputer itemPocketComputer = (ItemPocketComputer)stack.getItem(); + boolean modemOn = itemPocketComputer.getModemState( stack ); + switch( itemPocketComputer.getFamily( stack ) ) + { + case Advanced: + { + switch( itemPocketComputer.getState( stack ) ) + { + case Off: + default: + { + return advanced_pocket_computer_off; + } + case On: + { + return modemOn ? advanced_pocket_computer_on_modem_on : advanced_pocket_computer_on; + } + case Blinking: + { + return modemOn ? advanced_pocket_computer_blinking_modem_on : advanced_pocket_computer_blinking; + } + } + } + case Normal: + default: + { + switch( itemPocketComputer.getState( stack ) ) + { + case Off: + default: + { + return pocket_computer_off; + } + case On: + { + return modemOn ? pocket_computer_on_modem_on : pocket_computer_on; + } + case Blinking: + { + return modemOn ? pocket_computer_blinking_modem_on : pocket_computer_blinking; + } + } + } + } + } + }, new String[] { + "pocketComputer", "pocket_computer_on", "pocket_computer_blinking", "pocket_computer_on_modem_on", "pocket_computer_blinking_modem_on", + "advanced_pocket_computer_off", "advanced_pocket_computer_on", "advanced_pocket_computer_blinking", "advanced_pocket_computer_on_modem_on", "advanced_pocket_computer_blinking_modem_on", + } ); + + // Setup renderers + ClientRegistry.bindTileEntitySpecialRenderer( TileMonitor.class, new TileEntityMonitorRenderer() ); + + // Setup client forge handlers + registerForgeHandlers(); + } + + private void registerItemModel( Block block, int damage, String name ) + { + registerItemModel( Item.getItemFromBlock( block ), damage, name ); + } + + private void registerItemModel( Item item, int damage, String name ) + { + name = "computercraft:" + name; + ModelResourceLocation res = new ModelResourceLocation( name, "inventory" ); + ModelBakery.addVariantName( item, name ); + Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register( item, damage, res ); + } + + private void registerItemModel( Block block, String name ) + { + registerItemModel( Item.getItemFromBlock( block ), name ); + } + + private void registerItemModel( Item item, String name ) + { + name = "computercraft:" + name; + final ModelResourceLocation res = new ModelResourceLocation( name, "inventory" ); + ModelBakery.addVariantName( item, name ); + Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register( item, new ItemMeshDefinition() + { + @Override + public ModelResourceLocation getModelLocation( ItemStack stack ) + { + return res; + } + } ); + } + + private void registerItemModel( Block block, ItemMeshDefinition definition, String[] names ) + { + registerItemModel( Item.getItemFromBlock( block ), definition, names ); + } + + private void registerItemModel( Item item, ItemMeshDefinition definition, String[] names ) + { + for( int i=0; i 0 ) { + return info.get(0).toString(); + } else { + return super.getRecordInfo( recordStack ); + } + } + + @Override + public void playRecord( String record, String recordInfo, World world, BlockPos pos ) + { + Minecraft mc = FMLClientHandler.instance().getClient(); + world.playRecord( pos, record ); + if( record != null ) + { + mc.ingameGUI.setRecordPlayingMessage( recordInfo ); + } + } + + @Override + public Object getDiskDriveGUI( InventoryPlayer inventory, TileDiskDrive drive ) + { + return new GuiDiskDrive( inventory, drive ); + } + + @Override + public Object getComputerGUI( TileComputer computer ) + { + return new GuiComputer( computer ); + } + + @Override + public Object getPrinterGUI( InventoryPlayer inventory, TilePrinter printer ) + { + return new GuiPrinter( inventory, printer ); + } + + @Override + public Object getTurtleGUI( InventoryPlayer inventory, TileTurtle turtle ) + { + return new GuiTurtle( turtle.getWorld(), inventory, turtle ); + } + + @Override + public Object getPrintoutGUI( InventoryPlayer inventory ) + { + ContainerHeldItem container = new ContainerHeldItem( inventory ); + if( container.getStack() != null && container.getStack().getItem() instanceof ItemPrintout ) + { + return new GuiPrintout( container ); + } + return null; + } + + @Override + public Object getPocketComputerGUI( InventoryPlayer inventory ) + { + ContainerHeldItem container = new ContainerHeldItem( inventory ); + if( container.getStack() != null && container.getStack().getItem() instanceof ItemPocketComputer ) + { + return new GuiPocketComputer( container ); + } + return null; + } + + @Override + public File getWorldDir( World world ) + { + return new File( ComputerCraft.getBaseDir(), "saves/" + world.getSaveHandler().getWorldDirectoryName() ); + } + + @Override + public void handlePacket( final ComputerCraftPacket packet, final EntityPlayer player ) + { + switch( packet.m_packetType ) + { + case ComputerCraftPacket.ComputerChanged: + case ComputerCraftPacket.ComputerDeleted: + { + // Packet from Server to Client + IThreadListener listener = Minecraft.getMinecraft(); + if( listener != null ) + { + if( listener.isCallingFromMinecraftThread() ) + { + processPacket( packet, player ); + } + else + { + listener.addScheduledTask( new Runnable() + { + @Override + public void run() + { + processPacket( packet, player ); + } + } ); + } + } + break; + } + default: + { + // Packet from Client to Server + super.handlePacket( packet, player ); + break; + } + } + } + + private void processPacket( ComputerCraftPacket packet, EntityPlayer player ) + { + switch( packet.m_packetType ) + { + /////////////////////////////////// + // Packets from Server to Client // + /////////////////////////////////// + case ComputerCraftPacket.ComputerChanged: + { + int instanceID = packet.m_dataInt[ 0 ]; + if( !ComputerCraft.clientComputerRegistry.contains( instanceID ) ) + { + ComputerCraft.clientComputerRegistry.add( instanceID, new ClientComputer( instanceID ) ); + } + ComputerCraft.clientComputerRegistry.get( instanceID ).handlePacket( packet, (EntityPlayer) player ); + break; + } + case ComputerCraftPacket.ComputerDeleted: + { + int instanceID = packet.m_dataInt[ 0 ]; + if( ComputerCraft.clientComputerRegistry.contains( instanceID ) ) + { + ComputerCraft.clientComputerRegistry.remove( instanceID ); + } + break; + } + } + } + + private void registerForgeHandlers() + { + ForgeHandlers handlers = new ForgeHandlers(); + FMLCommonHandler.instance().bus().register( handlers ); + MinecraftForge.EVENT_BUS.register( handlers ); + } + + public class ForgeHandlers + { + public ForgeHandlers() + { + } + + @SubscribeEvent + public void onRenderHand( RenderHandEvent event ) + { + // Don't draw the player arm when in turtle vision + Minecraft mc = Minecraft.getMinecraft(); + if( mc.getRenderViewEntity() instanceof TurtleVisionCamera ) + { + event.setCanceled( true ); + } + } + + @SubscribeEvent + public void onRenderPlayer( RenderPlayerEvent.Pre event ) + { + Minecraft mc = Minecraft.getMinecraft(); + if( event.entityPlayer.isUser() && mc.getRenderViewEntity() instanceof TurtleVisionCamera ) + { + // HACK: Force the 'livingPlayer' variable to the player, this ensures the entity is drawn + event.renderer.getRenderManager().livingPlayer = event.entityPlayer; + } + } + + @SubscribeEvent + public void onRenderPlayer( RenderPlayerEvent.Post event ) + { + Minecraft mc = Minecraft.getMinecraft(); + if( event.entityPlayer.isUser() && mc.getRenderViewEntity() instanceof TurtleVisionCamera ) + { + // HACK: Restore the 'livingPlayer' variable to what it was before the RenderPlayerEvent.Pre hack + event.renderer.getRenderManager().livingPlayer = mc.getRenderViewEntity(); + } + } + + @SubscribeEvent + public void onPreRenderGameOverlay( RenderGameOverlayEvent.Pre event ) + { + Minecraft mc = Minecraft.getMinecraft(); + if( mc.getRenderViewEntity() instanceof TurtleVisionCamera ) + { + switch( event.type ) + { + case HELMET: + case PORTAL: + //case CROSSHAIRS: + case BOSSHEALTH: + case ARMOR: + case HEALTH: + case FOOD: + case AIR: + case HOTBAR: + case EXPERIENCE: + case HEALTHMOUNT: + case JUMPBAR: + { + event.setCanceled( true ); + break; + } + } + } + } + + @SubscribeEvent + public void onTick( TickEvent.ClientTickEvent event ) + { + if( event.phase == TickEvent.Phase.START ) + { + m_tick++; + } + } + + @SubscribeEvent + public void onRenderTick( TickEvent.RenderTickEvent event ) + { + if( event.phase == TickEvent.Phase.START ) + { + m_renderFrame++; + } + } + } +} diff --git a/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java b/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java new file mode 100644 index 0000000000..494967b7dd --- /dev/null +++ b/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java @@ -0,0 +1,287 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.client.render; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.client.gui.FixedWidthFontRenderer; +import dan200.computercraft.core.terminal.Terminal; +import dan200.computercraft.core.terminal.TextBuffer; +import dan200.computercraft.shared.common.ClientTerminal; +import dan200.computercraft.shared.common.ITerminal; +import dan200.computercraft.shared.peripheral.monitor.TileMonitor; +import dan200.computercraft.shared.util.Colour; +import dan200.computercraft.shared.util.DirectionUtil; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.MinecraftForgeClient; +import org.lwjgl.opengl.GL11; + +public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer +{ + public TileEntityMonitorRenderer() + { + } + + @Override + public void renderTileEntityAt( TileMonitor tileEntity, double posX, double posY, double posZ, float f, int i ) + { + if( tileEntity != null ) + { + renderMonitorAt( tileEntity, posX, posY, posZ, f, i ); + } + } + + private void renderMonitorAt( TileMonitor monitor, double posX, double posY, double posZ, float f, int i ) + { + // Render from the origin monitor + TileMonitor origin = monitor.getOrigin(); + if( origin == null ) + { + return; + } + + // Ensure each monitor is rendered only once + long renderFrame = ComputerCraft.getRenderFrame(); + if( origin.m_lastRenderFrame == renderFrame ) + { + return; + } + else + { + origin.m_lastRenderFrame = renderFrame; + } + + boolean redraw = origin.pollChanged(); + BlockPos monitorPos = monitor.getPos(); + BlockPos originPos = origin.getPos(); + posX += originPos.getX() - monitorPos.getX(); + posY += originPos.getY() - monitorPos.getY(); + posZ += originPos.getZ() - monitorPos.getZ(); + + // Determine orientation + EnumFacing dir = origin.getDirection(); + EnumFacing front = origin.getFront(); + float yaw = DirectionUtil.toYawAngle( dir ); + float pitch = DirectionUtil.toPitchAngle( front ); + + GlStateManager.pushMatrix(); + try + { + // Setup initial transform + GlStateManager.translate( posX + 0.5, posY + 0.5, posZ + 0.5 ); + GlStateManager.rotate( -yaw, 0.0f, 1.0f, 0.0f ); + GlStateManager.rotate( pitch, 1.0f, 0.0f, 0.0f ); + GlStateManager.translate( + -0.5 + TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN, + ((double)origin.getHeight() - 0.5) - (TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN), + 0.5 + ); + double xSize = (double)origin.getWidth() - 2.0 * ( TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER ); + double ySize = (double)origin.getHeight() - 2.0 * ( TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER ); + + // Get renderers + Minecraft mc = Minecraft.getMinecraft(); + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer renderer = tessellator.getWorldRenderer(); + + // Get terminal + ClientTerminal clientTerminal = (ClientTerminal)origin.getTerminal(); + Terminal terminal = (clientTerminal != null) ? clientTerminal.getTerminal() : null; + redraw = redraw || (clientTerminal != null && clientTerminal.hasTerminalChanged()); + + // Draw the contents + GlStateManager.depthMask( false ); + GlStateManager.disableLighting(); + try + { + if( terminal != null ) + { + // Allocate display lists + if( origin.m_renderDisplayList < 0 ) + { + origin.m_renderDisplayList = GL11.glGenLists( 3 ); + redraw = true; + } + + // Draw a terminal + boolean greyscale = !clientTerminal.isColour(); + int width = terminal.getWidth(); + int height = terminal.getHeight(); + int cursorX = terminal.getCursorX(); + int cursorY = terminal.getCursorY(); + FixedWidthFontRenderer fontRenderer = (FixedWidthFontRenderer)ComputerCraft.getFixedWidthFontRenderer(); + + GlStateManager.pushMatrix(); + try + { + double xScale = xSize / (double) ( width * FixedWidthFontRenderer.FONT_WIDTH ); + double yScale = ySize / (double) ( height * FixedWidthFontRenderer.FONT_HEIGHT ); + GlStateManager.scale( xScale, -yScale, 1.0 ); + + // Draw background + mc.getTextureManager().bindTexture( FixedWidthFontRenderer.background ); + if( redraw ) + { + // Build background display list + GL11.glNewList( origin.m_renderDisplayList, GL11.GL_COMPILE ); + try + { + double marginXSize = TileMonitor.RENDER_MARGIN / xScale; + double marginYSize = TileMonitor.RENDER_MARGIN / yScale; + double marginSquash = marginYSize / (double) FixedWidthFontRenderer.FONT_HEIGHT; + + // Top and bottom margins + GL11.glPushMatrix(); + try + { + GL11.glScaled( 1.0, marginSquash, 1.0 ); + GL11.glTranslated( 0.0, -marginYSize / marginSquash, 0.0 ); + fontRenderer.drawStringBackgroundPart( 0, 0, terminal.getBackgroundColourLine( 0 ), marginXSize, marginXSize, greyscale ); + GL11.glTranslated( 0.0, ( marginYSize + height * FixedWidthFontRenderer.FONT_HEIGHT ) / marginSquash, 0.0 ); + fontRenderer.drawStringBackgroundPart( 0, 0, terminal.getBackgroundColourLine( height - 1 ), marginXSize, marginXSize, greyscale ); + } + finally + { + GL11.glPopMatrix(); + } + + // Backgrounds + for( int y = 0; y < height; ++y ) + { + fontRenderer.drawStringBackgroundPart( + 0, FixedWidthFontRenderer.FONT_HEIGHT * y, + terminal.getBackgroundColourLine( y ), + marginXSize, marginXSize, + greyscale + ); + } + } + finally + { + GL11.glEndList(); + } + } + GlStateManager.callList( origin.m_renderDisplayList ); + + // Draw text + mc.getTextureManager().bindTexture( FixedWidthFontRenderer.font ); + if( redraw ) + { + // Build text display list + GL11.glNewList( origin.m_renderDisplayList + 1, GL11.GL_COMPILE ); + try + { + // Lines + for( int y = 0; y < height; ++y ) + { + fontRenderer.drawStringTextPart( + 0, FixedWidthFontRenderer.FONT_HEIGHT * y, + terminal.getLine( y ), + terminal.getTextColourLine( y ), + greyscale + ); + } + } + finally + { + GL11.glEndList(); + } + } + GlStateManager.callList( origin.m_renderDisplayList + 1 ); + + // Draw cursor + mc.getTextureManager().bindTexture( FixedWidthFontRenderer.font ); + if( redraw ) + { + // Build cursor display list + GL11.glNewList( origin.m_renderDisplayList + 2, GL11.GL_COMPILE ); + try + { + // Cursor + if( terminal.getCursorBlink() && cursorX >= 0 && cursorX < width && cursorY >= 0 && cursorY < height ) + { + TextBuffer cursor = new TextBuffer( "_" ); + TextBuffer cursorColour = new TextBuffer( "0123456789abcdef".charAt( terminal.getTextColour() ), 1 ); + fontRenderer.drawString( + cursor, + FixedWidthFontRenderer.FONT_WIDTH * cursorX, + FixedWidthFontRenderer.FONT_HEIGHT * cursorY, + cursorColour, null, + 0, 0, + greyscale + ); + } + } + finally + { + GL11.glEndList(); + } + } + if( ComputerCraft.getGlobalCursorBlink() ) + { + GlStateManager.callList( origin.m_renderDisplayList + 2 ); + } + } + finally + { + GlStateManager.popMatrix(); + } + } + else + { + // Draw a big black quad + mc.getTextureManager().bindTexture( FixedWidthFontRenderer.background ); + renderer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR ); + Colour colour = Colour.Black; + renderer.pos( -TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).tex( 0.0, 1.0 ).color( colour.getR(), colour.getG(), colour.getB(), 1.0f ).endVertex(); + renderer.pos( xSize + TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).tex( 1.0, 1.0 ).color( colour.getR(), colour.getG(), colour.getB(), 1.0f ).endVertex(); + renderer.pos( xSize + TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0D ).tex( 1.0, 0.0 ).color( colour.getR(), colour.getG(), colour.getB(), 1.0f ).endVertex(); + renderer.pos( -TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0D ).tex( 0.0, 0.0 ).color( colour.getR(), colour.getG(), colour.getB(), 1.0f ).endVertex(); + renderer.pos( -TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).tex( 0.0, 1.0 ).color( colour.getR(), colour.getG(), colour.getB(), 1.0f ).endVertex(); + tessellator.draw(); + } + } + finally + { + GlStateManager.depthMask( true ); + GlStateManager.enableLighting(); + } + + // Draw the depth blocker + GlStateManager.colorMask( false, false, false, false ); + try + { + mc.getTextureManager().bindTexture( FixedWidthFontRenderer.background ); + renderer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR ); + Colour colour = Colour.Black; + renderer.pos( -TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).tex( 0.0, 1.0 ).color( colour.getR(), colour.getG(), colour.getB(), 1.0f ).endVertex(); + renderer.pos( xSize + TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).tex( 1.0, 1.0 ).color( colour.getR(), colour.getG(), colour.getB(), 1.0f ).endVertex(); + renderer.pos( xSize + TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0D ).tex( 1.0, 0.0 ).color( colour.getR(), colour.getG(), colour.getB(), 1.0f ).endVertex(); + renderer.pos( -TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0D ).tex( 0.0, 0.0 ).color( colour.getR(), colour.getG(), colour.getB(), 1.0f ).endVertex(); + renderer.pos( -TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).tex( 0.0, 1.0 ).color( colour.getR(), colour.getG(), colour.getB(), 1.0f ).endVertex(); + tessellator.draw(); + } + finally + { + GlStateManager.colorMask( true, true, true, true ); + } + } + finally + { + GlStateManager.color( 1.0f, 1.0f, 1.0f, 1.0f ); + GlStateManager.popMatrix(); + } + } +} diff --git a/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java b/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java new file mode 100644 index 0000000000..51c5e7e4cc --- /dev/null +++ b/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java @@ -0,0 +1,398 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.client.render; + +import dan200.computercraft.api.turtle.ITurtleUpgrade; +import dan200.computercraft.api.turtle.TurtleSide; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.core.IComputer; +import dan200.computercraft.shared.turtle.blocks.TileTurtle; +import dan200.computercraft.shared.turtle.entity.TurtleVisionCamera; +import dan200.computercraft.shared.util.Colour; +import dan200.computercraft.shared.util.Holiday; +import dan200.computercraft.shared.util.HolidayUtil; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.resources.model.IBakedModel; +import net.minecraft.client.resources.model.ModelManager; +import net.minecraft.client.resources.model.ModelResourceLocation; +import net.minecraft.entity.Entity; +import net.minecraft.util.*; +import net.minecraftforge.client.ForgeHooksClient; +import net.minecraftforge.client.model.IFlexibleBakedModel; +import org.apache.commons.lang3.tuple.Pair; +import org.lwjgl.opengl.GL11; + +import javax.vecmath.Matrix4f; +import java.util.Iterator; +import java.util.List; + +public class TileEntityTurtleRenderer extends TileEntitySpecialRenderer +{ + private static ModelResourceLocation NORMAL_TURTLE_MODEL = new ModelResourceLocation( "computercraft:CC-Turtle", "inventory" ); + private static ModelResourceLocation ADVANCED_TURTLE_MODEL = new ModelResourceLocation( "computercraft:CC-TurtleAdvanced", "inventory" ); + private static ModelResourceLocation[] COLOUR_TURTLE_MODELS = new ModelResourceLocation[] { + new ModelResourceLocation( "computercraft:turtle_black", "inventory" ), + new ModelResourceLocation( "computercraft:turtle_red", "inventory" ), + new ModelResourceLocation( "computercraft:turtle_green", "inventory" ), + new ModelResourceLocation( "computercraft:turtle_brown", "inventory" ), + new ModelResourceLocation( "computercraft:turtle_blue", "inventory" ), + new ModelResourceLocation( "computercraft:turtle_purple", "inventory" ), + new ModelResourceLocation( "computercraft:turtle_cyan", "inventory" ), + new ModelResourceLocation( "computercraft:turtle_lightGrey", "inventory" ), + new ModelResourceLocation( "computercraft:turtle_grey", "inventory" ), + new ModelResourceLocation( "computercraft:turtle_pink", "inventory" ), + new ModelResourceLocation( "computercraft:turtle_lime", "inventory" ), + new ModelResourceLocation( "computercraft:turtle_yellow", "inventory" ), + new ModelResourceLocation( "computercraft:turtle_lightBlue", "inventory" ), + new ModelResourceLocation( "computercraft:turtle_magenta", "inventory" ), + new ModelResourceLocation( "computercraft:turtle_orange", "inventory" ), + new ModelResourceLocation( "computercraft:turtle_white", "inventory" ), + }; + private static ModelResourceLocation BEGINNER_TURTLE_MODEL = new ModelResourceLocation( "computercraftedu:CC-TurtleJunior", "inventory" ); + private static ModelResourceLocation[] BEGINNER_TURTLE_COLOUR_MODELS = new ModelResourceLocation[] { + new ModelResourceLocation( "computercraftedu:turtleJunior_black", "inventory" ), + new ModelResourceLocation( "computercraftedu:turtleJunior_red", "inventory" ), + new ModelResourceLocation( "computercraftedu:turtleJunior_green", "inventory" ), + new ModelResourceLocation( "computercraftedu:turtleJunior_brown", "inventory" ), + new ModelResourceLocation( "computercraftedu:turtleJunior_blue", "inventory" ), + new ModelResourceLocation( "computercraftedu:turtleJunior_purple", "inventory" ), + new ModelResourceLocation( "computercraftedu:turtleJunior_cyan", "inventory" ), + new ModelResourceLocation( "computercraftedu:turtleJunior_lightGrey", "inventory" ), + new ModelResourceLocation( "computercraftedu:turtleJunior_grey", "inventory" ), + new ModelResourceLocation( "computercraftedu:turtleJunior_pink", "inventory" ), + new ModelResourceLocation( "computercraftedu:turtleJunior_lime", "inventory" ), + new ModelResourceLocation( "computercraftedu:turtleJunior_yellow", "inventory" ), + new ModelResourceLocation( "computercraftedu:turtleJunior_lightBlue", "inventory" ), + new ModelResourceLocation( "computercraftedu:turtleJunior_magenta", "inventory" ), + new ModelResourceLocation( "computercraftedu:turtleJunior_orange", "inventory" ), + new ModelResourceLocation( "computercraftedu:turtleJunior_white", "inventory" ), + }; + private static ModelResourceLocation ELF_OVERLAY_MODEL = new ModelResourceLocation( "computercraft:turtle_elf_overlay", "inventory" ); + + public TileEntityTurtleRenderer() + { + } + + @Override + public void renderTileEntityAt( TileTurtle tileEntity, double posX, double posY, double posZ, float f, int i ) + { + if( tileEntity != null ) + { + // Check the turtle isn't first person + Entity viewEntity = Minecraft.getMinecraft().getRenderViewEntity(); + if( viewEntity != null && viewEntity instanceof TurtleVisionCamera ) + { + TurtleVisionCamera camera = (TurtleVisionCamera)viewEntity; + if( camera.getTurtle() == tileEntity.getAccess() ) + { + return; + } + } + + // Render the turtle + renderTurtleAt( tileEntity, posX, posY, posZ, f, i ); + } + } + + public static ModelResourceLocation getTurtleModel( ComputerFamily family, Colour colour ) + { + switch( family ) + { + case Normal: + default: + { + if( colour != null ) + { + return COLOUR_TURTLE_MODELS[ colour.ordinal() ]; + } + else + { + return NORMAL_TURTLE_MODEL; + } + } + case Advanced: + { + if( colour != null ) + { + return COLOUR_TURTLE_MODELS[ colour.ordinal() ]; + } + else + { + return ADVANCED_TURTLE_MODEL; + } + } + case Beginners: + { + if( colour != null ) + { + return BEGINNER_TURTLE_COLOUR_MODELS[ colour.ordinal() ]; + } + else + { + return BEGINNER_TURTLE_MODEL; + } + } + } + } + + public static ModelResourceLocation getTurtleOverlayModel( ComputerFamily family, ResourceLocation overlay, boolean christmas ) + { + if( overlay != null ) + { + return new ModelResourceLocation( overlay, "inventory" ); + } + else if( christmas && family != ComputerFamily.Beginners ) + { + return ELF_OVERLAY_MODEL; + } + else + { + return null; + } + } + + private void renderTurtleAt( TileTurtle turtle, double posX, double posY, double posZ, float f, int i ) + { + GlStateManager.pushMatrix(); + try + { + // Setup the transform + Vec3 offset; + float yaw; + if( turtle != null ) + { + offset = turtle.getRenderOffset( f ); + yaw = turtle.getRenderYaw( f ); + } + else + { + offset = new Vec3( 0.0, 0.0, 0.0 ); + yaw = 0.0f; + } + GlStateManager.translate( posX + offset.xCoord, posY + offset.yCoord, posZ + offset.zCoord ); + + // Render the label + IComputer computer = (turtle != null) ? turtle.getComputer() : null; + String label = (computer != null) ? computer.getLabel() : null; + if( label != null ) + { + renderLabel( turtle.getAccess().getPosition(), label ); + } + + // Render the turtle + GlStateManager.translate( 0.5f, 0.0f, 0.5f ); + GlStateManager.rotate( 180.0f - yaw, 0.0f, 1.0f, 0.0f ); + GlStateManager.translate( -0.5f, 0.0f, -0.5f ); + + // Render the turtle + Colour colour; + ComputerFamily family; + ResourceLocation overlay; + if( turtle != null ) + { + colour = turtle.getColour(); + family = turtle.getFamily(); + overlay = turtle.getOverlay(); + } + else + { + colour = null; + family = ComputerFamily.Normal; + overlay = null; + } + renderModel( getTurtleModel( family, colour ) ); + + // Render the overlay + ModelResourceLocation overlayModel = getTurtleOverlayModel( + family, + overlay, + HolidayUtil.getCurrentHoliday() == Holiday.Christmas + ); + if( overlayModel != null ) + { + GlStateManager.disableCull(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc( GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA ); + try + { + renderModel( overlayModel ); + } + finally + { + GlStateManager.disableBlend(); + GlStateManager.enableCull(); + } + } + + // Render the upgrades + if( turtle != null ) + { + renderUpgrade( turtle, TurtleSide.Left, f ); + renderUpgrade( turtle, TurtleSide.Right, f ); + } + } + finally + { + GlStateManager.popMatrix(); + } + } + + private void renderUpgrade( TileTurtle turtle, TurtleSide side, float f ) + { + ITurtleUpgrade upgrade = turtle.getUpgrade( side ); + if( upgrade != null ) + { + GlStateManager.pushMatrix(); + try + { + float toolAngle = turtle.getToolRenderAngle( side, f ); + GlStateManager.translate( 0.0f, 0.5f, 0.5f ); + GlStateManager.rotate( -toolAngle, 1.0f, 0.0f, 0.0f ); + GlStateManager.translate( 0.0f, -0.5f, -0.5f ); + + Pair pair = upgrade.getModel( turtle.getAccess(), side ); + if( pair != null ) + { + if( pair.getRight() != null ) + { + ForgeHooksClient.multiplyCurrentGlMatrix( pair.getRight() ); + } + if( pair.getLeft() != null ) + { + renderModel( pair.getLeft() ); + } + } + } + finally + { + GlStateManager.popMatrix(); + } + } + } + + private void renderModel( ModelResourceLocation modelLocation ) + { + Minecraft mc = Minecraft.getMinecraft(); + ModelManager modelManager = mc.getRenderItem().getItemModelMesher().getModelManager(); + renderModel( modelManager.getModel( modelLocation ) ); + } + + private void renderModel( IBakedModel model ) + { + if( model instanceof IFlexibleBakedModel ) + { + renderModel( (IFlexibleBakedModel) model ); + } + else + { + renderModel( new IFlexibleBakedModel.Wrapper( model, DefaultVertexFormats.ITEM ) ); + } + } + + private void renderModel( IFlexibleBakedModel model ) + { + Minecraft mc = Minecraft.getMinecraft(); + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer renderer = tessellator.getWorldRenderer(); + mc.getTextureManager().bindTexture( TextureMap.locationBlocksTexture ); + renderer.begin( GL11.GL_QUADS, model.getFormat() ); + for( EnumFacing facing : EnumFacing.VALUES ) + { + renderQuads( renderer, model.getFaceQuads( facing ) ); + } + renderQuads( renderer, model.getGeneralQuads() ); + tessellator.draw(); + } + + private void renderQuads( WorldRenderer renderer, List quads ) + { + int color = 0xFFFFFFFF; + Iterator it = quads.iterator(); + while( it.hasNext() ) + { + BakedQuad quad = (BakedQuad)it.next(); + net.minecraftforge.client.model.pipeline.LightUtil.renderQuadColor( renderer, quad, color ); + } + } + + private void renderLabel( BlockPos position, String label ) + { + Minecraft mc = Minecraft.getMinecraft(); + MovingObjectPosition mop = mc.objectMouseOver; + if( mop != null && mop.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK && mop.getBlockPos().equals( position ) ) + { + RenderManager renderManager = mc.getRenderManager(); + FontRenderer fontrenderer = renderManager.getFontRenderer(); + float scale = 0.016666668F * 1.6f; + + GlStateManager.pushMatrix(); + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc( GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA ); + try + { + GlStateManager.translate( 0.5f, 1.25f, 0.5f ); + GlStateManager.rotate( -renderManager.playerViewY, 0.0F, 1.0F, 0.0F ); + GlStateManager.rotate( renderManager.playerViewX, 1.0F, 0.0F, 0.0F ); + GlStateManager.scale( -scale, -scale, scale ); + + int yOffset = 0; + int xOffset = fontrenderer.getStringWidth( label ) / 2; + + // Draw background + GlStateManager.depthMask( false ); + GlStateManager.disableDepth(); + try + { + // Quad + GlStateManager.disableTexture2D(); + try + { + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer renderer = tessellator.getWorldRenderer(); + renderer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR ); + renderer.pos( (double) ( -xOffset - 1 ), (double) ( -1 + yOffset ), 0.0D ).color( 0.0F, 0.0F, 0.0F, 0.25F ).endVertex(); + renderer.pos( (double) ( -xOffset - 1 ), (double) ( 8 + yOffset ), 0.0D ).color( 0.0F, 0.0F, 0.0F, 0.25F ).endVertex(); + renderer.pos( (double) ( xOffset + 1 ), (double) ( 8 + yOffset ), 0.0D ).color( 0.0F, 0.0F, 0.0F, 0.25F ).endVertex(); + renderer.pos( (double) ( xOffset + 1 ), (double) ( -1 + yOffset ), 0.0D ).color( 0.0F, 0.0F, 0.0F, 0.25F ).endVertex(); + tessellator.draw(); + } + finally + { + GlStateManager.enableTexture2D(); + } + + // Text + fontrenderer.drawString( label, -fontrenderer.getStringWidth( label ) / 2, yOffset, 0x20ffffff ); + } + finally + { + GlStateManager.enableDepth(); + GlStateManager.depthMask( true ); + } + + // Draw foreground text + fontrenderer.drawString( label, -fontrenderer.getStringWidth( label ) / 2, yOffset, -1 ); + } + finally + { + GlStateManager.disableBlend(); + GlStateManager.enableLighting(); + GlStateManager.popMatrix(); + } + } + } +} diff --git a/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java b/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java new file mode 100644 index 0000000000..a5eee071b4 --- /dev/null +++ b/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java @@ -0,0 +1,195 @@ +package dan200.computercraft.client.render; + +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.block.model.ItemCameraTransforms; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.renderer.vertex.VertexFormat; +import net.minecraft.client.renderer.vertex.VertexFormatElement; +import net.minecraft.client.resources.model.IBakedModel; +import net.minecraft.util.EnumFacing; +import net.minecraftforge.client.model.IFlexibleBakedModel; + +import javax.vecmath.Matrix4f; +import javax.vecmath.Point3f; +import java.util.ArrayList; +import java.util.List; + +public class TurtleMultiModel implements IFlexibleBakedModel +{ + private IFlexibleBakedModel m_baseModel; + private IFlexibleBakedModel m_overlayModel; + private IFlexibleBakedModel m_leftUpgradeModel; + private IFlexibleBakedModel m_rightUpgradeModel; + + private List m_generalQuads; + private List[] m_faceQuads; + + public TurtleMultiModel( IBakedModel baseModel, IBakedModel overlayModel, IBakedModel leftUpgradeModel, Matrix4f leftUpgradeTransform, IBakedModel rightUpgradeModel, Matrix4f rightUpgradeTransform ) + { + // Get the models + m_baseModel = makeFlexible( baseModel ); + m_overlayModel = makeFlexible( overlayModel ); + m_leftUpgradeModel = makeFlexible( leftUpgradeModel ); + m_rightUpgradeModel = makeFlexible( rightUpgradeModel ); + + // Bake the quads + m_generalQuads = new ArrayList(); + m_generalQuads.addAll( m_baseModel.getGeneralQuads() ); + if( m_overlayModel != null ) + { + m_generalQuads.addAll( m_overlayModel.getGeneralQuads() ); + } + if( m_leftUpgradeModel != null ) + { + m_generalQuads.addAll( transformQuads( m_leftUpgradeModel.getFormat(), m_leftUpgradeModel.getGeneralQuads(), leftUpgradeTransform ) ); + } + if( m_rightUpgradeModel != null ) + { + m_generalQuads.addAll( transformQuads( m_rightUpgradeModel.getFormat(), m_rightUpgradeModel.getGeneralQuads(), rightUpgradeTransform ) ); + } + + m_faceQuads = new List[ EnumFacing.VALUES.length ]; + for( EnumFacing facing : EnumFacing.VALUES ) + { + List faces = new ArrayList(); + faces.addAll( m_baseModel.getFaceQuads( facing ) ); + if( m_overlayModel != null ) + { + faces.addAll( m_overlayModel.getFaceQuads( facing ) ); + } + if( m_leftUpgradeModel != null ) + { + faces.addAll( transformQuads( m_leftUpgradeModel.getFormat(), m_leftUpgradeModel.getFaceQuads( facing ), leftUpgradeTransform ) ); + } + if( m_rightUpgradeModel != null ) + { + faces.addAll( transformQuads( m_rightUpgradeModel.getFormat(), m_rightUpgradeModel.getFaceQuads( facing ), rightUpgradeTransform ) ); + } + m_faceQuads[ facing.getIndex() ] = faces; + } + } + + @Override + public List getFaceQuads( EnumFacing side ) + { + return m_faceQuads[ side.getIndex() ]; + } + + @Override + public List getGeneralQuads() + { + return m_generalQuads; + } + + @Override + public boolean isAmbientOcclusion() + { + return m_baseModel.isAmbientOcclusion(); + } + + @Override + public boolean isGui3d() + { + return m_baseModel.isGui3d(); + } + + @Override + public boolean isBuiltInRenderer() + { + return m_baseModel.isBuiltInRenderer(); + } + + @Override + public TextureAtlasSprite getParticleTexture() + { + return m_baseModel.getParticleTexture(); + } + + @Override + public ItemCameraTransforms getItemCameraTransforms() + { + return m_baseModel.getItemCameraTransforms(); + } + + @Override + public VertexFormat getFormat() + { + return m_baseModel.getFormat(); + } + + private List transformQuads( VertexFormat format, List input, Matrix4f transform ) + { + if( transform == null || input.size() == 0 ) + { + return input; + } + else + { + List output = new ArrayList( input.size() ); + for( int i=0; i m_cachedModels; + + public TurtleSmartItemModel() + { + m_defaultItem = TurtleItemFactory.create( -1, null, null, ComputerFamily.Normal, null, null, 0, null ); + m_cachedModels = new HashMap(); + } + + @Override + public void onResourceManagerReload( IResourceManager resourceManager ) + { + m_cachedModels.clear(); + } + + @Override + public IBakedModel handleItemState( ItemStack stack ) + { + ItemTurtleBase turtle = (ItemTurtleBase) stack.getItem(); + ComputerFamily family = turtle.getFamily( stack ); + Colour colour = turtle.getColour( stack ); + ITurtleUpgrade leftUpgrade = turtle.getUpgrade( stack, TurtleSide.Left ); + ITurtleUpgrade rightUpgrade = turtle.getUpgrade( stack, TurtleSide.Right ); + ResourceLocation overlay = turtle.getOverlay( stack ); + boolean christmas = HolidayUtil.getCurrentHoliday() == Holiday.Christmas; + TurtleModelCombination combo = new TurtleModelCombination( family, colour, leftUpgrade, rightUpgrade, overlay, christmas ); + if( m_cachedModels.containsKey( combo ) ) + { + return m_cachedModels.get( combo ); + } + else + { + IBakedModel model = buildModel( combo ); + m_cachedModels.put( combo, model ); + return model; + } + } + + private IBakedModel buildModel( TurtleModelCombination combo ) + { + Minecraft mc = Minecraft.getMinecraft(); + ModelManager modelManager = mc.getRenderItem().getItemModelMesher().getModelManager(); + ModelResourceLocation baseModelLocation = TileEntityTurtleRenderer.getTurtleModel( combo.m_family, combo.m_colour ); + ModelResourceLocation overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.m_family, combo.m_overlay, combo.m_christmas ); + IBakedModel baseModel = modelManager.getModel( baseModelLocation ); + IBakedModel overlayModel = (overlayModelLocation != null) ? modelManager.getModel( baseModelLocation ) : null; + Pair leftModel = (combo.m_leftUpgrade != null) ? combo.m_leftUpgrade.getModel( null, TurtleSide.Left ) : null; + Pair rightModel = (combo.m_rightUpgrade != null) ? combo.m_rightUpgrade.getModel( null, TurtleSide.Right ) : null; + if( leftModel != null && rightModel != null ) + { + return new TurtleMultiModel( baseModel, overlayModel, leftModel.getLeft(), leftModel.getRight(), rightModel.getLeft(), rightModel.getRight() ); + } + else if( leftModel != null ) + { + return new TurtleMultiModel( baseModel, overlayModel, leftModel.getLeft(), leftModel.getRight(), null, null ); + } + else if( rightModel != null ) + { + return new TurtleMultiModel( baseModel, overlayModel, null, null, rightModel.getLeft(), rightModel.getRight() ); + } + else if( overlayModel != null ) + { + return new TurtleMultiModel( baseModel, overlayModel, null, null, null, null ); + } + else + { + return baseModel; + } + } + + // These should not be called: + + @Override + public List getFaceQuads( EnumFacing facing ) + { + return getDefaultModel().getFaceQuads( facing ); + } + + @Override + public List getGeneralQuads() + { + return getDefaultModel().getGeneralQuads(); + } + + @Override + public boolean isAmbientOcclusion() + { + return getDefaultModel().isAmbientOcclusion(); + } + + @Override + public boolean isGui3d() + { + return getDefaultModel().isGui3d(); + } + + @Override + public boolean isBuiltInRenderer() + { + return getDefaultModel().isBuiltInRenderer(); + } + + @Override + public TextureAtlasSprite getParticleTexture() + { + return getDefaultModel().getParticleTexture(); + } + + @Override + public ItemCameraTransforms getItemCameraTransforms() + { + return getDefaultModel().getItemCameraTransforms(); + } + + private IBakedModel getDefaultModel() + { + return handleItemState( m_defaultItem ); + } +} diff --git a/src/main/java/dan200/computercraft/core/apis/BitAPI.java b/src/main/java/dan200/computercraft/core/apis/BitAPI.java new file mode 100644 index 0000000000..a7f5e7824d --- /dev/null +++ b/src/main/java/dan200/computercraft/core/apis/BitAPI.java @@ -0,0 +1,112 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.apis; + +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.LuaException; + +// Contributed by Nia +// Based on LuaBit (http://luaforge.net/projects/bit) + +public class BitAPI implements ILuaAPI +{ + private static final int BNOT = 0; + private static final int BAND = 1; + private static final int BOR = 2; + private static final int BXOR = 3; + private static final int BRSHIFT = 4; + private static final int BLSHIFT = 5; + private static final int BLOGIC_RSHIFT = 6; + + private static int checkInt( Object o, int count ) throws LuaException + { + if( o instanceof Number ) + { + return (int)(((Number)o).longValue()); + } + else + { + if( count == 2 ) + { + throw new LuaException( "Expected number, number" ); + } + else + { + throw new LuaException( "Expected number" ); + } + } + } + + public BitAPI( IAPIEnvironment _environment ) + { + } + + @Override + public String[] getNames() + { + return new String[] { + "bit" + }; + } + + @Override + public void startup( ) + { + } + + @Override + public void advance( double _dt ) + { + } + + @Override + public void shutdown( ) + { + } + + @Override + public String[] getMethodNames() { + return new String[] { + "bnot", "band", "bor", "bxor", + "brshift", "blshift", "blogic_rshift" + }; + } + + @Override + public Object[] callMethod( ILuaContext context, int method, Object[] args ) throws LuaException + { + Object a = args.length>0?args[0]:null; + Object b = args.length>1?args[1]:null; + + int ret = 0; + switch(method) { + case BNOT: + ret = ~checkInt(a, 1); + break; + case BAND: + ret = checkInt(a, 2) & checkInt(b, 2); + break; + case BOR: + ret = checkInt(a, 2) | checkInt(b, 2); + break; + case BXOR: + ret = checkInt(a, 2) ^ checkInt(b, 2); + break; + case BRSHIFT: + ret = checkInt(a, 2) >> checkInt(b, 2); + break; + case BLSHIFT: + ret = checkInt(a, 2) << checkInt(b, 2); + break; + case BLOGIC_RSHIFT: + ret = checkInt(a, 2) >>> checkInt(b, 2); + break; + } + + return new Object[]{ ret&0xFFFFFFFFL }; + } +} diff --git a/src/main/java/dan200/computercraft/core/apis/BufferAPI.java b/src/main/java/dan200/computercraft/core/apis/BufferAPI.java new file mode 100644 index 0000000000..546f7037bf --- /dev/null +++ b/src/main/java/dan200/computercraft/core/apis/BufferAPI.java @@ -0,0 +1,210 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.apis; + +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.ILuaObject; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.core.terminal.TextBuffer; + +public class BufferAPI implements ILuaAPI +{ + private static class BufferLuaObject implements ILuaObject + { + private TextBuffer m_buffer; + + public BufferLuaObject( TextBuffer buffer ) + { + m_buffer = buffer; + } + + @Override + public String[] getMethodNames() + { + return new String[] { + "len", + "tostring", + "read", + "write", + "fill" + }; + } + + @Override + public Object[] callMethod( ILuaContext context, int method, Object[] arguments ) throws LuaException, InterruptedException + { + switch( method ) + { + case 0: + { + // len + return new Object[] { m_buffer.length() }; + } + case 1: + { + // tostring + return new Object[] { m_buffer.toString() }; + } + case 2: + { + // read + int start = 0; + if( arguments.length >= 1 && (arguments[0] != null) ) + { + if( !(arguments[0] instanceof Number) ) + { + throw new LuaException( "Expected number" ); + } + start = ((Number)arguments[1]).intValue() - 1; + } + int end = m_buffer.length(); + if( arguments.length >= 2 && (arguments[1] != null) ) + { + if( !(arguments[1] instanceof Number) ) + { + throw new LuaException( "Expected number, number" ); + } + end = ((Number)arguments[1]).intValue(); + } + return new Object[] { m_buffer.read( start, end ) }; + } + case 3: + { + // write + if( arguments.length < 1 || !(arguments[0] instanceof String) ) + { + throw new LuaException( "Expected string" ); + } + String text = (String)(arguments[0]); + int start = 0; + if( arguments.length >= 2 && (arguments[1] != null) ) + { + if( !(arguments[1] instanceof Number) ) + { + throw new LuaException( "Expected string, number" ); + } + start = ((Number)arguments[1]).intValue() - 1; + } + int end = start + text.length(); + if( arguments.length >= 3 && (arguments[2] != null) ) + { + if( !(arguments[2] instanceof Number) ) + { + throw new LuaException( "Expected string, number, number" ); + } + end = ((Number)arguments[2]).intValue(); + } + m_buffer.write( text, start, end ); + return null; + } + case 4: + { + // fill + if( arguments.length < 1 || !(arguments[0] instanceof String) ) + { + throw new LuaException( "Expected string" ); + } + String text = (String)(arguments[0]); + int start = 0; + if( arguments.length >= 2 && (arguments[1] != null) ) + { + if( !(arguments[1] instanceof Number) ) + { + throw new LuaException( "Expected string, number" ); + } + start = ((Number)arguments[1]).intValue() - 1; + } + int end = m_buffer.length(); + if( arguments.length >= 3 && (arguments[2] != null) ) + { + if( !(arguments[2] instanceof Number) ) + { + throw new LuaException( "Expected string, number, number" ); + } + end = ((Number)arguments[2]).intValue(); + } + m_buffer.fill( text, start, end ); + return null; + } + default: + { + return null; + } + } + } + } + + public BufferAPI( IAPIEnvironment _env ) + { + } + + @Override + public String[] getNames() + { + return new String[] { + "buffer" + }; + } + + @Override + public void startup() + { + } + + @Override + public void advance( double _dt ) + { + } + + @Override + public void shutdown() + { + } + + @Override + public String[] getMethodNames() + { + return new String[] { + "new" + }; + } + + @Override + public Object[] callMethod( ILuaContext context, int method, Object[] arguments ) throws LuaException, InterruptedException + { + switch( method ) + { + case 0: + { + if( arguments.length < 1 || !(arguments[0] instanceof String) ) + { + throw new LuaException( "Expected string" ); + } + String text = (String)(arguments[0]); + int repetitions = 1; + if( arguments.length >= 2 && arguments[1] != null ) + { + if( !(arguments[1] instanceof Number) ) + { + throw new LuaException( "Expected string, number" ); + } + repetitions = ((Number)arguments[1]).intValue(); + if( repetitions < 0 ) + { + throw new LuaException( "Expected positive number" ); + } + } + TextBuffer buffer = new TextBuffer( text, repetitions ); + return new Object[] { new BufferLuaObject( buffer ) }; + } + default: + { + return null; + } + } + } +} diff --git a/src/main/java/dan200/computercraft/core/apis/FSAPI.java b/src/main/java/dan200/computercraft/core/apis/FSAPI.java new file mode 100644 index 0000000000..0eaf49ba58 --- /dev/null +++ b/src/main/java/dan200/computercraft/core/apis/FSAPI.java @@ -0,0 +1,630 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.apis; + +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.ILuaObject; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.core.filesystem.FileSystem; +import dan200.computercraft.core.filesystem.FileSystemException; +import dan200.computercraft.core.filesystem.IMountedFileBinary; +import dan200.computercraft.core.filesystem.IMountedFileNormal; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class FSAPI implements ILuaAPI +{ + private IAPIEnvironment m_env; + private FileSystem m_fileSystem; + + public FSAPI( IAPIEnvironment _env ) + { + m_env = _env; + m_fileSystem = null; + } + + @Override + public String[] getNames() + { + return new String[] { + "fs" + }; + } + + @Override + public void startup( ) + { + m_fileSystem = m_env.getFileSystem(); + } + + @Override + public void advance( double _dt ) + { + } + + @Override + public void shutdown( ) + { + m_fileSystem = null; + } + + @Override + public String[] getMethodNames() + { + return new String[] { + "list", + "combine", + "getName", + "getSize", + "exists", + "isDir", + "isReadOnly", + "makeDir", + "move", + "copy", + "delete", + "open", + "getDrive", + "getFreeSpace", + "find", + "getDir", + }; + } + + @Override + public Object[] callMethod( ILuaContext context, int method, Object[] args ) throws LuaException + { + switch( method ) + { + case 0: + { + // list + if( args.length != 1 || args[0] == null || !(args[0] instanceof String) ) + { + throw new LuaException( "Expected string" ); + } + String path = (String)args[0]; + try { + String[] results = m_fileSystem.list( path ); + Map table = new HashMap(); + for(int i=0; i= 0 ) + { + return new Object[]{ freeSpace }; + } + return new Object[]{ "unlimited" }; + } catch( FileSystemException e ) { + throw new LuaException( e.getMessage() ); + } + } + case 14: + { + // find + if( args.length != 1 || args[0] == null || !(args[0] instanceof String) ) + { + throw new LuaException( "Expected string" ); + } + String path = (String)args[0]; + try { + String[] results = m_fileSystem.find( path ); + Map table = new HashMap(); + for(int i=0; i 0 && args[0] != null ) { + text = args[0].toString(); + } else { + text = ""; + } + try { + writer.write( text, 0, text.length(), false ); + return null; + } catch( IOException e ) { + throw new LuaException( e.getMessage() ); + } + } + case 1: + { + // writeLine + String text; + if( args.length > 0 && args[0] != null ) { + text = args[0].toString(); + } else { + text = ""; + } + try { + writer.write( text, 0, text.length(), true ); + return null; + } catch( IOException e ) { + throw new LuaException( e.getMessage() ); + } + } + case 2: + { + // close + try { + writer.close(); + return null; + } catch( IOException e ) { + return null; + } + } + case 3: + { + try { + writer.flush(); + return null; + } catch ( IOException e ) { + return null; + } + } + default: + { + assert( false ); + return null; + } + } + } + } }; + } + + private static Object[] wrapInputStream( final IMountedFileBinary reader ) + { + + return new Object[] { new ILuaObject() { + + @Override + public String[] getMethodNames() { + return new String[] { + "read", + "close" + }; + } + + @Override + public Object[] callMethod( ILuaContext context, int method, Object[] args) throws LuaException { + switch( method ) + { + case 0: + { + // read + try { + int b = reader.read(); + if( b != -1 ) { + return new Object[] { b }; + } else { + return null; + } + } catch( IOException e ) { + return null; + } + } + case 1: + { + //close + try { + reader.close(); + return null; + } catch( IOException e ) { + return null; + } + } + default: + { + assert( false ); + return null; + } + } + } + }}; + } + + private static Object[] wrapOutputStream( final IMountedFileBinary writer ) + { + + return new Object[] { new ILuaObject() { + + @Override + public String[] getMethodNames() { + return new String[] { + "write", + "close", + "flush" + }; + } + + @Override + public Object[] callMethod( ILuaContext context, int method, Object[] args) throws LuaException { + switch( method ) + { + case 0: + { + // write + try { + if( args.length > 0 && args[0] instanceof Number ) + { + int number = ((Number)args[0]).intValue(); + writer.write( number ); + } + return null; + } catch( IOException e ) { + throw new LuaException(e.getMessage()); + } + } + case 1: + { + //close + try { + writer.close(); + return null; + } catch( IOException e ) { + return null; + } + } + case 2: + { + try { + writer.flush(); + return null; + } catch ( IOException e ) { + return null; + } + } + default: + { + assert( false ); + return null; + } + } + } + }}; + } +} diff --git a/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java b/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java new file mode 100644 index 0000000000..706880851d --- /dev/null +++ b/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java @@ -0,0 +1,246 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.apis; + +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.ILuaObject; +import dan200.computercraft.api.lua.LuaException; + +import java.io.BufferedReader; +import java.io.IOException; +import java.util.*; + +public class HTTPAPI implements ILuaAPI +{ + private IAPIEnvironment m_apiEnvironment; + private List m_httpRequests; + + public HTTPAPI( IAPIEnvironment environment ) + { + m_apiEnvironment = environment; + m_httpRequests = new ArrayList(); + } + + @Override + public String[] getNames() + { + return new String[] { + "http" + }; + } + + @Override + public void startup( ) + { + } + + @Override + public void advance( double _dt ) + { + // Wait for all of our http requests + synchronized( m_httpRequests ) + { + Iterator it = m_httpRequests.iterator(); + while( it.hasNext() ) { + final HTTPRequest h = it.next(); + if( h.isComplete() ) { + final String url = h.getURL(); + if( h.wasSuccessful() ) { + // Queue the "http_success" event + final BufferedReader contents = h.getContents(); + final int responseCode = h.getResponseCode(); + final Object result = wrapBufferedReader( contents, responseCode ); + m_apiEnvironment.queueEvent( "http_success", new Object[] { url, result } ); + } else { + // Queue the "http_failure" event + m_apiEnvironment.queueEvent( "http_failure", new Object[] { url, "Could not connect" } ); + } + it.remove(); + } + } + } + } + + private static ILuaObject wrapBufferedReader( final BufferedReader reader, final int responseCode ) + { + return new ILuaObject() { + @Override + public String[] getMethodNames() + { + return new String[] { + "readLine", + "readAll", + "close", + "getResponseCode" + }; + } + + @Override + public Object[] callMethod( ILuaContext context, int method, Object[] args ) throws LuaException + { + switch( method ) + { + case 0: + { + // readLine + try { + String line = reader.readLine(); + if( line != null ) { + return new Object[] { line }; + } else { + return null; + } + } catch( IOException e ) { + return null; + } + } + case 1: + { + // readAll + try { + StringBuilder result = new StringBuilder( "" ); + String line = reader.readLine(); + while( line != null ) { + result.append( line ); + line = reader.readLine(); + if( line != null ) { + result.append( "\n" ); + } + } + return new Object[] { result.toString() }; + } catch( IOException e ) { + return null; + } + } + case 2: + { + // close + try { + reader.close(); + return null; + } catch( IOException e ) { + return null; + } + } + case 3: + { + // getResponseCode + return new Object[] { responseCode }; + } + default: + { + return null; + } + } + } + }; + } + + @Override + public void shutdown( ) + { + synchronized( m_httpRequests ) + { + Iterator it = m_httpRequests.iterator(); + while( it.hasNext() ) { + HTTPRequest r = it.next(); + r.cancel(); + } + m_httpRequests.clear(); + } + } + + @Override + public String[] getMethodNames() + { + return new String[] { + "request", + "checkURL" + }; + } + + @Override + public Object[] callMethod( ILuaContext context, int method, Object[] args ) throws LuaException + { + switch( method ) + { + case 0: + { + // request + // Get URL + if( args.length < 1 || !(args[0] instanceof String) ) + { + throw new LuaException( "Expected string" ); + } + String urlString = args[0].toString(); + + // Get POST + String postString = null; + if( args.length >= 2 && args[1] instanceof String ) + { + postString = args[1].toString(); + } + + // Get Headers + Map headers = null; + if( args.length >= 3 && args[2] instanceof Map ) + { + Map table = (Map)args[2]; + headers = new HashMap( table.size() ); + for( Object key : table.keySet() ) + { + Object value = table.get( key ); + if( key instanceof String && value instanceof String ) + { + headers.put( (String)key, (String)value ); + } + } + } + + // Make the request + try + { + HTTPRequest request = new HTTPRequest( urlString, postString, headers ); + synchronized( m_httpRequests ) + { + m_httpRequests.add( request ); + } + return new Object[] { true }; + } + catch( HTTPRequestException e ) + { + return new Object[] { false, e.getMessage() }; + } + } + case 1: + { + // checkURL + // Get URL + if( args.length < 1 || !(args[0] instanceof String) ) + { + throw new LuaException( "Expected string" ); + } + String urlString = args[0].toString(); + + // Check URL + try + { + HTTPRequest.checkURL( urlString ); + return new Object[] { true }; + } + catch( HTTPRequestException e ) + { + return new Object[] { false, e.getMessage() }; + } + } + default: + { + return null; + } + } + } +} \ No newline at end of file diff --git a/src/main/java/dan200/computercraft/core/apis/HTTPRequest.java b/src/main/java/dan200/computercraft/core/apis/HTTPRequest.java new file mode 100644 index 0000000000..cd6b4effe8 --- /dev/null +++ b/src/main/java/dan200/computercraft/core/apis/HTTPRequest.java @@ -0,0 +1,273 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.apis; + +import dan200.computercraft.ComputerCraft; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Map; +import java.util.regex.Pattern; + +class HTTPRequestException extends Exception { + public HTTPRequestException( String s ) { + super( s ); + } +} + +public class HTTPRequest +{ + public static URL checkURL( String urlString ) throws HTTPRequestException + { + URL url; + try + { + url = new URL( urlString ); + } + catch( MalformedURLException e ) + { + throw new HTTPRequestException( "URL malformed" ); + } + + // Validate the URL + String protocol = url.getProtocol().toLowerCase(); + if( !protocol.equals("http") && !protocol.equals("https") ) + { + throw new HTTPRequestException( "URL not http" ); + } + + // Compare the URL to the whitelist + boolean allowed = false; + String whitelistString = ComputerCraft.http_whitelist; + String[] allowedURLs = whitelistString.split( ";" ); + for( int i=0; i headers ) throws HTTPRequestException + { + // Parse the URL + m_urlString = url; + m_url = checkURL( m_urlString ); + + // Start the thread + m_cancelled = false; + m_complete = false; + m_success = false; + m_result = null; + m_responseCode = -1; + + Thread thread = new Thread( new Runnable() { + @Override + public void run() + { + try + { + // Connect to the URL + HttpURLConnection connection = (HttpURLConnection)m_url.openConnection(); + + if( postText != null ) + { + connection.setRequestMethod( "POST" ); + connection.setDoOutput( true ); + } + else + { + connection.setRequestMethod( "GET" ); + } + + // Set headers + connection.setRequestProperty( "accept-charset", "UTF-8" ); + if( postText != null ) + { + connection.setRequestProperty( "content-type", "application/x-www-form-urlencoded; charset=utf-8" ); + connection.setRequestProperty( "content-encoding", "UTF-8" ); + } + if( headers != null ) + { + for( Map.Entry header : headers.entrySet() ) + { + connection.setRequestProperty( header.getKey(), header.getValue() ); + } + } + + // Send POST text + if( postText != null ) + { + OutputStream os = connection.getOutputStream(); + OutputStreamWriter osw; + try + { + osw = new OutputStreamWriter( os, "UTF-8" ); + } + catch( UnsupportedEncodingException e ) + { + osw = new OutputStreamWriter( os ); + } + BufferedWriter writer = new BufferedWriter( osw ); + writer.write( postText, 0, postText.length() ); + writer.close(); + } + + // Read response + InputStream is = connection.getInputStream(); + InputStreamReader isr; + try + { + String contentEncoding = connection.getContentEncoding(); + if( contentEncoding != null ) + { + try + { + isr = new InputStreamReader( is, contentEncoding ); + } + catch( UnsupportedEncodingException e ) + { + isr = new InputStreamReader( is, "UTF-8" ); + } + } + else + { + isr = new InputStreamReader( is, "UTF-8" ); + } + } + catch( UnsupportedEncodingException e ) + { + isr = new InputStreamReader( is ); + } + + // Download the contents + BufferedReader reader = new BufferedReader( isr ); + StringBuilder result = new StringBuilder(); + while( true ) + { + synchronized( m_lock ) + { + if( m_cancelled ) + { + break; + } + } + + String line = reader.readLine(); + if( line == null ) + { + break; + } + result.append( line ); + result.append( '\n' ); + } + reader.close(); + + synchronized( m_lock ) + { + if( m_cancelled ) + { + // We cancelled + m_complete = true; + m_success = false; + m_result = null; + } + else + { + // We completed + m_complete = true; + m_success = true; + m_result = result.toString(); + m_responseCode = connection.getResponseCode(); + } + } + + connection.disconnect(); // disconnect + + } + catch( IOException e ) + { + synchronized( m_lock ) + { + // There was an error + m_complete = true; + m_success = false; + m_result = null; + } + } + } + } ); + + thread.start(); + } + + public String getURL() { + return m_urlString; + } + + public void cancel() + { + synchronized(m_lock) { + m_cancelled = true; + } + } + + public boolean isComplete() + { + synchronized(m_lock) { + return m_complete; + } + } + + public int getResponseCode() { + synchronized(m_lock) { + return m_responseCode; + } + } + + public boolean wasSuccessful() + { + synchronized(m_lock) { + return m_success; + } + } + + public BufferedReader getContents() + { + String result = null; + synchronized(m_lock) { + result = m_result; + } + + if( result != null ) { + return new BufferedReader( new StringReader( result ) ); + } + return null; + } + + private Object m_lock = new Object(); + private URL m_url; + private final String m_urlString; + + private boolean m_complete; + private boolean m_cancelled; + private boolean m_success; + private String m_result; + private int m_responseCode; +} diff --git a/src/main/java/dan200/computercraft/core/apis/IAPIEnvironment.java b/src/main/java/dan200/computercraft/core/apis/IAPIEnvironment.java new file mode 100644 index 0000000000..9a14ece99e --- /dev/null +++ b/src/main/java/dan200/computercraft/core/apis/IAPIEnvironment.java @@ -0,0 +1,45 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.apis; + +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.core.computer.Computer; +import dan200.computercraft.core.computer.IComputerEnvironment; +import dan200.computercraft.core.filesystem.FileSystem; +import dan200.computercraft.core.terminal.Terminal; + +public interface IAPIEnvironment +{ + public static interface IPeripheralChangeListener + { + public void onPeripheralChanged( int side, IPeripheral newPeripheral ); + } + + public Computer getComputer(); + public int getComputerID(); + public IComputerEnvironment getComputerEnvironment(); + public Terminal getTerminal(); + public FileSystem getFileSystem(); + + public void shutdown(); + public void reboot(); + public void queueEvent( String event, Object[] args ); + + public void setOutput( int side, int output ); + public int getOutput( int side ); + public int getInput( int side ); + + public void setBundledOutput( int side, int output ); + public int getBundledOutput( int side ); + public int getBundledInput( int side ); + + public void setPeripheralChangeListener( IPeripheralChangeListener listener ); + public IPeripheral getPeripheral( int side ); + + public String getLabel(); + public void setLabel( String label ); +} diff --git a/src/main/java/dan200/computercraft/core/apis/ILuaAPI.java b/src/main/java/dan200/computercraft/core/apis/ILuaAPI.java new file mode 100644 index 0000000000..14baa685bc --- /dev/null +++ b/src/main/java/dan200/computercraft/core/apis/ILuaAPI.java @@ -0,0 +1,17 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.apis; +import dan200.computercraft.api.lua.ILuaObject; + +public interface ILuaAPI extends ILuaObject +{ + public String[] getNames(); + + public void startup(); // LT + public void advance( double _dt ); // MT + public void shutdown(); // LT +} diff --git a/src/main/java/dan200/computercraft/core/apis/OSAPI.java b/src/main/java/dan200/computercraft/core/apis/OSAPI.java new file mode 100644 index 0000000000..d415d0a820 --- /dev/null +++ b/src/main/java/dan200/computercraft/core/apis/OSAPI.java @@ -0,0 +1,370 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.apis; + +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.LuaException; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public class OSAPI implements ILuaAPI +{ + private IAPIEnvironment m_apiEnvironment; + + private final Map m_timers; + private final Map m_alarms; + private int m_clock; + private double m_time; + private int m_day; + + private int m_nextTimerToken; + private int m_nextAlarmToken; + + private static class Timer + { + public int m_ticksLeft; + + public Timer( int ticksLeft ) + { + m_ticksLeft = ticksLeft; + } + } + + private class Alarm implements Comparable + { + public final double m_time; + public final int m_day; + + public Alarm( double time, int day ) + { + m_time = time; + m_day = day; + } + + @Override + public int compareTo( Alarm o ) + { + double t = (double)m_day * 24.0 + m_time; + double ot = (double)m_day * 24.0 + m_time; + if( t < ot ) { + return -1; + } else if( t > ot ) { + return 1; + } else { + return 0; + } + } + } + + public OSAPI( IAPIEnvironment environment ) + { + m_apiEnvironment = environment; + m_nextTimerToken = 0; + m_nextAlarmToken = 0; + m_timers = new HashMap(); + m_alarms = new HashMap(); + } + + // ILuaAPI implementation + + @Override + public String[] getNames() + { + return new String[] { + "os" + }; + } + + @Override + public void startup() + { + m_time = m_apiEnvironment.getComputerEnvironment().getTimeOfDay(); + m_day = m_apiEnvironment.getComputerEnvironment().getDay(); + m_clock = 0; + + synchronized( m_timers ) + { + m_timers.clear(); + } + + synchronized( m_alarms ) + { + m_alarms.clear(); + } + } + + @Override + public void advance( double dt ) + { + synchronized( m_timers ) + { + // Update the clock + m_clock++; + + // Countdown all of our active timers + Iterator> it = m_timers.entrySet().iterator(); + while( it.hasNext() ) + { + Map.Entry entry = it.next(); + Timer timer = entry.getValue(); + timer.m_ticksLeft = timer.m_ticksLeft - 1; + if( timer.m_ticksLeft <= 0 ) + { + // Queue the "timer" event + queueLuaEvent( "timer", new Object[] { entry.getKey() } ); + it.remove(); + } + } + } + + // Wait for all of our alarms + synchronized( m_alarms ) + { + double previousTime = m_time; + int previousDay = m_day; + double time = m_apiEnvironment.getComputerEnvironment().getTimeOfDay(); + int day = m_apiEnvironment.getComputerEnvironment().getDay(); + + if( time > previousTime || day > previousDay ) + { + double now = (double)m_day * 24.0 + m_time; + Iterator> it = m_alarms.entrySet().iterator(); + while( it.hasNext() ) + { + Map.Entry entry = it.next(); + Alarm alarm = entry.getValue(); + double t = (double)alarm.m_day * 24.0 + alarm.m_time; + if( now >= t ) + { + queueLuaEvent( "alarm", new Object[]{ entry.getKey() } ); + it.remove(); + } + } + } + + m_time = time; + m_day = day; + } + } + + @Override + public void shutdown( ) + { + synchronized( m_timers ) + { + m_timers.clear(); + } + + synchronized( m_alarms ) + { + m_alarms.clear(); + } + } + + @Override + public String[] getMethodNames() + { + return new String[] { + "queueEvent", + "startTimer", + "setAlarm", + "shutdown", + "reboot", + "computerID", + "getComputerID", + "setComputerLabel", + "computerLabel", + "getComputerLabel", + "clock", + "time", + "day", + "cancelTimer", + "cancelAlarm", + }; + } + + @Override + public Object[] callMethod( ILuaContext context, int method, Object[] args ) throws LuaException + { + switch( method ) + { + case 0: + { + // queueEvent + if( args.length == 0 || args[0] == null || !(args[0] instanceof String) ) + { + throw new LuaException( "Expected string" ); + } + queueLuaEvent( (String)args[0], trimArray( args, 1 ) ); + return null; + } + case 1: + { + // startTimer + if( args.length < 1 || args[0] == null || !(args[0] instanceof Number) ) + { + throw new LuaException( "Expected number" ); + } + double timer = ((Number)args[0]).doubleValue(); + synchronized( m_timers ) + { + m_timers.put( m_nextTimerToken, new Timer( (int)Math.round( timer / 0.05 ) ) ); + return new Object[] { m_nextTimerToken++ }; + } + } + case 2: + { + // setAlarm + if( args.length < 1 || args[0] == null || !(args[0] instanceof Number) ) + { + throw new LuaException( "Expected number" ); + } + double time = ((Number)args[0]).doubleValue(); + if( time < 0.0 || time >= 24.0 ) + { + throw new LuaException( "Number out of range" ); + } + synchronized( m_alarms ) + { + int day = (time > m_time) ? m_day : (m_day + 1); + m_alarms.put( m_nextAlarmToken, new Alarm( time, day ) ); + return new Object[] { m_nextAlarmToken++ }; + } + } + case 3: + { + // shutdown + m_apiEnvironment.shutdown(); + return null; + } + case 4: + { + // reboot + m_apiEnvironment.reboot(); + return null; + } + case 5: + case 6: + { + // computerID/getComputerID + return new Object[] { getComputerID() }; + } + case 7: + { + // setComputerLabel + String label = null; + if( args.length > 0 && args[0] != null ) + { + if(!(args[0] instanceof String)) + { + throw new LuaException( "Expected string or nil" ); + } + label = (String)args[0]; + if( label.length() > 32 ) + { + label = label.substring( 0, 32 ); + } + } + m_apiEnvironment.setLabel( label ); + return null; + } + case 8: + case 9: + { + // computerLabel/getComputerLabel + String label = m_apiEnvironment.getLabel(); + if( label != null ) + { + return new Object[] { label }; + } + return null; + } + case 10: + { + // clock + synchronized( m_timers ) + { + return new Object[] { (double)m_clock * 0.05 }; + } + } + case 11: + { + // m_time + synchronized( m_alarms ) + { + return new Object[] { m_time }; + } + } + case 12: + { + // day + synchronized( m_alarms ) + { + return new Object[] { m_day }; + } + } + case 13: + { + // cancelTimer + if( args.length < 1 || args[0] == null || !(args[0] instanceof Number) ) + { + throw new LuaException( "Expected number" ); + } + int token = ((Number)args[0]).intValue(); + synchronized( m_timers ) + { + if( m_timers.containsKey( token ) ) + { + m_timers.remove( token ); + } + } + return null; + } + case 14: + { + // cancelAlarm + if( args.length < 1 || args[0] == null || !(args[0] instanceof Number) ) + { + throw new LuaException( "Expected number" ); + } + int token = ((Number)args[0]).intValue(); + synchronized( m_alarms ) + { + if( m_alarms.containsKey( token ) ) + { + m_alarms.remove( token ); + } + } + return null; + } + default: + { + return null; + } + } + } + + // Private methods + + private void queueLuaEvent( String event, Object[] args ) + { + m_apiEnvironment.queueEvent( event, args ); + } + + private Object[] trimArray( Object[] array, int skip ) + { + return Arrays.copyOfRange( array, skip, array.length ); + } + + private int getComputerID() + { + return m_apiEnvironment.getComputerID(); + } +} diff --git a/src/main/java/dan200/computercraft/core/apis/PeripheralAPI.java b/src/main/java/dan200/computercraft/core/apis/PeripheralAPI.java new file mode 100644 index 0000000000..dbe2f1daed --- /dev/null +++ b/src/main/java/dan200/computercraft/core/apis/PeripheralAPI.java @@ -0,0 +1,534 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.apis; + +import dan200.computercraft.api.filesystem.IMount; +import dan200.computercraft.api.filesystem.IWritableMount; +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.core.computer.Computer; +import dan200.computercraft.core.computer.ComputerThread; +import dan200.computercraft.core.computer.ITask; +import dan200.computercraft.core.filesystem.FileSystem; +import dan200.computercraft.core.filesystem.FileSystemException; + +import java.util.*; + +public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChangeListener +{ + private class PeripheralWrapper implements IComputerAccess + { + private final String m_side; + private final IPeripheral m_peripheral; + + private String m_type; + private String[] m_methods; + private Map m_methodMap; + private boolean m_attached; + + private Set m_mounts; + + public PeripheralWrapper( IPeripheral peripheral, String side ) + { + m_side = side; + m_peripheral = peripheral; + m_attached = false; + + m_type = peripheral.getType(); + m_methods = peripheral.getMethodNames(); + assert( m_type != null ); + assert( m_methods != null ); + + m_methodMap = new HashMap(); + for(int i=0; i(); + } + + public IPeripheral getPeripheral() + { + return m_peripheral; + } + + public String getType() + { + return m_type; + } + + public String[] getMethods() + { + return m_methods; + } + + public synchronized boolean isAttached() + { + return m_attached; + } + + public synchronized void attach() + { + m_attached = true; + m_peripheral.attach( this ); + } + + public synchronized void detach() + { + // Call detach + m_peripheral.detach( this ); + m_attached = false; + + // Unmount everything the detach function forgot to do + Iterator it = m_mounts.iterator(); + while( it.hasNext() ) { + m_fileSystem.unmount( it.next() ); + } + m_mounts.clear(); + } + + public Object[] call( ILuaContext context, String methodName, Object[] arguments ) throws LuaException, InterruptedException + { + int method = -1; + synchronized( this ) + { + if( m_methodMap.containsKey( methodName ) ) + { + method = m_methodMap.get( methodName ); + } + } + if( method >= 0 ) + { + return m_peripheral.callMethod( this, context, method, arguments ); + } + else + { + throw new LuaException( "No such method " + methodName ); + } + } + + // IComputerAccess implementation + + @Override + public String mount( String desiredLoc, IMount mount ) + { + return mount( desiredLoc, mount, m_side ); + } + + @Override + public synchronized String mount( String desiredLoc, IMount mount, String driveName ) + { + if( !m_attached ) + { + throw new RuntimeException( "You are not attached to this Computer" ); + } + + // Mount the location + String location = null; + synchronized( m_fileSystem ) + { + location = findFreeLocation( desiredLoc ); + if( location != null ) + { + try { + m_fileSystem.mount( driveName, location, mount ); + } catch( FileSystemException e ) { + // fail and return null + } + } + } + if( location != null ) + { + m_mounts.add( location ); + } + return location; + } + + @Override + public String mountWritable( String desiredLoc, IWritableMount mount ) + { + return mountWritable( desiredLoc, mount, m_side ); + } + + @Override + public synchronized String mountWritable( String desiredLoc, IWritableMount mount, String driveName ) + { + if( !m_attached ) + { + throw new RuntimeException( "You are not attached to this Computer" ); + } + + // Mount the location + String location = null; + synchronized( m_fileSystem ) + { + location = findFreeLocation( desiredLoc ); + if( location != null ) + { + try { + m_fileSystem.mountWritable( driveName, location, mount ); + } catch( FileSystemException e ) { + // fail and return null + } + } + } + if( location != null ) + { + m_mounts.add( location ); + } + return location; + } + + @Override + public synchronized void unmount( String location ) + { + if( !m_attached ) { + throw new RuntimeException( "You are not attached to this Computer" ); + } + + if( location != null ) + { + if( !m_mounts.contains( location ) ) { + throw new RuntimeException( "You didn't mount this location" ); + } + + m_fileSystem.unmount( location ); + m_mounts.remove( location ); + } + } + + @Override + public synchronized int getID() + { + if( !m_attached ) { + throw new RuntimeException( "You are not attached to this Computer" ); + } + return m_environment.getComputerID(); + } + + @Override + public synchronized void queueEvent( final String event, final Object[] arguments ) + { + if( !m_attached ) { + throw new RuntimeException( "You are not attached to this Computer" ); + } + m_environment.queueEvent( event, arguments ); + } + + @Override + public synchronized String getAttachmentName() + { + if( !m_attached ) { + throw new RuntimeException( "You are not attached to this Computer" ); + } + return m_side; + } + } + + private IAPIEnvironment m_environment; + private FileSystem m_fileSystem; + private PeripheralWrapper[] m_peripherals; + private boolean m_running; + + public PeripheralAPI( IAPIEnvironment _environment ) + { + m_environment = _environment; + m_environment.setPeripheralChangeListener( this ); + + m_peripherals = new PeripheralWrapper[6]; + for(int i=0; i<6; ++i) + { + m_peripherals[i] = null; + } + + m_running = false; + } + + // IPeripheralChangeListener + + @Override + public void onPeripheralChanged( int side, IPeripheral newPeripheral ) + { + synchronized( m_peripherals ) + { + if( m_peripherals[side] != null ) + { + // Queue a detachment + final PeripheralWrapper wrapper = m_peripherals[side]; + ComputerThread.queueTask(new ITask() { + @Override + public Computer getOwner() { + return m_environment.getComputer(); + } + + @Override + public void execute() { + synchronized (m_peripherals) { + if (wrapper.isAttached()) { + wrapper.detach(); + } + } + } + }, null); + + // Queue a detachment event + m_environment.queueEvent( "peripheral_detach", new Object[] { Computer.s_sideNames[side] } ); + } + + // Assign the new peripheral + if( newPeripheral != null ) + { + m_peripherals[side] = new PeripheralWrapper( newPeripheral, Computer.s_sideNames[side] ); + } + else + { + m_peripherals[side] = null; + } + + if( m_peripherals[side] != null ) + { + // Queue an attachment + final PeripheralWrapper wrapper = m_peripherals[side]; + ComputerThread.queueTask( new ITask() { + @Override + public Computer getOwner() { + return m_environment.getComputer(); + } + + @Override + public void execute() { + synchronized( m_peripherals ) + { + if( m_running && !wrapper.isAttached() ) + { + wrapper.attach(); + } + } + } + }, null ); + + // Queue an attachment event + m_environment.queueEvent( "peripheral", new Object[] { Computer.s_sideNames[side] } ); + } + } + } + + // ILuaAPI implementation + + @Override + public String[] getNames() + { + return new String[] { + "peripheral" + }; + } + + @Override + public void startup( ) + { + synchronized( m_peripherals ) + { + m_fileSystem = m_environment.getFileSystem(); + m_running = true; + for( int i=0; i<6; ++i ) + { + PeripheralWrapper wrapper = m_peripherals[i]; + if( wrapper != null && !wrapper.isAttached() ) + { + wrapper.attach(); + } + } + } + } + + @Override + public void advance( double _dt ) + { + } + + @Override + public void shutdown( ) + { + synchronized( m_peripherals ) + { + m_running = false; + for( int i=0; i<6; ++i ) + { + PeripheralWrapper wrapper = m_peripherals[i]; + if( wrapper != null && wrapper.isAttached() ) + { + wrapper.detach(); + } + } + m_fileSystem = null; + } + } + + @Override + public String[] getMethodNames() + { + return new String[] { + "isPresent", + "getType", + "getMethods", + "call" + }; + } + + @Override + public Object[] callMethod( ILuaContext context, int method, Object[] args ) throws LuaException, InterruptedException + { + switch( method ) + { + case 0: + { + // isPresent + boolean present = false; + int side = parseSide( args ); + if( side >= 0 ) + { + synchronized( m_peripherals ) + { + PeripheralWrapper p = m_peripherals[ side ]; + if( p != null ) + { + present = true; + } + } + } + return new Object[] { present }; + } + case 1: + { + // getType + String type = null; + int side = parseSide( args ); + if( side >= 0 ) + { + synchronized( m_peripherals ) + { + PeripheralWrapper p = m_peripherals[ side ]; + if( p != null ) + { + type = p.getType(); + } + } + if( type != null ) + { + return new Object[] { type }; + } + } + return null; + } + case 2: + { + // getMethods + String[] methods = null; + int side = parseSide( args ); + if( side >= 0 ) + { + synchronized( m_peripherals ) + { + PeripheralWrapper p = m_peripherals[ side ]; + if( p != null ) + { + methods = p.getMethods(); + } + } + } + if( methods != null ) + { + Map table = new HashMap(); + for(int i=0; i= 0 ) + { + PeripheralWrapper p = null; + synchronized( m_peripherals ) + { + p = m_peripherals[ side ]; + } + if( p != null ) + { + Object[] results = p.call( context, methodName, methodArgs ); + return results; + } + } + throw new LuaException( "No peripheral attached" ); + } + default: + { + return null; + } + } + } + + // Privates + + private Object[] trimArray( Object[] array, int skip ) + { + return Arrays.copyOfRange( array, skip, array.length ); + } + + private int parseSide( Object[] args ) throws LuaException + { + if( args.length < 1 || args[0] == null || !(args[0] instanceof String) ) + { + throw new LuaException( "Expected string" ); + } + String side = (String)args[0]; + for( int n=0; n table = new HashMap(); + for(int i=0; i< Computer.s_sideNames.length; ++i ) + { + table.put( i+1, Computer.s_sideNames[i] ); + } + return new Object[] { table }; + } + case 1: + { + // setOutput + if( args.length < 2 || args[0] == null || !(args[0] instanceof String) || args[1] == null || !(args[1] instanceof Boolean) ) + { + throw new LuaException( "Expected string, boolean" ); + } + int side = parseSide( args ); + boolean output = ((Boolean)args[1]).booleanValue(); + m_environment.setOutput( side, output ? 15 : 0 ); + return null; + } + case 2: + { + // getOutput + int side = parseSide( args ); + return new Object[] { m_environment.getOutput( side ) > 0 }; + } + case 3: + { + // getInput + int side = parseSide( args ); + return new Object[] { m_environment.getInput( side ) > 0 }; + } + case 4: + { + // setBundledOutput + if( args.length < 2 || args[0] == null || !(args[0] instanceof String) || args[1] == null || !(args[1] instanceof Double) ) + { + throw new LuaException( "Expected string, number" ); + } + int side = parseSide( args ); + int output = ((Double)args[1]).intValue(); + m_environment.setBundledOutput( side, output ); + return null; + } + case 5: + { + // getBundledOutput + int side = parseSide( args ); + return new Object[] { m_environment.getBundledOutput( side ) }; + } + case 6: + { + // getBundledInput + int side = parseSide( args ); + return new Object[] { m_environment.getBundledInput( side ) }; + } + case 7: + { + // testBundledInput + if( args.length < 2 || args[0] == null || !(args[0] instanceof String) || args[1] == null || !(args[1] instanceof Double) ) + { + throw new LuaException( "Expected string, number" ); + } + int side = parseSide( args ); + int mask = ((Double)args[1]).intValue(); + int input = m_environment.getBundledInput( side ); + return new Object[] { ((input & mask) == mask) }; + } + case 8: + case 9: + { + // setAnalogOutput/setAnalogueOutput + if( args.length < 2 || args[0] == null || !(args[0] instanceof String) || args[1] == null || !(args[1] instanceof Double) ) + { + throw new LuaException( "Expected string, number" ); + } + int side = parseSide( args ); + int output = ((Double)args[1]).intValue(); + if( output < 0 || output > 15 ) + { + throw new LuaException( "Expected number in range 0-15" ); + } + m_environment.setOutput( side, output ); + return null; + } + case 10: + case 11: + { + // getAnalogOutput/getAnalogueOutput + int side = parseSide( args ); + return new Object[] { m_environment.getOutput( side ) }; + } + case 12: + case 13: + { + // getAnalogInput/getAnalogueInput + int side = parseSide( args ); + return new Object[] { m_environment.getInput( side ) }; + } + default: + { + return null; + } + } + } + + private int parseSide( Object[] args ) throws LuaException + { + if( args.length < 1 || args[0] == null || !(args[0] instanceof String) ) + { + throw new LuaException( "Expected string" ); + } + String side = (String)args[0]; + for( int n=0; n 15 ) + { + throw new LuaException( "Colour out of range" ); + } + if( !_enableColours && (colour != 0 && colour != 15 && colour != 7 && colour != 8) ) + { + throw new LuaException( "Colour not supported" ); + } + return colour; + } + + public static Object[] encodeColour( int colour ) throws LuaException + { + return new Object[] { + 1 << colour + }; + } + + @Override + public Object[] callMethod( ILuaContext context, int method, Object[] args ) throws LuaException + { + switch( method ) + { + case 0: + { + // write + String text; + if( args.length > 0 && args[0] != null ) { + text = args[0].toString(); + } else { + text = ""; + } + + synchronized( m_terminal ) + { + m_terminal.write( text ); + m_terminal.setCursorPos( m_terminal.getCursorX() + text.length(), m_terminal.getCursorY() ); + } + return null; + } + case 1: + { + // scroll + if( args.length != 1 || args[0] == null || !(args[0] instanceof Double) ) + { + throw new LuaException( "Expected number" ); + } + + int y = (int)((Double)args[0]).doubleValue(); + synchronized( m_terminal ) + { + m_terminal.scroll(y); + } + return null; + } + case 2: + { + // setCursorPos + if( args.length != 2 || args[0] == null || !(args[0] instanceof Double) || args[1] == null || !(args[1] instanceof Double) ) + { + throw new LuaException( "Expected number, number" ); + } + int x = (int)((Double)args[0]).doubleValue() - 1; + int y = (int)((Double)args[1]).doubleValue() - 1; + synchronized( m_terminal ) + { + m_terminal.setCursorPos( x, y ); + } + return null; + } + case 3: + { + // setCursorBlink + if( args.length != 1 || args[0] == null || !(args[0] instanceof Boolean) ) + { + throw new LuaException( "Expected boolean" ); + } + boolean b = ((Boolean)args[0]).booleanValue(); + synchronized( m_terminal ) + { + m_terminal.setCursorBlink( b ); + } + return null; + } + case 4: + { + // getCursorPos + int x, y; + synchronized( m_terminal ) + { + x = m_terminal.getCursorX(); + y = m_terminal.getCursorY(); + } + return new Object[] { x + 1, y + 1 }; + } + case 5: + { + // getSize + int width, height; + synchronized( m_terminal ) + { + width = m_terminal.getWidth(); + height = m_terminal.getHeight(); + } + return new Object[] { width, height }; + } + case 6: + { + // clear + synchronized( m_terminal ) + { + m_terminal.clear(); + } + return null; + } + case 7: + { + // clearLine + synchronized( m_terminal ) + { + m_terminal.clearLine(); + } + return null; + } + case 8: + case 9: + { + // setTextColour/setTextColor + int colour = parseColour( args, m_environment.isColour() ); + synchronized( m_terminal ) + { + m_terminal.setTextColour( colour ); + } + return null; + } + case 10: + case 11: + { + // setBackgroundColour/setBackgroundColor + int colour = parseColour( args, m_environment.isColour() ); + synchronized( m_terminal ) + { + m_terminal.setBackgroundColour( colour ); + } + return null; + } + case 12: + case 13: + { + // isColour/isColor + return new Object[] { m_environment.isColour() }; + } + case 14: + case 15: + { + // getTextColour/getTextColor + return encodeColour( m_terminal.getTextColour() ); + } + case 16: + case 17: + { + // getBackgroundColour/getBackgroundColor + return encodeColour( m_terminal.getBackgroundColour() ); + } + case 18: + { + // blit + if( args.length < 3 || !(args[0] instanceof String) || !(args[1] instanceof String) || !(args[2] instanceof String) ) + { + throw new LuaException( "Expected string, string, string" ); + } + + String text = (String)args[0]; + String textColour = (String)args[1]; + String backgroundColour = (String)args[2]; + if( textColour.length() != text.length() || backgroundColour.length() != text.length() ) + { + throw new LuaException( "Arguments must be the same length" ); + } + + synchronized( m_terminal ) + { + m_terminal.blit( text, textColour, backgroundColour ); + m_terminal.setCursorPos( m_terminal.getCursorX() + text.length(), m_terminal.getCursorY() ); + } + return null; + } + default: + { + return null; + } + } + } + + private static int getHighestBit( int group ) + { + int bit = 0; + while( group > 0 ) + { + group >>= 1; + bit++; + } + return bit; + } +} diff --git a/src/main/java/dan200/computercraft/core/computer/Computer.java b/src/main/java/dan200/computercraft/core/computer/Computer.java new file mode 100644 index 0000000000..5d47982bd1 --- /dev/null +++ b/src/main/java/dan200/computercraft/core/computer/Computer.java @@ -0,0 +1,894 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.computer; + +import com.google.common.base.Objects; +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.filesystem.IMount; +import dan200.computercraft.api.filesystem.IWritableMount; +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.core.apis.*; +import dan200.computercraft.core.filesystem.FileSystem; +import dan200.computercraft.core.filesystem.FileSystemException; +import dan200.computercraft.core.lua.ILuaMachine; +import dan200.computercraft.core.lua.LuaJLuaMachine; +import dan200.computercraft.core.terminal.Terminal; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class Computer +{ + public static final String[] s_sideNames = new String[] { + "bottom", "top", "back", "front", "right", "left", + }; + + private static enum State + { + Off, + Starting, + Running, + Stopping, + } + + private static class APIEnvironment implements IAPIEnvironment + { + private Computer m_computer; + private IAPIEnvironment.IPeripheralChangeListener m_peripheralListener; + + public APIEnvironment( Computer computer ) + { + m_computer = computer; + m_peripheralListener = null; + } + + @Override + public Computer getComputer() + { + return m_computer; + } + + @Override + public int getComputerID() + { + return m_computer.assignID(); + } + + @Override + public IComputerEnvironment getComputerEnvironment() + { + return m_computer.m_environment; + } + + @Override + public Terminal getTerminal() + { + return m_computer.m_terminal; + } + + @Override + public FileSystem getFileSystem() + { + return m_computer.m_fileSystem; + } + + @Override + public void shutdown() + { + m_computer.shutdown(); + } + + @Override + public void reboot() + { + m_computer.reboot(); + } + + @Override + public void queueEvent( String event, Object[] args ) + { + m_computer.queueEvent( event, args ); + } + + @Override + public void setOutput( int side, int output ) + { + m_computer.setRedstoneOutput( side, output ); + } + + @Override + public int getOutput( int side ) + { + return m_computer.getInternalRedstoneOutput( side ); + } + + @Override + public int getInput( int side ) + { + return m_computer.getRedstoneInput( side ); + } + + @Override + public void setBundledOutput( int side, int output ) + { + m_computer.setBundledRedstoneOutput( side, output ); + } + + @Override + public int getBundledOutput( int side ) + { + return m_computer.getInternalBundledRedstoneOutput( side ); + } + + @Override + public int getBundledInput( int side ) + { + return m_computer.getBundledRedstoneInput( side ); + } + + @Override + public IPeripheral getPeripheral( int side ) + { + synchronized( m_computer.m_peripherals ) + { + return m_computer.m_peripherals[ side ]; + } + } + + @Override + public void setPeripheralChangeListener( IPeripheralChangeListener listener ) + { + synchronized( m_computer.m_peripherals ) + { + m_peripheralListener = listener; + } + } + + @Override + public String getLabel() + { + return m_computer.getLabel(); + } + + @Override + public void setLabel( String label ) + { + m_computer.setLabel( label ); + } + + public void onPeripheralChanged( int side, IPeripheral peripheral ) + { + synchronized( m_computer.m_peripherals ) + { + if( m_peripheralListener != null ) + { + m_peripheralListener.onPeripheralChanged( side, peripheral ); + } + } + } + } + + private static IMount s_romMount = null; + + private int m_id; + private String m_label; + private final IComputerEnvironment m_environment; + + private int m_ticksSinceStart; + private boolean m_startRequested; + private State m_state; + private boolean m_blinking; + + private ILuaMachine m_machine; + private List m_apis; + private APIEnvironment m_apiEnvironment; + + private Terminal m_terminal; + private FileSystem m_fileSystem; + private IWritableMount m_rootMount; + + private int[] m_internalOutput; + private int[] m_internalBundledOutput; + private boolean m_internalOutputChanged; + + private int[] m_externalOutput; + private int[] m_externalBundledOutput; + private boolean m_externalOutputChanged; + + private int[] m_input; + private int[] m_bundledInput; + private boolean m_inputChanged; + + private IPeripheral[] m_peripherals; + + public Computer( IComputerEnvironment environment, Terminal terminal, int id ) + { + ComputerThread.start(); + + m_id = id; + m_label = null; + m_environment = environment; + + m_ticksSinceStart = -1; + m_startRequested = false; + m_state = State.Off; + m_blinking = false; + + m_terminal = terminal; + m_fileSystem = null; + + m_machine = null; + m_apis = new ArrayList(); + m_apiEnvironment = new APIEnvironment( this ); + + m_internalOutput = new int[6]; + m_internalBundledOutput = new int[6]; + m_internalOutputChanged = true; + + m_externalOutput = new int[6]; + m_externalBundledOutput = new int[6]; + m_externalOutputChanged = true; + + m_input = new int[6]; + m_bundledInput = new int[6]; + m_inputChanged = false; + + m_peripherals = new IPeripheral[6]; + for( int i=0; i<6; ++i ) + { + m_peripherals[i] = null; + } + + m_rootMount = null; + createAPIs(); + } + + public IAPIEnvironment getAPIEnvironment() + { + return m_apiEnvironment; + } + + public void turnOn() + { + if( m_state == State.Off ) + { + m_startRequested = true; + } + } + + public void shutdown() + { + stopComputer( false ); + } + + public void reboot() + { + stopComputer( true ); + } + + public boolean isOn() + { + synchronized( this ) + { + return m_state == State.Running; + } + } + + public void abort( boolean hard ) + { + synchronized( this ) + { + if( m_state == State.Running ) + { + if( hard ) + { + m_machine.hardAbort( "Too long without yielding" ); + } + else + { + m_machine.softAbort( "Too long without yielding" ); + } + } + } + } + + public void unload() + { + synchronized( this ) + { + stopComputer( false ); + } + } + + public int getID() + { + return m_id; + } + + public int assignID() + { + if( m_id < 0 ) + { + m_id = m_environment.assignNewID(); + } + return m_id; + } + + public void setID( int id ) + { + m_id = id; + } + + public String getLabel() + { + return m_label; + } + + public void setLabel( String label ) + { + if( !Objects.equal( label, m_label ) ) + { + m_label = label; + m_externalOutputChanged = true; + } + } + + public void advance( double _dt ) + { + synchronized( this ) + { + // Start after a number of ticks + if( m_ticksSinceStart >= 0 ) + { + m_ticksSinceStart++; + } + if( m_startRequested && (m_ticksSinceStart < 0 || m_ticksSinceStart > 50) ) + { + startComputer(); + m_startRequested = false; + } + + if( m_state == State.Running ) + { + // Fire the redstone event if our redstone input has changed + synchronized( m_input ) + { + if( m_inputChanged ) + { + queueEvent( "redstone", null ); + m_inputChanged = false; + } + } + + // Advance our APIs + synchronized( m_apis ) + { + Iterator it = m_apis.iterator(); + while( it.hasNext() ) + { + ILuaAPI api = it.next(); + api.advance( _dt ); + } + } + } + } + + // Set outputchanged if the internal redstone has changed + synchronized( m_internalOutput ) + { + if( m_internalOutputChanged ) + { + boolean changed = false; + for( int i=0; i<6; ++i ) + { + if( m_externalOutput[i] != m_internalOutput[i] ) + { + m_externalOutput[ i ] = m_internalOutput[ i ]; + changed = true; + } + if( m_externalBundledOutput[i] != m_internalBundledOutput[i] ) + { + m_externalBundledOutput[ i ] = m_internalBundledOutput[ i ]; + changed = true; + } + } + m_internalOutputChanged = false; + if( changed ) + { + m_externalOutputChanged = true; + } + } + } + + // Set outputchanged if the terminal has changed from blinking to not + synchronized( m_terminal ) + { + boolean blinking = + m_terminal.getCursorBlink() && + m_terminal.getCursorX() >= 0 && m_terminal.getCursorX() < m_terminal.getWidth() && + m_terminal.getCursorY() >= 0 && m_terminal.getCursorY() < m_terminal.getHeight(); + + if( blinking != m_blinking ) + { + m_blinking = blinking; + m_externalOutputChanged = true; + } + } + } + + public boolean pollChanged() + { + return m_externalOutputChanged; + } + + public void clearChanged() + { + m_externalOutputChanged = false; + } + + public boolean isBlinking() + { + synchronized( m_terminal ) + { + return isOn() && m_blinking; + } + } + + public IWritableMount getRootMount() + { + if( m_rootMount == null ) + { + m_rootMount = m_environment.createSaveDirMount( "computer/" + assignID(), m_environment.getComputerSpaceLimit() ); + } + return m_rootMount; + } + + // FileSystem + + private boolean initFileSystem() + { + // Create the file system + int id = assignID(); + try + { + m_fileSystem = new FileSystem( "hdd", getRootMount() ); + if( s_romMount == null ) + { + s_romMount = m_environment.createResourceMount( "computercraft", "lua/rom" ); + } + if( s_romMount != null ) + { + m_fileSystem.mount( "rom", "rom", s_romMount ); + return true; + } + return false; + } + catch( FileSystemException e ) + { + e.printStackTrace(); + return false; + } + } + + // Redstone + + public int getRedstoneOutput( int side ) + { + synchronized( m_internalOutput ) + { + return isOn() ? m_externalOutput[side] : 0; + } + } + + private int getInternalRedstoneOutput( int side ) + { + synchronized( m_internalOutput ) + { + return isOn() ? m_internalOutput[side] : 0; + } + } + + private void setRedstoneOutput( int side, int level ) + { + synchronized( m_internalOutput ) + { + if( m_internalOutput[side] != level ) + { + m_internalOutput[side] = level; + m_internalOutputChanged = true; + } + } + } + + public void setRedstoneInput( int side, int level ) + { + synchronized( m_input ) + { + if( m_input[side] != level ) + { + m_input[side] = level; + m_inputChanged = true; + } + } + } + + private int getRedstoneInput( int side ) + { + synchronized( m_input ) + { + return m_input[side]; + } + } + + public int getBundledRedstoneOutput( int side ) + { + synchronized( m_internalOutput ) + { + return isOn() ? m_externalBundledOutput[side] : 0; + } + } + + private int getInternalBundledRedstoneOutput( int side ) + { + synchronized( m_internalOutput ) + { + return isOn() ? m_internalBundledOutput[side] : 0; + } + } + + private void setBundledRedstoneOutput( int side, int combination ) + { + synchronized( m_internalOutput ) + { + if( m_internalBundledOutput[side] != combination ) + { + m_internalBundledOutput[side] = combination; + m_internalOutputChanged = true; + } + } + } + + public void setBundledRedstoneInput( int side, int combination ) + { + synchronized( m_input ) + { + if( m_bundledInput[side] != combination ) + { + m_bundledInput[side] = combination; + m_inputChanged = true; + } + } + } + + private int getBundledRedstoneInput( int side ) + { + synchronized( m_input ) + { + return m_bundledInput[side]; + } + } + + // Peripherals + + public void addAPI( ILuaAPI api ) + { + m_apis.add( api ); + } + + public void setPeripheral( int side, IPeripheral peripheral ) + { + synchronized( m_peripherals ) + { + IPeripheral existing = m_peripherals[side]; + if( (existing == null && peripheral != null) || + (existing != null && peripheral == null) || + (existing != null && !existing.equals( peripheral )) ) + { + m_peripherals[side] = peripheral; + m_apiEnvironment.onPeripheralChanged( side, peripheral ); + } + } + } + + public IPeripheral getPeripheral( int side ) + { + synchronized( m_peripherals ) + { + return m_peripherals[side]; + } + } + + // Lua + + private void createAPIs() + { + m_apis.add( new TermAPI( m_apiEnvironment ) ); + m_apis.add( new RedstoneAPI( m_apiEnvironment ) ); + m_apis.add( new FSAPI( m_apiEnvironment ) ); + m_apis.add( new PeripheralAPI( m_apiEnvironment ) ); + m_apis.add( new OSAPI( m_apiEnvironment ) ); + m_apis.add( new BitAPI( m_apiEnvironment ) ); + //m_apis.add( new BufferAPI( m_apiEnvironment ) ); + if( ComputerCraft.http_enable ) + { + m_apis.add( new HTTPAPI( m_apiEnvironment ) ); + } + } + + private void initLua() + { + // Create the lua machine + ILuaMachine machine = new LuaJLuaMachine( this ); + + // Add the APIs + Iterator it = m_apis.iterator(); + while( it.hasNext() ) + { + ILuaAPI api = it.next(); + machine.addAPI( api ); + api.startup(); + } + + // Load the bios resource + InputStream biosStream; + try + { + biosStream = Computer.class.getResourceAsStream( "/assets/computercraft/lua/bios.lua" ); + } + catch( Exception e ) + { + biosStream = null; + } + + // Start the machine running the bios resource + if( biosStream != null ) + { + machine.loadBios( biosStream ); + try { + biosStream.close(); + } catch( IOException e ) { + // meh + } + + if( machine.isFinished() ) + { + m_terminal.reset(); + m_terminal.write("Error starting bios.lua" ); + m_terminal.setCursorPos( 0, 1 ); + m_terminal.write( "ComputerCraft may be installed incorrectly" ); + + machine.unload(); + m_machine = null; + } + else + { + m_machine = machine; + } + } + else + { + m_terminal.reset(); + m_terminal.write("Error loading bios.lua" ); + m_terminal.setCursorPos( 0, 1 ); + m_terminal.write( "ComputerCraft may be installed incorrectly" ); + + machine.unload(); + m_machine = null; + } + } + + private void startComputer() + { + synchronized( this ) + { + if( m_state != State.Off ) + { + return; + } + m_state = State.Starting; + m_ticksSinceStart = 0; + } + + // Turn the computercraft on + final Computer computer = this; + ComputerThread.queueTask( new ITask() { + @Override + public Computer getOwner() + { + return computer; + } + + @Override + public void execute() + { + synchronized( this ) + { + if( m_state != State.Starting ) + { + return; + } + + // Init terminal + synchronized( m_terminal ) + { + m_terminal.reset(); + } + + // Init filesystem + if( !initFileSystem() ) + { + // Init failed, so shutdown + m_terminal.reset(); + m_terminal.write( "Error mounting lua/rom" ); + m_terminal.setCursorPos( 0, 1 ); + m_terminal.write( "ComputerCraft may be installed incorrectly" ); + + m_state = State.Running; + stopComputer( false ); + return; + } + + // Init lua + initLua(); + if( m_machine == null ) + { + m_terminal.reset(); + m_terminal.write( "Error loading bios.lua" ); + m_terminal.setCursorPos( 0, 1 ); + m_terminal.write( "ComputerCraft may be installed incorrectly" ); + + // Init failed, so shutdown + m_state = State.Running; + stopComputer( false ); + return; + } + + // Start a new state + m_state = State.Running; + synchronized( m_machine ) + { + m_machine.handleEvent( null, null ); + } + } + } + }, computer ); + } + + private void stopComputer( final boolean reboot ) + { + synchronized( this ) + { + if( m_state != State.Running ) + { + return; + } + m_state = State.Stopping; + } + + // Turn the computercraft off + final Computer computer = this; + ComputerThread.queueTask( new ITask() { + @Override + public Computer getOwner() + { + return computer; + } + + @Override + public void execute() + { + synchronized( this ) + { + if( m_state != State.Stopping ) + { + return; + } + + // Shutdown our APIs + synchronized( m_apis ) + { + Iterator it = m_apis.iterator(); + while( it.hasNext() ) + { + ILuaAPI api = it.next(); + api.shutdown(); + } + } + + // Shutdown terminal and filesystem + if( m_fileSystem != null ) + { + m_fileSystem.unload(); + m_fileSystem = null; + } + + if( m_machine != null ) + { + synchronized( m_terminal ) + { + m_terminal.reset(); + } + + synchronized( m_machine ) + { + m_machine.unload(); + m_machine = null; + } + } + + // Reset redstone output + synchronized( m_internalOutput ) + { + for( int i=0; i<6; ++i ) + { + m_internalOutput[i] = 0; + m_internalBundledOutput[i] = 0; + } + m_internalOutputChanged = true; + } + + m_state = State.Off; + if( reboot ) + { + m_startRequested = true; + } + } + } + }, computer ); + } + + public void queueEvent( final String event, final Object[] arguments ) + { + synchronized( this ) + { + if( m_state != State.Running ) + { + return; + } + } + + final Computer computer = this; + ITask task = new ITask() { + @Override + public Computer getOwner() + { + return computer; + } + + @Override + public void execute() + { + synchronized( this ) + { + if( m_state != State.Running ) + { + return; + } + } + + synchronized( m_machine ) + { + m_machine.handleEvent( event, arguments ); + if( m_machine.isFinished() ) + { + m_terminal.reset(); + m_terminal.write( "Error resuming bios.lua" ); + m_terminal.setCursorPos( 0, 1 ); + m_terminal.write( "ComputerCraft may be installed incorrectly" ); + + stopComputer( false ); + } + } + } + }; + + ComputerThread.queueTask( task, computer ); + } +} diff --git a/src/main/java/dan200/computercraft/core/computer/ComputerThread.java b/src/main/java/dan200/computercraft/core/computer/ComputerThread.java new file mode 100644 index 0000000000..def6d3eec8 --- /dev/null +++ b/src/main/java/dan200/computercraft/core/computer/ComputerThread.java @@ -0,0 +1,230 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.computer; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.WeakHashMap; +import java.util.concurrent.LinkedBlockingQueue; + +public class ComputerThread +{ + private static Object m_lock; + + private static Thread m_thread; + private static WeakHashMap > m_computerTasks; + private static ArrayList > m_computerTasksActive; + private static ArrayList > m_computerTasksPending; + private static Object m_defaultQueue; + private static Object m_monitor; + + private static boolean m_running; + private static boolean m_stopped; + + static + { + m_lock = new Object(); + m_thread = null; + m_computerTasks = new WeakHashMap>(); + m_computerTasksPending = new ArrayList>(); + m_computerTasksActive = new ArrayList>(); + m_defaultQueue = new Object(); + m_monitor = new Object(); + m_running = false; + m_stopped = false; + } + + public static void start() + { + synchronized( m_lock ) + { + if( m_running ) + { + m_stopped = false; + return; + } + + m_thread = new Thread( new Runnable() { + public void run() + { + while( true ) + { + synchronized( m_computerTasksPending ) + { + if (!m_computerTasksPending.isEmpty()) + { + Iterator> it = m_computerTasksPending.iterator(); + while(it.hasNext()) + { + LinkedBlockingQueue queue = it.next(); + + if (!m_computerTasksActive.contains(queue)) + { + m_computerTasksActive.add(queue); + } + it.remove(); + } + /* + m_computerTasksActive.addAll(m_computerTasksPending); // put any that have been added since + m_computerTasksPending.clear(); + */ + } + } + + Iterator> it = m_computerTasksActive.iterator(); + + while (it.hasNext()) + { + LinkedBlockingQueue queue = it.next(); + + if (queue == null || queue.isEmpty()) // we don't need the blocking part of the queue. Null check to ensure it exists due to a weird NPE I got + { + continue; + } + + synchronized( m_lock ) + { + if( m_stopped ) + { + m_running = false; + m_thread = null; + return; + } + } + + try + { + final ITask task = queue.take(); + + // Create the task + Thread worker = new Thread( new Runnable() { + public void run() { + try { + task.execute(); + } catch( Throwable e ) { + System.out.println( "ComputerCraft: Error running task." ); + e.printStackTrace(); + } + } + } ); + + // Run the task + worker.start(); + worker.join( 7000 ); + + if( worker.isAlive() ) + { + // Task ran for too long + // Initiate escape plan + Computer computer = task.getOwner(); + if( computer != null ) + { + // Step 1: Soft abort + computer.abort( false ); + worker.join( 1500 ); + + if( worker.isAlive() ) + { + // Step 2: Hard abort + computer.abort( true ); + worker.join( 1500 ); + } + } + + // Step 3: abandon + if( worker.isAlive() ) + { + //System.out.println( "computercraft: Warning! Failed to abort Computer " + computercraft.getDescription() + ". Dangling lua thread could cause errors." ); + worker.interrupt(); + } + } + } + catch( InterruptedException e ) + { + continue; + } + + synchronized (queue) + { + if (queue.isEmpty()) + { + it.remove(); + } + } + } + + while (m_computerTasksActive.isEmpty() && m_computerTasksPending.isEmpty()) + { + synchronized (m_monitor) + { + try + { + m_monitor.wait(); + } + catch( InterruptedException e ) + { + } + } + } + } + } + }, "Computer Dispatch Thread" ); + + m_thread.start(); + m_running = true; + } + } + + public static void stop() + { + synchronized( m_lock ) + { + if( m_running ) + { + m_stopped = true; + m_thread.interrupt(); + } + } + } + + public static void queueTask( ITask _task, Computer computer ) + { + Object queueObject = computer; + + if (queueObject == null) + { + queueObject = m_defaultQueue; + } + + LinkedBlockingQueue queue = m_computerTasks.get(queueObject); + + if (queue == null) + { + m_computerTasks.put(queueObject, queue = new LinkedBlockingQueue(256)); + } + + synchronized ( m_computerTasksPending ) + { + if( queue.offer( _task ) ) + { + if( !m_computerTasksPending.contains( queue ) ) + { + m_computerTasksPending.add( queue ); + } + } + else + { + //System.out.println( "Event queue overflow" ); + } + } + + synchronized (m_monitor) + { + m_monitor.notify(); + } + } +} diff --git a/src/main/java/dan200/computercraft/core/computer/IComputerEnvironment.java b/src/main/java/dan200/computercraft/core/computer/IComputerEnvironment.java new file mode 100644 index 0000000000..f2edf326f2 --- /dev/null +++ b/src/main/java/dan200/computercraft/core/computer/IComputerEnvironment.java @@ -0,0 +1,22 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.computer; +import dan200.computercraft.api.filesystem.IMount; +import dan200.computercraft.api.filesystem.IWritableMount; + +public interface IComputerEnvironment +{ + public int getDay(); + public double getTimeOfDay(); + public boolean isColour(); + public long getComputerSpaceLimit(); + public String getHostString(); + + public int assignNewID(); + public IWritableMount createSaveDirMount( String subPath, long capacity ); + public IMount createResourceMount( String domain, String subPath ); +} diff --git a/src/main/java/dan200/computercraft/core/computer/ITask.java b/src/main/java/dan200/computercraft/core/computer/ITask.java new file mode 100644 index 0000000000..30b0d69ca2 --- /dev/null +++ b/src/main/java/dan200/computercraft/core/computer/ITask.java @@ -0,0 +1,13 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.computer; + +public interface ITask +{ + public Computer getOwner(); + public void execute(); +} diff --git a/src/main/java/dan200/computercraft/core/computer/MainThread.java b/src/main/java/dan200/computercraft/core/computer/MainThread.java new file mode 100644 index 0000000000..3ffca84978 --- /dev/null +++ b/src/main/java/dan200/computercraft/core/computer/MainThread.java @@ -0,0 +1,65 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.computer; + +import java.util.LinkedList; + +public class MainThread +{ + private static final int MAX_TASKS_PER_TICK = 1000; + private static final int MAX_TASKS_TOTAL = 50000; + + private static final LinkedList m_outstandingTasks = new LinkedList(); + private static final Object m_nextUnusedTaskIDLock = new Object(); + private static long m_nextUnusedTaskID = 0; + + public static long getUniqueTaskID() + { + synchronized( m_nextUnusedTaskIDLock ) + { + return ++m_nextUnusedTaskID; + } + } + + public static boolean queueTask( ITask task ) + { + synchronized( m_outstandingTasks ) + { + if( m_outstandingTasks.size() < MAX_TASKS_TOTAL ) + { + m_outstandingTasks.addLast( task ); + return true; + } + } + return false; + } + + public static void executePendingTasks() + { + int tasksThisTick = 0; + while( tasksThisTick < MAX_TASKS_PER_TICK ) + { + ITask task = null; + synchronized( m_outstandingTasks ) + { + if( m_outstandingTasks.size() > 0 ) + { + task = m_outstandingTasks.removeFirst(); + } + } + if( task != null ) + { + task.execute(); + ++tasksThisTick; + } + else + { + break; + } + } + } +} diff --git a/src/main/java/dan200/computercraft/core/filesystem/ComboMount.java b/src/main/java/dan200/computercraft/core/filesystem/ComboMount.java new file mode 100644 index 0000000000..8474d1ca76 --- /dev/null +++ b/src/main/java/dan200/computercraft/core/filesystem/ComboMount.java @@ -0,0 +1,128 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.filesystem; + +import dan200.computercraft.api.filesystem.IMount; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class ComboMount implements IMount +{ + private IMount[] m_parts; + + public ComboMount( IMount[] parts ) + { + m_parts = parts; + } + + // IMount implementation + + @Override + public boolean exists( String path ) throws IOException + { + for( int i=m_parts.length-1; i>=0; --i ) + { + IMount part = m_parts[i]; + if( part.exists( path ) ) + { + return true; + } + } + return false; + } + + @Override + public boolean isDirectory( String path ) throws IOException + { + for( int i=m_parts.length-1; i>=0; --i ) + { + IMount part = m_parts[i]; + if( part.isDirectory( path ) ) + { + return true; + } + } + return false; + } + + @Override + public void list( String path, List contents ) throws IOException + { + // Combine the lists from all the mounts + List foundFiles = null; + int foundDirs = 0; + for( int i=m_parts.length-1; i>=0; --i ) + { + IMount part = m_parts[i]; + if( part.exists( path ) && part.isDirectory( path ) ) + { + if( foundFiles == null ) + { + foundFiles = new ArrayList(); + } + part.list( path, foundFiles ); + foundDirs++; + } + } + + if( foundDirs == 1 ) + { + // We found one directory, so we know it already doesn't contain duplicates + contents.addAll( foundFiles ); + } + else if( foundDirs > 1 ) + { + // We found multiple directories, so filter for duplicates + Set seen = new HashSet(); + for( int i=0; i=0; --i ) + { + IMount part = m_parts[i]; + if( part.exists( path ) ) + { + return part.getSize( path ); + } + } + throw new IOException( "No such file" ); + } + + @Override + public InputStream openForRead( String path ) throws IOException + { + for( int i=m_parts.length-1; i>=0; --i ) + { + IMount part = m_parts[i]; + if( part.exists( path ) && !part.isDirectory( path ) ) + { + return part.openForRead( path ); + } + } + throw new IOException( "No such file" ); + } +} diff --git a/src/main/java/dan200/computercraft/core/filesystem/EmptyMount.java b/src/main/java/dan200/computercraft/core/filesystem/EmptyMount.java new file mode 100644 index 0000000000..85190b95d1 --- /dev/null +++ b/src/main/java/dan200/computercraft/core/filesystem/EmptyMount.java @@ -0,0 +1,51 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.filesystem; + +import dan200.computercraft.api.filesystem.IMount; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +public class EmptyMount implements IMount +{ + public EmptyMount() + { + } + + // IMount implementation + + @Override + public boolean exists( String path ) throws IOException + { + return path.isEmpty(); + } + + @Override + public boolean isDirectory( String path ) throws IOException + { + return path.isEmpty(); + } + + @Override + public void list( String path, List contents ) throws IOException + { + } + + @Override + public long getSize( String path ) throws IOException + { + return 0; + } + + @Override + public InputStream openForRead( String path ) throws IOException + { + return null; + } +} diff --git a/src/main/java/dan200/computercraft/core/filesystem/FileMount.java b/src/main/java/dan200/computercraft/core/filesystem/FileMount.java new file mode 100644 index 0000000000..e6c2e3e12d --- /dev/null +++ b/src/main/java/dan200/computercraft/core/filesystem/FileMount.java @@ -0,0 +1,386 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.filesystem; + +import dan200.computercraft.api.filesystem.IWritableMount; + +import java.io.*; +import java.util.List; + +public class FileMount implements IWritableMount +{ + private static int MINIMUM_FILE_SIZE = 500; + + private class CountingOutputStream extends OutputStream + { + private OutputStream m_innerStream; + private long m_ignoredBytesLeft; + + public CountingOutputStream( OutputStream innerStream, long bytesToIgnore ) + { + m_innerStream = innerStream; + m_ignoredBytesLeft = bytesToIgnore; + } + + @Override + public void close() throws IOException + { + m_innerStream.close(); + } + + @Override + public void flush() throws IOException + { + m_innerStream.flush(); + } + + @Override + public void write( byte[] b ) throws IOException + { + count( b.length ); + m_innerStream.write( b ); + } + + @Override + public void write( byte[] b, int off, int len ) throws IOException + { + count( len ); + m_innerStream.write( b, off, len ); + } + + @Override + public void write( int b ) throws IOException + { + count( 1 ); + m_innerStream.write( b ); + } + + private void count( long n ) throws IOException + { + m_ignoredBytesLeft -= n; + if( m_ignoredBytesLeft < 0 ) + { + long newBytes = -m_ignoredBytesLeft; + m_ignoredBytesLeft = 0; + + long bytesLeft = m_capacity - m_usedSpace; + if( newBytes > bytesLeft ) + { + throw new IOException( "Out of space" ); + } + else + { + m_usedSpace += newBytes; + } + } + } + } + + private File m_rootPath; + private long m_capacity; + private long m_usedSpace; + + public FileMount( File rootPath, long capacity ) + { + m_rootPath = rootPath; + m_capacity = capacity + MINIMUM_FILE_SIZE; + m_usedSpace = created() ? measureUsedSpace( m_rootPath ) : MINIMUM_FILE_SIZE; + } + + // IMount implementation + + @Override + public boolean exists( String path ) throws IOException + { + if( !created() ) + { + return path.length() == 0; + } + else + { + File file = getRealPath( path ); + return file.exists(); + } + } + + @Override + public boolean isDirectory( String path ) throws IOException + { + if( !created() ) + { + return path.length() == 0; + } + else + { + File file = getRealPath( path ); + return file.exists() && file.isDirectory(); + } + } + + @Override + public void list( String path, List contents ) throws IOException + { + if( !created() ) + { + if( path.length() != 0 ) + { + throw new IOException( "Not a directory" ); + } + } + else + { + File file = getRealPath( path ); + if( file.exists() && file.isDirectory() ) + { + String[] paths = file.list(); + for( String subPath : paths ) + { + if( new File( file, subPath ).exists() ) + { + contents.add( subPath ); + } + } + } + else + { + throw new IOException( "Not a directory" ); + } + } + } + + @Override + public long getSize( String path ) throws IOException + { + if( !created() ) + { + if( path.length() == 0 ) + { + return 0; + } + } + else + { + File file = getRealPath( path ); + if( file.exists() ) + { + if( file.isDirectory() ) + { + return 0; + } + else + { + return file.length(); + } + } + } + throw new IOException( "No such file" ); + } + + @Override + public InputStream openForRead( String path ) throws IOException + { + if( created() ) + { + File file = getRealPath( path ); + if( file.exists() && !file.isDirectory() ) + { + return new FileInputStream( file ); + } + } + throw new IOException( "No such file" ); + } + + // IWritableMount implementation + + @Override + public void makeDirectory( String path ) throws IOException + { + create(); + File file = getRealPath( path ); + if( file.exists() ) + { + if( !file.isDirectory() ) + { + throw new IOException( "File exists" ); + } + } + else + { + int dirsToCreate = 1; + File parent = file.getParentFile(); + while( !parent.exists() ) + { + ++dirsToCreate; + parent = parent.getParentFile(); + } + + if( getRemainingSpace() < dirsToCreate * MINIMUM_FILE_SIZE ) + { + throw new IOException( "Out of space" ); + } + + boolean success = file.mkdirs(); + if( success ) + { + m_usedSpace += dirsToCreate * MINIMUM_FILE_SIZE; + } + else + { + throw new IOException( "Access denied" ); + } + } + } + + @Override + public void delete( String path ) throws IOException + { + if( path.length() == 0 ) + { + throw new IOException( "Access denied" ); + } + + if( created() ) + { + File file = getRealPath( path ); + if( file.exists() ) + { + deleteRecursively( file ); + } + } + } + + private void deleteRecursively( File file ) throws IOException + { + // Empty directories first + if( file.isDirectory() ) + { + String[] children = file.list(); + for( int i=0; i contents ) throws FileSystemException + { + path = toLocal( path ); + try + { + if( m_mount.exists( path ) && m_mount.isDirectory( path ) ) + { + m_mount.list( path, contents ); + } + else + { + throw new FileSystemException( "Not a directory" ); + } + } + catch( IOException e ) + { + throw new FileSystemException( e.getMessage() ); + } + } + + public long getSize( String path ) throws FileSystemException + { + path = toLocal( path ); + try + { + if( m_mount.exists( path ) ) + { + if( m_mount.isDirectory( path ) ) + { + return 0; + } + else + { + return m_mount.getSize( path ); + } + } + else + { + throw new FileSystemException( "No such file" ); + } + } + catch( IOException e ) + { + throw new FileSystemException( e.getMessage() ); + } + } + + public InputStream openForRead( String path ) throws FileSystemException + { + path = toLocal( path ); + try + { + if( m_mount.exists( path ) && !m_mount.isDirectory( path ) ) + { + return m_mount.openForRead( path ); + } + else + { + throw new FileSystemException( "No such file" ); + } + } + catch( IOException e ) + { + throw new FileSystemException( e.getMessage() ); + } + } + + // IWritableMount forwarders: + + public void makeDirectory( String path ) throws FileSystemException + { + if( m_writableMount == null ) + { + throw new FileSystemException( "Access Denied" ); + } + try + { + path = toLocal( path ); + if( m_mount.exists( path ) ) + { + if( !m_mount.isDirectory( path ) ) + { + throw new FileSystemException( "File exists" ); + } + } + else + { + m_writableMount.makeDirectory( path ); + } + } + catch( IOException e ) + { + throw new FileSystemException( e.getMessage() ); + } + } + + public void delete( String path ) throws FileSystemException + { + if( m_writableMount == null ) + { + throw new FileSystemException( "Access Denied" ); + } + try + { + path = toLocal( path ); + if( m_mount.exists( path ) ) + { + m_writableMount.delete( path ); + } + } + catch( IOException e ) + { + throw new FileSystemException( e.getMessage() ); + } + } + + public OutputStream openForWrite( String path ) throws FileSystemException + { + if( m_writableMount == null ) + { + throw new FileSystemException( "Access Denied" ); + } + try + { + path = toLocal( path ); + if( m_mount.exists( path ) && m_mount.isDirectory( path ) ) + { + throw new FileSystemException( "Cannot write to directory" ); + } + else + { + if( !path.isEmpty() ) + { + String dir = getDirectory( path ); + if( !dir.isEmpty() && !m_mount.exists( path ) ) + { + m_writableMount.makeDirectory( dir ); + } + } + return m_writableMount.openForWrite( path ); + } + } + catch( IOException e ) + { + throw new FileSystemException( e.getMessage() ); + } + } + + public OutputStream openForAppend( String path ) throws FileSystemException + { + if( m_writableMount == null ) + { + throw new FileSystemException( "Access Denied" ); + } + try + { + path = toLocal( path ); + if( !m_mount.exists( path ) ) + { + if( !path.isEmpty() ) + { + String dir = getDirectory( path ); + if( !dir.isEmpty() && !m_mount.exists( path ) ) + { + m_writableMount.makeDirectory( dir ); + } + } + return m_writableMount.openForWrite( path ); + } + else if( m_mount.isDirectory( path ) ) + { + throw new FileSystemException( "Cannot write to directory" ); + } + else + { + return m_writableMount.openForAppend( path ); + } + } + catch( IOException e ) + { + throw new FileSystemException( e.getMessage() ); + } + } + + // private members + + private String toLocal( String path ) + { + return FileSystem.toLocal( path, m_location ); + } + } + + private Map m_mounts = new HashMap(); + private Set m_openFiles = new HashSet(); + + public FileSystem( String rootLabel, IMount rootMount ) throws FileSystemException + { + mount( rootLabel, "", rootMount ); + } + + public FileSystem( String rootLabel, IWritableMount rootMount ) throws FileSystemException + { + mountWritable( rootLabel, "", rootMount ); + } + + public void unload() + { + // Close all dangling open files + synchronized( m_openFiles ) + { + while( m_openFiles.size() > 0 ) + { + IMountedFile file = m_openFiles.iterator().next(); + try + { + file.close(); + } + catch( IOException e ) + { + m_openFiles.remove( file ); + } + } + } + } + + public synchronized void mount( String label, String location, IMount mount ) throws FileSystemException + { + if( mount == null ) + { + throw new NullPointerException(); + } + location = sanitizePath( location ); + if( location.indexOf( ".." ) != -1 ) { + throw new FileSystemException( "Cannot mount below the root" ); + } + mount( new MountWrapper( label, location, mount ) ); + } + + public synchronized void mountWritable( String label, String location, IWritableMount mount ) throws FileSystemException + { + if( mount == null ) + { + throw new NullPointerException(); + } + location = sanitizePath( location ); + if( location.contains( ".." ) ) + { + throw new FileSystemException( "Cannot mount below the root" ); + } + mount( new MountWrapper( label, location, mount ) ); + } + + private synchronized void mount( MountWrapper wrapper ) throws FileSystemException + { + String location = wrapper.getLocation(); + if( m_mounts.containsKey( location ) ) + { + m_mounts.remove( location ); + } + m_mounts.put( location, wrapper ); + } + + public synchronized void unmount( String path ) + { + path = sanitizePath( path ); + if( m_mounts.containsKey( path ) ) + { + m_mounts.remove( path ); + } + } + + public synchronized String combine( String path, String childPath ) + { + path = sanitizePath( path, true ); + childPath = sanitizePath( childPath, true ); + + if( path.isEmpty() ) { + return childPath; + } else if( childPath.isEmpty() ) { + return path; + } else { + return sanitizePath( path + '/' + childPath, true ); + } + } + + public static String getDirectory( String path ) + { + path = sanitizePath( path, true ); + if( path.isEmpty() ) { + return ".."; + } + + int lastSlash = path.lastIndexOf('/'); + if( lastSlash >= 0 ) { + return path.substring( 0, lastSlash ); + } else { + return ""; + } + } + + public static String getName( String path ) + { + path = sanitizePath( path, true ); + if( path.isEmpty() ) { + return "root"; + } + + int lastSlash = path.lastIndexOf('/'); + if( lastSlash >= 0 ) { + return path.substring( lastSlash + 1 ); + } else { + return path; + } + } + + public synchronized long getSize( String path ) throws FileSystemException + { + path = sanitizePath( path ); + MountWrapper mount = getMount( path ); + return mount.getSize( path ); + } + + public synchronized String[] list( String path ) throws FileSystemException + { + path = sanitizePath( path ); + MountWrapper mount = getMount( path ); + + // Gets a list of the files in the mount + List list = new ArrayList(); + mount.list( path, list ); + + // Add any mounts that are mounted at this location + Iterator it = m_mounts.values().iterator(); + while( it.hasNext() ) { + MountWrapper otherMount = it.next(); + if( getDirectory( otherMount.getLocation() ).equals( path ) ) { + list.add( getName( otherMount.getLocation() ) ); + } + } + + // Return list + String[] array = new String[ list.size() ]; + list.toArray(array); + return array; + } + + private void findIn( String dir, List matches, Pattern wildPattern ) throws FileSystemException + { + String[] list = list( dir ); + for( int i=0; i matches = new ArrayList(); + findIn( "", matches, wildPattern ); + + // Return matches + String[] array = new String[ matches.size() ]; + matches.toArray(array); + return array; + } + + public synchronized boolean exists( String path ) throws FileSystemException + { + path = sanitizePath( path ); + MountWrapper mount = getMount( path ); + return mount.exists( path ); + } + + public synchronized boolean isDir( String path ) throws FileSystemException + { + path = sanitizePath( path ); + MountWrapper mount = getMount( path ); + return mount.isDirectory( path ); + } + + public synchronized boolean isReadOnly( String path ) throws FileSystemException + { + path = sanitizePath( path ); + MountWrapper mount = getMount( path ); + return mount.isReadOnly( path ); + } + + public synchronized String getMountLabel( String path ) throws FileSystemException + { + path = sanitizePath( path ); + MountWrapper mount = getMount( path ); + return mount.getLabel(); + } + + public synchronized void makeDir( String path ) throws FileSystemException + { + path = sanitizePath( path ); + MountWrapper mount = getMount( path ); + mount.makeDirectory( path ); + } + + public synchronized void delete( String path ) throws FileSystemException + { + path = sanitizePath( path ); + MountWrapper mount = getMount( path ); + mount.delete( path ); + } + + public synchronized void move( String sourcePath, String destPath ) throws FileSystemException + { + sourcePath = sanitizePath( sourcePath ); + destPath = sanitizePath( destPath ); + if( isReadOnly( sourcePath ) || isReadOnly( destPath ) ) { + throw new FileSystemException( "Access denied" ); + } + if( !exists( sourcePath ) ) { + throw new FileSystemException( "No such file" ); + } + if( exists( destPath ) ) { + throw new FileSystemException( "File exists" ); + } + if( contains( sourcePath, destPath ) ) { + throw new FileSystemException( "Can't move a directory inside itself" ); + } + copy( sourcePath, destPath ); + delete( sourcePath ); + } + + public synchronized void copy( String sourcePath, String destPath ) throws FileSystemException + { + sourcePath = sanitizePath( sourcePath ); + destPath = sanitizePath( destPath ); + if( isReadOnly( destPath ) ) { + throw new FileSystemException( "Access denied" ); + } + if( !exists( sourcePath ) ) { + throw new FileSystemException( "No such file" ); + } + if( exists( destPath ) ) { + throw new FileSystemException( "File exists" ); + } + if( contains( sourcePath, destPath ) ) { + throw new FileSystemException( "Can't copy a directory inside itself" ); + } + copyRecursive( sourcePath, getMount( sourcePath ), destPath, getMount( destPath ) ); + } + + private synchronized void copyRecursive( String sourcePath, MountWrapper sourceMount, String destinationPath, MountWrapper destinationMount ) throws FileSystemException + { + if( !sourceMount.exists( sourcePath ) ) + { + return; + } + + if( sourceMount.isDirectory( sourcePath ) ) + { + // Copy a directory: + // Make the new directory + destinationMount.makeDirectory( destinationPath ); + + // Copy the source contents into it + List sourceChildren = new ArrayList(); + sourceMount.list( sourcePath, sourceChildren ); + for( String child : sourceChildren ) + { + copyRecursive( + combine( sourcePath, child ), sourceMount, + combine( destinationPath, child ), destinationMount + ); + } + } + else + { + // Copy a file: + InputStream source = null; + OutputStream destination = null; + try + { + // Open both files + source = sourceMount.openForRead( sourcePath ); + destination = destinationMount.openForWrite( destinationPath ); + + // Copy bytes as fast as we can + byte[] buffer = new byte[1024]; + while( true ) + { + int bytesRead = source.read( buffer ); + if( bytesRead >= 0 ) + { + destination.write( buffer, 0, bytesRead ); + } + else + { + break; + } + } + } + catch( IOException e ) + { + throw new FileSystemException( e.getMessage() ); + } + finally + { + // Close both files + if( source != null ) + { + try { + source.close(); + } catch( IOException e ) { + // nobody cares + } + } + if( destination != null ) + { + try { + destination.close(); + } catch( IOException e ) { + // nobody cares + } + } + } + } + } + + public synchronized IMountedFileNormal openForRead( String path ) throws FileSystemException + { + path = sanitizePath ( path ); + MountWrapper mount = getMount( path ); + InputStream stream = mount.openForRead( path ); + if( stream != null ) + { + InputStreamReader isr; + try + { + isr = new InputStreamReader( stream, "UTF-8" ); + } + catch( UnsupportedEncodingException e ) + { + isr = new InputStreamReader( stream ); + } + final BufferedReader reader = new BufferedReader( isr ); + IMountedFileNormal file = new IMountedFileNormal() + { + @Override + public String readLine() throws IOException + { + return reader.readLine(); + } + + @Override + public void write(String s, int off, int len, boolean newLine) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public void close() throws IOException + { + synchronized( m_openFiles ) + { + m_openFiles.remove( this ); + reader.close(); + } + } + + @Override + public void flush() throws IOException + { + throw new UnsupportedOperationException(); + } + }; + synchronized( m_openFiles ) + { + m_openFiles.add( file ); + } + return file; + } + return null; + } + + public synchronized IMountedFileNormal openForWrite( String path, boolean append ) throws FileSystemException + { + path = sanitizePath ( path ); + MountWrapper mount = getMount( path ); + OutputStream stream = append ? mount.openForAppend( path ) : mount.openForWrite( path ); + if( stream != null ) + { + OutputStreamWriter osw; + try + { + osw = new OutputStreamWriter( stream, "UTF-8" ); + } + catch( UnsupportedEncodingException e ) + { + osw = new OutputStreamWriter( stream ); + } + final BufferedWriter writer = new BufferedWriter( osw ); + IMountedFileNormal file = new IMountedFileNormal() + { + @Override + public String readLine() throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public void write( String s, int off, int len, boolean newLine ) throws IOException + { + writer.write( s, off, len ); + if( newLine ) + { + writer.newLine(); + } + } + + @Override + public void close() throws IOException + { + synchronized( m_openFiles ) + { + m_openFiles.remove( this ); + writer.close(); + } + } + + @Override + public void flush() throws IOException + { + writer.flush(); + } + }; + synchronized( m_openFiles ) + { + m_openFiles.add( file ); + } + return file; + } + return null; + } + + public synchronized IMountedFileBinary openForBinaryRead( String path ) throws FileSystemException + { + path = sanitizePath ( path ); + MountWrapper mount = getMount( path ); + final InputStream stream = mount.openForRead( path ); + if( stream != null ) + { + IMountedFileBinary file = new IMountedFileBinary() + { + @Override + public int read() throws IOException + { + return stream.read(); + } + + @Override + public void write(int i) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public void close() throws IOException + { + synchronized( m_openFiles ) + { + m_openFiles.remove( this ); + stream.close(); + } + } + + @Override + public void flush() throws IOException + { + throw new UnsupportedOperationException(); + } + }; + synchronized( m_openFiles ) + { + m_openFiles.add( file ); + } + return file; + } + return null; + } + + public synchronized IMountedFileBinary openForBinaryWrite( String path, boolean append ) throws FileSystemException + { + path = sanitizePath ( path ); + MountWrapper mount = getMount( path ); + final OutputStream stream = append ? mount.openForAppend( path ) : mount.openForWrite( path ); + if( stream != null ) + { + IMountedFileBinary file = new IMountedFileBinary() + { + @Override + public int read() throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public void write(int i) throws IOException + { + stream.write(i); + } + + @Override + public void close() throws IOException + { + synchronized( m_openFiles ) + { + m_openFiles.remove( this ); + stream.close(); + } + } + + @Override + public void flush() throws IOException + { + stream.flush(); + } + }; + synchronized( m_openFiles ) + { + m_openFiles.add( file ); + } + return file; + } + return null; + } + + public long getFreeSpace( String path ) throws FileSystemException + { + path = sanitizePath( path ); + MountWrapper mount = getMount( path ); + return mount.getFreeSpace(); + } + + private MountWrapper getMount( String path ) throws FileSystemException + { + // Return the deepest mount that contains a given path + Iterator it = m_mounts.values().iterator(); + MountWrapper match = null; + int matchLength = 999; + while( it.hasNext() ) + { + MountWrapper mount = it.next(); + if( contains( mount.getLocation(), path ) ) { + int len = toLocal( path, mount.getLocation() ).length(); + if( match == null || len < matchLength ) { + match = mount; + matchLength = len; + } + } + } + if( match == null ) + { + throw new FileSystemException( "Invalid Path" ); + } + return match; + } + + private static String sanitizePath( String path ) + { + return sanitizePath( path, false ); + } + + private static String sanitizePath( String path, boolean allowWildcards ) + { + // Allow windowsy slashes + path = path.replace( '\\', '/' ); + + // Clean the path or illegal characters. + final char[] specialChars = { + '"', ':', '<', '>', '?', '|' // Sorted by ascii value (important) + }; + + StringBuilder cleanName = new StringBuilder(); + for( int i = 0; i < path.length(); i++ ) { + char c = path.charAt(i); + if( c >= 32 && Arrays.binarySearch( specialChars, c ) < 0 && (allowWildcards || c != '*') ) + { + cleanName.append((char)c); + } + } + path = cleanName.toString(); + + // Collapse the string into its component parts, removing ..'s + String[] parts = path.split("/"); + Stack outputParts = new Stack(); + for( int n=0; n= 255) { + // If part length > 255 and it is the last part + outputParts.push( part.substring(0, 255) ); + } else { + // Anything else we add to the stack + outputParts.push(part); + } + } + + // Recombine the output parts into a new string + StringBuilder result = new StringBuilder( "" ); + Iterator it = outputParts.iterator(); + while( it.hasNext() ) { + String part = it.next(); + result.append( part ); + if( it.hasNext() ) { + result.append( '/' ); + } + } + + return result.toString(); + } + + public static boolean contains( String pathA, String pathB ) + { + pathA = sanitizePath( pathA ); + pathB = sanitizePath( pathB ); + + if( pathB.equals("..") ) + { + return false; + } + else if ( pathB.startsWith("../") ) + { + return false; + } + else if( pathB.equals( pathA ) ) + { + return true; + } + else if( pathA.isEmpty() ) + { + return true; + } + else + { + return pathB.startsWith( pathA + "/" ); + } + } + + public static String toLocal( String path, String location ) + { + path = sanitizePath( path ); + location = sanitizePath( location ); + + assert( contains( location, path ) ); + String local = path.substring( location.length() ); + if( local.startsWith("/") ) { + return local.substring( 1 ); + } else { + return local; + } + } +} diff --git a/src/main/java/dan200/computercraft/core/filesystem/FileSystemException.java b/src/main/java/dan200/computercraft/core/filesystem/FileSystemException.java new file mode 100644 index 0000000000..08215b3369 --- /dev/null +++ b/src/main/java/dan200/computercraft/core/filesystem/FileSystemException.java @@ -0,0 +1,13 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.filesystem; + +public class FileSystemException extends Exception { + FileSystemException( String s ) { + super( s ); + } +} diff --git a/src/main/java/dan200/computercraft/core/filesystem/IMountedFile.java b/src/main/java/dan200/computercraft/core/filesystem/IMountedFile.java new file mode 100644 index 0000000000..29aa528157 --- /dev/null +++ b/src/main/java/dan200/computercraft/core/filesystem/IMountedFile.java @@ -0,0 +1,13 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.filesystem; + +import java.io.IOException; + +public interface IMountedFile { + public void close() throws IOException; +} diff --git a/src/main/java/dan200/computercraft/core/filesystem/IMountedFileBinary.java b/src/main/java/dan200/computercraft/core/filesystem/IMountedFileBinary.java new file mode 100644 index 0000000000..bb92271a79 --- /dev/null +++ b/src/main/java/dan200/computercraft/core/filesystem/IMountedFileBinary.java @@ -0,0 +1,16 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.filesystem; + +import java.io.IOException; + +public interface IMountedFileBinary extends IMountedFile { + public int read() throws IOException; + public void write(int i) throws IOException; + public void close() throws IOException; + public void flush() throws IOException; +} diff --git a/src/main/java/dan200/computercraft/core/filesystem/IMountedFileNormal.java b/src/main/java/dan200/computercraft/core/filesystem/IMountedFileNormal.java new file mode 100644 index 0000000000..e94f20e461 --- /dev/null +++ b/src/main/java/dan200/computercraft/core/filesystem/IMountedFileNormal.java @@ -0,0 +1,16 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.filesystem; + +import java.io.IOException; + +public interface IMountedFileNormal extends IMountedFile { + public String readLine() throws IOException; + public void write(String s, int off, int len, boolean newLine) throws IOException; + public void close() throws IOException; + public void flush() throws IOException; +} diff --git a/src/main/java/dan200/computercraft/core/filesystem/JarMount.java b/src/main/java/dan200/computercraft/core/filesystem/JarMount.java new file mode 100644 index 0000000000..a944f9f450 --- /dev/null +++ b/src/main/java/dan200/computercraft/core/filesystem/JarMount.java @@ -0,0 +1,249 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.filesystem; + +import dan200.computercraft.api.filesystem.IMount; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Enumeration; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +public class JarMount implements IMount +{ + private class FileInZip + { + private String m_path; + private boolean m_directory; + private long m_size; + private Map m_children; + + public FileInZip( String path, boolean directory, long size ) + { + m_path = path; + m_directory = directory; + m_size = m_directory ? 0 : size; + m_children = new LinkedHashMap(); + } + + public String getPath() + { + return m_path; + } + + public boolean isDirectory() + { + return m_directory; + } + + public long getSize() + { + return m_size; + } + + public void list( List contents ) + { + for( String child : m_children.keySet() ) + { + contents.add( child ); + } + } + + public void insertChild( FileInZip child ) + { + String localPath = FileSystem.toLocal( child.getPath(), m_path ); + m_children.put( localPath, child ); + } + + public FileInZip getFile( String path ) + { + // If we've reached the target, return this + if( path.equals( m_path ) ) + { + return this; + } + + // Otherwise, get the next component of the path + String localPath = FileSystem.toLocal( path, m_path ); + int slash = localPath.indexOf("/"); + if( slash >= 0 ) + { + localPath = localPath.substring( 0, slash ); + } + + // And recurse down using it + FileInZip subFile = m_children.get( localPath ); + if( subFile != null ) + { + return subFile.getFile( path ); + } + + return null; + } + + public FileInZip getParent( String path ) + { + if( path.length() == 0 ) + { + return null; + } + + FileInZip file = getFile( FileSystem.getDirectory( path ) ); + if( file.isDirectory() ) + { + return file; + } + return null; + } + } + + private ZipFile m_zipFile; + private FileInZip m_root; + private String m_rootPath; + + public JarMount( File jarFile, String subPath ) throws IOException + { + if( !jarFile.exists() || jarFile.isDirectory() ) + { + throw new FileNotFoundException(); + } + + // Open the zip file + try + { + m_zipFile = new ZipFile( jarFile ); + } + catch( Exception e ) + { + throw new IOException( "Error loading zip file" ); + } + + if( m_zipFile.getEntry( subPath ) == null ) + { + m_zipFile.close(); + throw new IOException( "Zip does not contain path" ); + } + + // Read in all the entries + Enumeration zipEntries = m_zipFile.entries(); + while( zipEntries.hasMoreElements() ) + { + ZipEntry entry = zipEntries.nextElement(); + String entryName = entry.getName(); + if( entryName.startsWith( subPath ) ) + { + entryName = FileSystem.toLocal( entryName, subPath ); + if( m_root == null ) + { + if( entryName.equals( "" ) ) + { + m_root = new FileInZip( entryName, entry.isDirectory(), entry.getSize() ); + m_rootPath = subPath; + if( !m_root.isDirectory() ) + { + break; + } + } + else + { + // TODO: handle this case. The code currently assumes we find the root before anything else + } + } + else + { + FileInZip parent = m_root.getParent( entryName ); + if( parent != null ) + { + parent.insertChild( new FileInZip( entryName, entry.isDirectory(), entry.getSize() ) ); + } + else + { + // TODO: handle this case. The code currently assumes we find folders before their contents + } + } + } + } + } + + // IMount implementation + + @Override + public boolean exists( String path ) throws IOException + { + FileInZip file = m_root.getFile( path ); + return file != null; + } + + @Override + public boolean isDirectory( String path ) throws IOException + { + FileInZip file = m_root.getFile( path ); + if( file != null ) + { + return file.isDirectory(); + } + return false; + } + + @Override + public void list( String path, List contents ) throws IOException + { + FileInZip file = m_root.getFile( path ); + if( file != null && file.isDirectory() ) + { + file.list( contents ); + } + else + { + throw new IOException( "Not a directory" ); + } + } + + @Override + public long getSize( String path ) throws IOException + { + FileInZip file = m_root.getFile( path ); + if( file != null ) + { + return file.getSize(); + } + throw new IOException( "No such file" ); + } + + @Override + public InputStream openForRead( String path ) throws IOException + { + FileInZip file = m_root.getFile( path ); + if( file != null && !file.isDirectory() ) + { + try + { + String fullPath = m_rootPath; + if( path.length() > 0 ) + { + fullPath = fullPath + "/" + path; + } + ZipEntry entry = m_zipFile.getEntry( fullPath ); + if( entry != null ) + { + return m_zipFile.getInputStream( entry ); + } + } + catch( Exception e ) + { + // treat errors as non-existance of file + } + } + throw new IOException( "No such file" ); + } +} diff --git a/src/main/java/dan200/computercraft/core/filesystem/SubMount.java b/src/main/java/dan200/computercraft/core/filesystem/SubMount.java new file mode 100644 index 0000000000..ac650a0b95 --- /dev/null +++ b/src/main/java/dan200/computercraft/core/filesystem/SubMount.java @@ -0,0 +1,69 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.filesystem; + +import dan200.computercraft.api.filesystem.IMount; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +public class SubMount implements IMount +{ + private IMount m_parent; + private String m_subPath; + + public SubMount( IMount parent, String subPath ) + { + m_parent = parent; + m_subPath = subPath; + } + + // IMount implementation + + @Override + public boolean exists( String path ) throws IOException + { + return m_parent.exists( getFullPath( path ) ); + } + + @Override + public boolean isDirectory( String path ) throws IOException + { + return m_parent.isDirectory( getFullPath( path ) ); + } + + @Override + public void list( String path, List contents ) throws IOException + { + m_parent.list( getFullPath( path ), contents ); + } + + @Override + public long getSize( String path ) throws IOException + { + return m_parent.getSize( getFullPath( path ) ); + } + + @Override + public InputStream openForRead( String path ) throws IOException + { + return m_parent.openForRead( getFullPath( path ) ); + } + + private String getFullPath( String path ) + { + if( path.length() == 0 ) + { + return m_subPath; + } + else + { + return m_subPath + "/" + path; + } + } +} diff --git a/src/main/java/dan200/computercraft/core/lua/ILuaMachine.java b/src/main/java/dan200/computercraft/core/lua/ILuaMachine.java new file mode 100644 index 0000000000..3f0e7a3225 --- /dev/null +++ b/src/main/java/dan200/computercraft/core/lua/ILuaMachine.java @@ -0,0 +1,28 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.lua; +import dan200.computercraft.core.apis.ILuaAPI; + +import java.io.InputStream; +import java.io.OutputStream; + +public interface ILuaMachine +{ + public void addAPI( ILuaAPI api ); + + public void loadBios( InputStream bios ); + public void handleEvent( String eventName, Object[] arguments ); + public void softAbort( String abortMessage ); + public void hardAbort( String abortMessage ); + + public boolean saveState( OutputStream output ); + public boolean restoreState( InputStream input ); + + public boolean isFinished(); + + public void unload(); +} diff --git a/src/main/java/dan200/computercraft/core/lua/LuaJLuaMachine.java b/src/main/java/dan200/computercraft/core/lua/LuaJLuaMachine.java new file mode 100644 index 0000000000..7363f14bb7 --- /dev/null +++ b/src/main/java/dan200/computercraft/core/lua/LuaJLuaMachine.java @@ -0,0 +1,682 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.lua; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.ILuaObject; +import dan200.computercraft.api.lua.ILuaTask; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.core.apis.ILuaAPI; +import dan200.computercraft.core.computer.Computer; +import dan200.computercraft.core.computer.ITask; +import dan200.computercraft.core.computer.MainThread; +import org.luaj.vm2.*; +import org.luaj.vm2.lib.OneArgFunction; +import org.luaj.vm2.lib.VarArgFunction; +import org.luaj.vm2.lib.ZeroArgFunction; +import org.luaj.vm2.lib.jse.JsePlatform; + +import java.io.*; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.Map; + +public class LuaJLuaMachine implements ILuaMachine +{ + private Computer m_computer; + + private LuaValue m_globals; + private LuaValue m_loadString; + private LuaValue m_assert; + private LuaValue m_coroutine_create; + private LuaValue m_coroutine_resume; + private LuaValue m_coroutine_yield; + + private LuaValue m_mainRoutine; + private String m_eventFilter; + private String m_softAbortMessage; + private String m_hardAbortMessage; + + private Map m_valuesInProgress; + private Map m_objectsInProgress; + + public LuaJLuaMachine( Computer computer ) + { + m_computer = computer; + + // Create an environment to run in + m_globals = JsePlatform.debugGlobals(); + m_loadString = m_globals.get("loadstring"); + m_assert = m_globals.get("assert"); + + LuaValue coroutine = m_globals.get("coroutine"); + final LuaValue native_coroutine_create = coroutine.get("create"); + + LuaValue debug = m_globals.get("debug"); + final LuaValue debug_sethook = debug.get("sethook"); + + coroutine.set("create", new OneArgFunction() { + @Override + public LuaValue call( LuaValue value ) + { + final LuaThread thread = native_coroutine_create.call( value ).checkthread(); + debug_sethook.invoke( new LuaValue[] { + thread, + new ZeroArgFunction() { + @Override + public LuaValue call() { + String hardAbortMessage = m_hardAbortMessage; + if( hardAbortMessage != null ) + { + LuaThread.yield(LuaValue.NIL); + } + return LuaValue.NIL; + } + }, + LuaValue.NIL, + LuaValue.valueOf(100000) + } ); + return thread; + } + }); + + m_coroutine_create = coroutine.get("create"); + m_coroutine_resume = coroutine.get("resume"); + m_coroutine_yield = coroutine.get("yield"); + + // Remove globals we don't want to expose + m_globals.set( "collectgarbage", LuaValue.NIL ); + m_globals.set( "dofile", LuaValue.NIL ); + m_globals.set( "loadfile", LuaValue.NIL ); + m_globals.set( "module", LuaValue.NIL ); + m_globals.set( "require", LuaValue.NIL ); + m_globals.set( "package", LuaValue.NIL ); + m_globals.set( "io", LuaValue.NIL ); + m_globals.set( "os", LuaValue.NIL ); + m_globals.set( "print", LuaValue.NIL ); + m_globals.set( "luajava", LuaValue.NIL ); + m_globals.set( "debug", LuaValue.NIL ); + m_globals.set( "newproxy", LuaValue.NIL ); + m_globals.set( "__inext", LuaValue.NIL ); + + // Add version globals + m_globals.set( "_VERSION", "Lua 5.1" ); + m_globals.set( "_HOST", computer.getAPIEnvironment().getComputerEnvironment().getHostString() ); + m_globals.set( "_CC_DEFAULT_SETTINGS", toValue( ComputerCraft.default_computer_settings ) ); + if( ComputerCraft.disable_lua51_features ) + { + m_globals.set( "_CC_DISABLE_LUA51_FEATURES", toValue( true ) ); + } + + // Our main function will go here + m_mainRoutine = null; + m_eventFilter = null; + + m_softAbortMessage = null; + m_hardAbortMessage = null; + } + + @Override + public void addAPI( ILuaAPI api ) + { + // Add the methods of an API to the global table + LuaTable table = wrapLuaObject( api ); + String[] names = api.getNames(); + for( int i=0; i= 1 && results[0].equals( "terminate" ) ) + { + throw new LuaException( "Terminated", 0 ); + } + return results; + } + + @Override + public Object[] pullEventRaw( String filter ) throws InterruptedException + { + return yield( new Object[] { filter } ); + } + + @Override + public Object[] yield( Object[] yieldArgs ) throws InterruptedException + { + try + { + LuaValue[] yieldValues = toValues( yieldArgs, 0 ); + Varargs results = m_coroutine_yield.invoke( LuaValue.varargsOf( yieldValues ) ); + return toObjects( results, 1 ); + } + catch( OrphanedThread e ) + { + throw new InterruptedException(); + } + } + + @Override + public long issueMainThreadTask( final ILuaTask task ) throws LuaException + { + // Issue command + final long taskID = MainThread.getUniqueTaskID(); + final ITask iTask = new ITask() + { + @Override + public Computer getOwner() + { + return m_computer; + } + + @Override + public void execute() + { + try + { + Object[] results = task.execute(); + if( results != null ) + { + Object[] eventArguments = new Object[ results.length + 2 ]; + eventArguments[ 0 ] = taskID; + eventArguments[ 1 ] = true; + for( int i = 0; i < results.length; ++i ) + { + eventArguments[ i + 2 ] = results[ i ]; + } + m_computer.queueEvent( "task_complete", eventArguments ); + } + else + { + m_computer.queueEvent( "task_complete", new Object[] { taskID, true } ); + } + } + catch( LuaException e ) + { + m_computer.queueEvent( "task_complete", new Object[] { + taskID, false, e.getMessage() + } ); + } + catch( Throwable t ) + { + m_computer.queueEvent( "task_complete", new Object[] { + taskID, false, "Java Exception Thrown: " + t.toString() + } ); + } + } + }; + if( MainThread.queueTask( iTask ) ) + { + return taskID; + } + else + { + throw new LuaException( "Task limit exceeded" ); + } + } + + @Override + public Object[] executeMainThreadTask( final ILuaTask task ) throws LuaException, InterruptedException + { + // Issue task + final long taskID = issueMainThreadTask( task ); + + // Wait for response + while( true ) + { + Object[] response = pullEvent( "task_complete" ); + if( response.length >= 3 && response[ 1 ] instanceof Number && response[ 2 ] instanceof Boolean ) + { + if( ( (Number)response[ 1 ] ).intValue() == taskID ) + { + Object[] returnValues = new Object[ response.length - 3 ]; + if( (Boolean)response[ 2 ] ) + { + // Extract the return values from the event and return them + for( int i = 0; i < returnValues.length; ++i ) + { + returnValues[ i ] = response[ i + 3 ]; + } + return returnValues; + } + else + { + // Extract the error message from the event and raise it + if( response.length >= 4 && response[3] instanceof String ) + { + throw new LuaException( (String)response[ 3 ] ); + } + else + { + throw new LuaException(); + } + } + } + } + } + + } + }, method, arguments ); + } + catch( InterruptedException e ) + { + throw new OrphanedThread(); + } + catch( LuaException e ) + { + throw new LuaError( e.getMessage(), e.getLevel() ); + } + catch( Throwable t ) + { + throw new LuaError( "Java Exception Thrown: " + t.toString(), 0 ); + } + return LuaValue.varargsOf( toValues( results, 0 ) ); + } + } ); + } + } + return table; + } + + private LuaValue toValue( Object object ) + { + if( object == null ) + { + return LuaValue.NIL; + } + else if( object instanceof Number ) + { + double d = ((Number)object).doubleValue(); + return LuaValue.valueOf( d ); + } + else if( object instanceof Boolean ) + { + boolean b = ((Boolean)object).booleanValue(); + return LuaValue.valueOf( b ); + } + else if( object instanceof String ) + { + String s = object.toString(); + return LuaValue.valueOf( s ); + } + else if( object instanceof Map ) + { + // Table: + // Start remembering stuff + boolean clearWhenDone = false; + try + { + if( m_valuesInProgress == null ) + { + m_valuesInProgress = new IdentityHashMap(); + clearWhenDone = true; + } + else if( m_valuesInProgress.containsKey( object ) ) + { + return m_valuesInProgress.get( object ); + } + LuaValue table = new LuaTable(); + m_valuesInProgress.put( object, table ); + + // Convert all keys + Iterator it = ((Map)object).entrySet().iterator(); + while( it.hasNext() ) + { + Map.Entry pair = (Map.Entry)it.next(); + LuaValue key = toValue( pair.getKey() ); + LuaValue value = toValue( pair.getValue() ); + if( !key.isnil() && !value.isnil() ) + { + table.set( key, value ); + } + } + return table; + } + finally + { + // Clear (if exiting top level) + if( clearWhenDone ) + { + m_valuesInProgress = null; + } + } + } + else if( object instanceof ILuaObject ) + { + LuaValue table = wrapLuaObject( (ILuaObject)object ); + return table; + } + else + { + return LuaValue.NIL; + } + } + + private LuaValue[] toValues( Object[] objects, int leaveEmpty ) + { + if( objects == null || objects.length == 0 ) + { + return new LuaValue[ leaveEmpty ]; + } + + LuaValue[] values = new LuaValue[objects.length + leaveEmpty]; + for( int i=0; i(); + clearWhenDone = true; + } + else if( m_objectsInProgress.containsKey( value ) ) + { + return m_objectsInProgress.get( value ); + } + Map table = new HashMap(); + m_objectsInProgress.put( value, table ); + + // Convert all keys + LuaValue k = LuaValue.NIL; + while( true ) + { + Varargs keyValue = value.next( k ); + k = keyValue.arg1(); + if( k.isnil() ) + { + break; + } + + LuaValue v = keyValue.arg(2); + Object keyObject = toObject(k); + Object valueObject = toObject(v); + if( keyObject != null && valueObject != null ) + { + table.put( keyObject, valueObject ); + } + } + return table; + } + finally + { + // Clear (if exiting top level) + if( clearWhenDone ) + { + m_objectsInProgress = null; + } + } + } + default: + { + return null; + } + } + } + + private Object[] toObjects( Varargs values, int startIdx ) + { + int count = values.narg(); + Object[] objects = new Object[ count - startIdx + 1 ]; + for( int n=startIdx; n<=count; ++n ) + { + int i = n - startIdx; + LuaValue value = values.arg(n); + objects[i] = toObject( value ); + } + return objects; + } +} diff --git a/src/main/java/dan200/computercraft/core/terminal/Terminal.java b/src/main/java/dan200/computercraft/core/terminal/Terminal.java new file mode 100644 index 0000000000..36d4c71421 --- /dev/null +++ b/src/main/java/dan200/computercraft/core/terminal/Terminal.java @@ -0,0 +1,348 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.terminal; +import net.minecraft.nbt.NBTTagCompound; + +public class Terminal +{ + private static final String base16 = "0123456789abcdef"; + + private int m_cursorX; + private int m_cursorY; + private boolean m_cursorBlink; + private int m_cursorColour; + private int m_cursorBackgroundColour; + + private int m_width; + private int m_height; + + private TextBuffer m_text[]; + private TextBuffer m_textColour[]; + private TextBuffer m_backgroundColour[]; + + private boolean m_changed; + + public Terminal( int width, int height ) + { + m_width = width; + m_height = height; + + m_cursorColour = 0; + m_cursorBackgroundColour = 15; + + m_text = new TextBuffer[ m_height ]; + m_textColour = new TextBuffer[ m_height ]; + m_backgroundColour = new TextBuffer[ m_height ]; + for( int i=0; i= oldHeight ) + { + m_text[ i ] = new TextBuffer( ' ', m_width ); + m_textColour[ i ] = new TextBuffer( base16.charAt( m_cursorColour ), m_width ); + m_backgroundColour[ i ] = new TextBuffer( base16.charAt( m_cursorBackgroundColour ), m_width ); + } + else if( m_width == oldWidth ) + { + m_text[ i ] = oldText[ i ]; + m_textColour[ i ] = oldTextColour[ i ]; + m_backgroundColour[ i ] = oldBackgroundColour[ i ]; + } + else + { + m_text[ i ] = new TextBuffer( ' ', m_width ); + m_textColour[ i ] = new TextBuffer( base16.charAt( m_cursorColour ), m_width ); + m_backgroundColour[ i ] = new TextBuffer( base16.charAt( m_cursorBackgroundColour ), m_width ); + m_text[ i ].write( oldText[ i ] ); + m_textColour[ i ].write( oldTextColour[ i ] ); + m_backgroundColour[ i ].write( oldBackgroundColour[ i ] ); + } + } + m_changed = true; + } + + public void setCursorPos( int x, int y ) + { + if( m_cursorX != x || m_cursorY != y ) + { + m_cursorX = x; + m_cursorY = y; + m_changed = true; + } + } + + public void setCursorBlink( boolean blink ) + { + if( m_cursorBlink != blink ) + { + m_cursorBlink = blink; + m_changed = true; + } + } + + public void setTextColour( int colour ) + { + if( m_cursorColour != colour ) + { + m_cursorColour = colour; + m_changed = true; + } + } + + public void setBackgroundColour( int colour ) + { + if( m_cursorBackgroundColour != colour ) + { + m_cursorBackgroundColour = colour; + m_changed = true; + } + } + + public int getCursorX() + { + return m_cursorX; + } + + public int getCursorY() + { + return m_cursorY; + } + + public boolean getCursorBlink() + { + return m_cursorBlink; + } + + public int getTextColour() + { + return m_cursorColour; + } + + public int getBackgroundColour() + { + return m_cursorBackgroundColour; + } + + public void blit( String text, String textColour, String backgroundColour ) + { + int x = m_cursorX; + int y = m_cursorY; + if( y >= 0 && y < m_height ) + { + m_text[ y ].write( text, x ); + m_textColour[ y ].write( textColour, x ); + m_backgroundColour[ y ].write( backgroundColour, x ); + m_changed = true; + } + } + + public void write( String text ) + { + int x = m_cursorX; + int y = m_cursorY; + if( y >= 0 && y < m_height ) + { + m_text[ y ].write( text, x ); + m_textColour[ y ].fill( base16.charAt( m_cursorColour ), x, x + text.length() ); + m_backgroundColour[ y ].fill( base16.charAt( m_cursorBackgroundColour ), x, x + text.length() ); + m_changed = true; + } + } + + public void scroll( int yDiff ) + { + if( yDiff != 0 ) + { + TextBuffer[] newText = new TextBuffer[ m_height ]; + TextBuffer[] newTextColour = new TextBuffer[ m_height ]; + TextBuffer[] newBackgroundColour = new TextBuffer[ m_height ]; + for( int y = 0; y < m_height; ++y ) + { + int oldY = y + yDiff; + if( oldY >= 0 && oldY < m_height ) + { + newText[ y ] = m_text[ oldY ]; + newTextColour[ y ] = m_textColour[ oldY ]; + newBackgroundColour[ y ] = m_backgroundColour[ oldY ]; + } + else + { + newText[ y ] = new TextBuffer( ' ', m_width ); + newTextColour[ y ] = new TextBuffer( base16.charAt( m_cursorColour ), m_width ); + newBackgroundColour[ y ] = new TextBuffer( base16.charAt( m_cursorBackgroundColour ), m_width ); + } + } + m_text = newText; + m_textColour = newTextColour; + m_backgroundColour = newBackgroundColour; + m_changed = true; + } + } + + public void clear() + { + for( int y = 0; y < m_height; ++y ) + { + m_text[ y ].fill( ' ' ); + m_textColour[ y ].fill( base16.charAt( m_cursorColour ) ); + m_backgroundColour[ y ].fill( base16.charAt( m_cursorBackgroundColour ) ); + } + m_changed = true; + } + + public void clearLine() + { + int y = m_cursorY; + if( y >= 0 && y < m_height ) + { + m_text[ y ].fill( ' ' ); + m_textColour[ y ].fill( base16.charAt( m_cursorColour ) ); + m_backgroundColour[ y ].fill( base16.charAt( m_cursorBackgroundColour ) ); + m_changed = true; + } + } + + public TextBuffer getLine( int y ) + { + if( y >= 0 && y < m_height ) + { + return m_text[ y ]; + } + return null; + } + + public void setLine( int y, String text, String textColour, String backgroundColour ) + { + m_text[y].write( text ); + m_textColour[y].write( textColour ); + m_backgroundColour[y].write( backgroundColour ); + m_changed = true; + } + + public TextBuffer getTextColourLine( int y ) + { + if( y>=0 && y=0 && y= 0 && i getDrops( IBlockAccess world, BlockPos pos, IBlockState state, int fortune ) + { + ArrayList drops = new ArrayList( 1 ); + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileGeneric ) + { + TileGeneric generic = (TileGeneric)tile; + generic.getDroppedItems( drops, fortune, false, false ); + } + return drops; + } + + @Override + public final IBlockState onBlockPlaced( World world, BlockPos pos, EnumFacing side, float hitX, float hitY, float hitZ, int damage, EntityLivingBase placer ) + { + return getDefaultBlockState( damage, side ); + } + + @Override + public final boolean removedByPlayer( World world, BlockPos pos, EntityPlayer player, boolean willHarvest ) + { + if( !world.isRemote ) + { + // Drop items + int fortune = EnchantmentHelper.getFortuneModifier( player ); + boolean creative = player.capabilities.isCreativeMode; + boolean silkTouch = EnchantmentHelper.getSilkTouchModifier( player ); + dropAllItems( world, pos, fortune, creative, silkTouch ); + } + + // Remove block + return super.removedByPlayer( world, pos, player, willHarvest ); + } + + public final void dropAllItems( World world, BlockPos pos, int fortune, boolean creative, boolean silkTouch ) + { + // Get items to drop + List drops = new ArrayList( 1 ); + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileGeneric ) + { + TileGeneric generic = (TileGeneric)tile; + generic.getDroppedItems( drops, fortune, creative, silkTouch ); + } + + // Drop items + if( drops.size() > 0 ) + { + Iterator it = drops.iterator(); + while( it.hasNext() ) + { + ItemStack item = it.next(); + dropItem( world, pos, item ); + } + } + } + + public final void dropItem( World world, BlockPos pos, ItemStack stack ) + { + Block.spawnAsEntity( world, pos, stack ); + } + + @Override + public final void breakBlock( World world, BlockPos pos, IBlockState newState ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileGeneric ) + { + TileGeneric generic = (TileGeneric)tile; + generic.destroy(); + } + super.breakBlock( world, pos, newState ); + world.removeTileEntity( pos ); + } + + @Override + public final ItemStack getPickBlock( MovingObjectPosition target, World world, BlockPos pos, EntityPlayer player ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileGeneric ) + { + TileGeneric generic = (TileGeneric)tile; + return generic.getPickedItem(); + } + return null; + } + + @Override + protected final ItemStack createStackedBlock( IBlockState state ) + { + return null; + } + + @Override + public final boolean onBlockActivated( World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumFacing side, float hitX, float hitY, float hitZ ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileGeneric ) + { + TileGeneric generic = (TileGeneric)tile; + return generic.onActivate( player, side, hitX, hitY, hitZ ); + } + return false; + } + + @Override + public final void onNeighborBlockChange( World world, BlockPos pos, IBlockState state, Block neighbour ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileGeneric ) + { + TileGeneric generic = (TileGeneric)tile; + generic.onNeighbourChange(); + } + } + + @Override + public final boolean isSideSolid( IBlockAccess world, BlockPos pos, EnumFacing side ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileGeneric ) + { + TileGeneric generic = (TileGeneric)tile; + return generic.isSolidOnSide( side.ordinal() ); + } + return false; + } + + @Override + public final boolean canBeReplacedByLeaves( IBlockAccess world, BlockPos pos ) + { + return false; // Generify me if anyone ever feels the need to change this + } + + @Override + public float getExplosionResistance( World world, BlockPos pos, Entity exploder, Explosion explosion ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileGeneric && tile.hasWorldObj() ) + { + TileGeneric generic = (TileGeneric)tile; + if( generic.isImmuneToExplosion( exploder ) ) + { + return 2000.0f; + } + } + return super.getExplosionResistance( exploder ); + } + + private void setBlockBounds( AxisAlignedBB bounds ) + { + setBlockBounds( + (float)bounds.minX, (float)bounds.minY, (float)bounds.minZ, + (float)bounds.maxX, (float)bounds.maxY, (float)bounds.maxZ + ); + } + + @Override + public final void setBlockBoundsBasedOnState( IBlockAccess world, BlockPos pos ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileGeneric && tile.hasWorldObj() ) + { + TileGeneric generic = (TileGeneric)tile; + setBlockBounds( generic.getBounds() ); + } + } + + @Override + public final AxisAlignedBB getCollisionBoundingBox( World world, BlockPos pos, IBlockState state ) + { + setBlockBoundsBasedOnState( world, pos ); + return super.getCollisionBoundingBox( world, pos, state ); + } + + @Override + public final void addCollisionBoxesToList( World world, BlockPos pos, IBlockState state, AxisAlignedBB bigBox, List list, Entity entity ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileGeneric ) + { + TileGeneric generic = (TileGeneric)tile; + + // Get collision bounds + List collision = new ArrayList( 1 ); + generic.getCollisionBounds( collision ); + + // Add collision bounds to list + if( collision.size() > 0 ) + { + Iterator it = collision.iterator(); + while( it.hasNext() ) + { + AxisAlignedBB localBounds = it.next(); + setBlockBounds( localBounds ); + + AxisAlignedBB bounds = super.getCollisionBoundingBox( world, pos, state ); + if( bounds != null && bigBox.intersectsWith(bounds) ) + { + list.add( bounds ); + } + } + } + } + } + + @Override + public final boolean canProvidePower() + { + return true; + } + + @Override + public final boolean canConnectRedstone( IBlockAccess world, BlockPos pos, EnumFacing side ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileGeneric ) + { + TileGeneric generic = (TileGeneric)tile; + return generic.getRedstoneConnectivity( side ); + } + return false; + } + + @Override + public final int getStrongPower( IBlockAccess world, BlockPos pos, IBlockState state, EnumFacing oppositeSide ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileGeneric && tile.hasWorldObj() ) + { + TileGeneric generic = (TileGeneric)tile; + return generic.getRedstoneOutput( oppositeSide.getOpposite() ); + } + return 0; + } + + @Override + public final int getWeakPower( IBlockAccess world, BlockPos pos, IBlockState state, EnumFacing oppositeSide ) + { + return getStrongPower( world, pos, state, oppositeSide ); + } + + public boolean getBundledRedstoneConnectivity( World world, BlockPos pos, EnumFacing side ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileGeneric ) + { + TileGeneric generic = (TileGeneric)tile; + return generic.getBundledRedstoneConnectivity( side ); + } + return false; + } + + public int getBundledRedstoneOutput( World world, BlockPos pos, EnumFacing side ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileGeneric && tile.hasWorldObj() ) + { + TileGeneric generic = (TileGeneric)tile; + return generic.getBundledRedstoneOutput( side ); + } + return 0; + } + + @Override + public boolean onBlockEventReceived( World world, BlockPos pos, IBlockState state, int eventID, int eventParameter ) + { + if( world.isRemote ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileGeneric ) + { + TileGeneric generic = (TileGeneric)tile; + generic.onBlockEvent( eventID, eventParameter ); + } + } + return true; + } + + @Override + public final TileEntity createTileEntity( World world, IBlockState state ) + { + return createTile( state ); + } + + @Override + public final TileEntity createNewTileEntity( World world, int damage ) + { + return createTile( damage ); + } +} diff --git a/src/main/java/dan200/computercraft/shared/common/ClientTerminal.java b/src/main/java/dan200/computercraft/shared/common/ClientTerminal.java new file mode 100644 index 0000000000..37177a0194 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/common/ClientTerminal.java @@ -0,0 +1,92 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.common; + +import dan200.computercraft.core.terminal.Terminal; +import net.minecraft.nbt.NBTTagCompound; + +public class ClientTerminal implements ITerminal +{ + private boolean m_colour; + private Terminal m_terminal; + private boolean m_terminalChanged; + private boolean m_terminalChangedLastFrame; + + public ClientTerminal( boolean colour ) + { + m_colour = colour; + m_terminal = null; + m_terminalChanged = false; + m_terminalChangedLastFrame = false; + } + + public void update() + { + m_terminalChangedLastFrame = m_terminalChanged || (m_terminal != null && m_terminal.getChanged()); + if( m_terminal != null ) + { + m_terminal.clearChanged(); + } + m_terminalChanged = false; + } + + public boolean hasTerminalChanged() + { + return m_terminalChangedLastFrame; + } + + // ITerminal implementation + + @Override + public Terminal getTerminal() + { + return m_terminal; + } + + @Override + public boolean isColour() + { + return m_colour; + } + + public void readDescription( NBTTagCompound nbttagcompound ) + { + m_colour = nbttagcompound.getBoolean( "colour" ); + if( nbttagcompound.hasKey( "terminal" ) ) + { + NBTTagCompound terminal = nbttagcompound.getCompoundTag( "terminal" ); + resizeTerminal( terminal.getInteger( "term_width" ), terminal.getInteger( "term_height" ) ); + m_terminal.readFromNBT( terminal ); + } + else + { + deleteTerminal(); + } + } + + private void resizeTerminal( int width, int height ) + { + if( m_terminal == null ) + { + m_terminal = new Terminal( width, height ); + m_terminalChanged = true; + } + else + { + m_terminal.resize( width, height ); + } + } + + private void deleteTerminal() + { + if( m_terminal != null ) + { + m_terminal = null; + m_terminalChanged = true; + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/common/DefaultBundledRedstoneProvider.java b/src/main/java/dan200/computercraft/shared/common/DefaultBundledRedstoneProvider.java new file mode 100644 index 0000000000..1aa46578a2 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/common/DefaultBundledRedstoneProvider.java @@ -0,0 +1,40 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.common; + +import dan200.computercraft.api.redstone.IBundledRedstoneProvider; +import net.minecraft.block.Block; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +public class DefaultBundledRedstoneProvider implements IBundledRedstoneProvider +{ + public DefaultBundledRedstoneProvider() + { + } + + @Override + public int getBundledRedstoneOutput( World world, BlockPos pos, EnumFacing side ) + { + return getDefaultBundledRedstoneOutput( world, pos, side ); + } + + public static int getDefaultBundledRedstoneOutput( World world, BlockPos pos, EnumFacing side ) + { + Block block = world.getBlockState( pos ).getBlock(); + if( block != null && block instanceof BlockGeneric ) + { + BlockGeneric generic = (BlockGeneric)block; + if( generic.getBundledRedstoneConnectivity( world, pos, side ) ) + { + return generic.getBundledRedstoneOutput( world, pos, side ); + } + } + return -1; + } +} diff --git a/src/main/java/dan200/computercraft/shared/common/IDirectionalTile.java b/src/main/java/dan200/computercraft/shared/common/IDirectionalTile.java new file mode 100644 index 0000000000..494486ba99 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/common/IDirectionalTile.java @@ -0,0 +1,15 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.common; + +import net.minecraft.util.EnumFacing; + +public interface IDirectionalTile +{ + public EnumFacing getDirection(); + public void setDirection( EnumFacing dir ); +} diff --git a/src/main/java/dan200/computercraft/shared/common/ITerminal.java b/src/main/java/dan200/computercraft/shared/common/ITerminal.java new file mode 100644 index 0000000000..3b10da9a90 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/common/ITerminal.java @@ -0,0 +1,15 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.common; + +import dan200.computercraft.core.terminal.Terminal; + +public interface ITerminal +{ + public Terminal getTerminal(); + public boolean isColour(); +} diff --git a/src/main/java/dan200/computercraft/shared/common/ITerminalTile.java b/src/main/java/dan200/computercraft/shared/common/ITerminalTile.java new file mode 100644 index 0000000000..f7bbc022a7 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/common/ITerminalTile.java @@ -0,0 +1,12 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.common; + +public interface ITerminalTile +{ + public ITerminal getTerminal(); +} diff --git a/src/main/java/dan200/computercraft/shared/common/ServerTerminal.java b/src/main/java/dan200/computercraft/shared/common/ServerTerminal.java new file mode 100644 index 0000000000..b8755a2087 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/common/ServerTerminal.java @@ -0,0 +1,100 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.common; + +import dan200.computercraft.core.terminal.Terminal; +import net.minecraft.nbt.NBTTagCompound; + +public class ServerTerminal implements ITerminal +{ + private final boolean m_colour; + private Terminal m_terminal; + private boolean m_terminalChanged; + private boolean m_terminalChangedLastFrame; + + public ServerTerminal( boolean colour ) + { + m_colour = colour; + m_terminal = null; + m_terminalChanged = false; + m_terminalChangedLastFrame = false; + } + + public ServerTerminal( boolean colour, int terminalWidth, int terminalHeight ) + { + m_colour = colour; + m_terminal = new Terminal( terminalWidth, terminalHeight ); + m_terminalChanged = false; + m_terminalChangedLastFrame = false; + } + + public void resize( int width, int height ) + { + if( m_terminal == null ) + { + m_terminal = new Terminal( width, height ); + m_terminalChanged = true; + } + else + { + m_terminal.resize( width, height ); + } + } + + public void delete() + { + if( m_terminal != null ) + { + m_terminal = null; + m_terminalChanged = true; + } + } + + public void update() + { + m_terminalChangedLastFrame = m_terminalChanged || (m_terminal != null && m_terminal.getChanged()); + if( m_terminal != null ) + { + m_terminal.clearChanged(); + } + m_terminalChanged = false; + } + + public boolean hasTerminalChanged() + { + return m_terminalChangedLastFrame; + } + + // ITerminal implementation + + @Override + public Terminal getTerminal() + { + return m_terminal; + } + + @Override + public boolean isColour() + { + return m_colour; + } + + // Networking stuff + + public void writeDescription( NBTTagCompound nbttagcompound ) + { + nbttagcompound.setBoolean( "colour", m_colour ); + if( m_terminal != null ) + { + NBTTagCompound terminal = new NBTTagCompound(); + terminal.setInteger( "term_width", m_terminal.getWidth() ); + terminal.setInteger( "term_height", m_terminal.getHeight() ); + m_terminal.writeToNBT( terminal ); + nbttagcompound.setTag( "terminal", terminal ); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/common/TileGeneric.java b/src/main/java/dan200/computercraft/shared/common/TileGeneric.java new file mode 100644 index 0000000000..de2a45eff7 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/common/TileGeneric.java @@ -0,0 +1,210 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.common; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.network.ComputerCraftPacket; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.Packet; +import net.minecraft.network.play.server.S35PacketUpdateTileEntity; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +import java.util.List; + +public abstract class TileGeneric extends TileEntity +{ + public TileGeneric() + { + } + + public void requestTileEntityUpdate() + { + if( worldObj.isRemote ) + { + ComputerCraftPacket packet = new ComputerCraftPacket(); + packet.m_packetType = ComputerCraftPacket.RequestTileEntityUpdate; + + BlockPos pos = getPos(); + packet.m_dataInt = new int[]{ pos.getX(), pos.getY(), pos.getZ() }; + ComputerCraft.sendToServer( packet ); + } + } + + public void destroy() + { + } + + public BlockGeneric getBlock() + { + Block block = worldObj.getBlockState( getPos() ).getBlock(); + if( block != null && block instanceof BlockGeneric ) + { + return (BlockGeneric)block; + } + return null; + } + + protected final IBlockState getBlockState() + { + return worldObj.getBlockState( getPos() ); + } + + public final void updateBlock() + { + worldObj.markBlockForUpdate( getPos() ); + worldObj.markChunkDirty( getPos(), this ); + } + + protected final void setBlockState( IBlockState newState ) + { + worldObj.setBlockState( getPos(), newState, 3 ); + } + + public void getDroppedItems( List drops, int fortune, boolean creative, boolean silkTouch ) + { + } + + public ItemStack getPickedItem() + { + return null; + } + + public boolean onActivate( EntityPlayer player, EnumFacing side, float hitX, float hitY, float hitZ ) + { + return false; + } + + public void onNeighbourChange() + { + } + + public boolean isSolidOnSide( int side ) + { + return true; + } + + public boolean isImmuneToExplosion( Entity exploder ) + { + return false; + } + + public AxisAlignedBB getBounds() + { + return new AxisAlignedBB( 0.0, 0.0, 0.0, 1.0, 1.0, 1.0 ); + } + + public void getCollisionBounds( List bounds ) + { + bounds.add( getBounds() ); + } + + public boolean getRedstoneConnectivity( EnumFacing side ) + { + return false; + } + + public int getRedstoneOutput( EnumFacing side ) + { + return 0; + } + + public boolean getBundledRedstoneConnectivity( EnumFacing side ) + { + return false; + } + + public int getBundledRedstoneOutput( EnumFacing side ) + { + return 0; + } + + protected double getInteractRange( EntityPlayer player ) + { + return 8.0; + } + + public boolean isUsable( EntityPlayer player, boolean ignoreRange ) + { + if( player != null && player.isEntityAlive() ) + { + if( worldObj.getTileEntity( getPos() ) == this ) + { + if( !ignoreRange ) + { + double range = getInteractRange( player ); + BlockPos pos = getPos(); + return player.getEntityWorld() == worldObj && + player.getDistanceSq( (double)pos.getX() + 0.5, (double)pos.getY() + 0.5, (double)pos.getZ() + 0.5 ) <= ( range * range ); + } + return true; + } + } + return false; + } + + protected void writeDescription( NBTTagCompound nbttagcompound ) + { + } + + protected void readDescription( NBTTagCompound nbttagcompound ) + { + } + + public final void sendBlockEvent( int eventID ) + { + sendBlockEvent( eventID, 0 ); + } + + public final void sendBlockEvent( int eventID, int eventParameter ) + { + worldObj.addBlockEvent( getPos(), worldObj.getBlockState( getPos() ).getBlock(), eventID, eventParameter ); + } + + public void onBlockEvent( int eventID, int eventParameter ) + { + } + + @Override + public boolean shouldRefresh( World world, BlockPos pos, IBlockState oldState, IBlockState newState ) + { + return newState.getBlock() != oldState.getBlock(); + } + + @Override + public final Packet getDescriptionPacket() + { + // Communicate properties + NBTTagCompound nbttagcompound = new NBTTagCompound(); + writeDescription( nbttagcompound ); + return new S35PacketUpdateTileEntity( getPos(), 0, nbttagcompound ); + } + + @Override + public final void onDataPacket( NetworkManager net, S35PacketUpdateTileEntity packet ) + { + switch( packet.getTileEntityType() ) + { + case 0: + { + // Receive properties + NBTTagCompound nbttagcompound = packet.getNbtCompound(); + readDescription( nbttagcompound ); + break; + } + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java b/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java new file mode 100644 index 0000000000..3d5c2a78fc --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java @@ -0,0 +1,325 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.apis; + +import com.google.common.collect.ImmutableMap; +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.ILuaTask; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.core.apis.ILuaAPI; +import dan200.computercraft.shared.computer.blocks.TileCommandComputer; +import dan200.computercraft.shared.util.WorldUtil; +import net.minecraft.block.Block; +import net.minecraft.block.properties.IProperty; +import net.minecraft.block.state.IBlockState; +import net.minecraft.command.ICommand; +import net.minecraft.command.ICommandManager; +import net.minecraft.command.ICommandSender; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; + +import java.util.HashMap; +import java.util.Map; + +public class CommandAPI implements ILuaAPI +{ + private TileCommandComputer m_computer; + + public CommandAPI( TileCommandComputer computer ) + { + m_computer = computer; + } + + // ILuaAPI implementation + + @Override + public String[] getNames() + { + return new String[] { + "commands" + }; + } + + @Override + public void startup() + { + } + + @Override + public void advance( double dt ) + { + } + + @Override + public void shutdown() + { + } + + @Override + public String[] getMethodNames() + { + return new String[] { + "exec", + "execAsync", + "list", + "getBlockPosition", + "getBlockInfos", + "getBlockInfo" + }; + } + + private Map createOutput( String output ) + { + Map result = new HashMap( 1 ); + result.put( 1, output ); + return result; + } + + private Object[] doCommand( String command ) + { + MinecraftServer server = MinecraftServer.getServer(); + if( server != null && server.isCommandBlockEnabled() ) + { + ICommandManager commandManager = server.getCommandManager(); + try + { + TileCommandComputer.CommandSender sender = m_computer.getCommandSender(); + sender.clearOutput(); + + int result = commandManager.executeCommand( sender, command ); + return new Object[]{ (result > 0), sender.copyOutput() }; + } + catch( Throwable t ) + { + return new Object[]{ false, createOutput( "Java Exception Thrown: " + t.toString() ) }; + } + } + else + { + return new Object[] { false, createOutput( "Command blocks disabled by server" ) }; + } + } + + private Object getBlockInfo( World world, BlockPos pos ) + { + // Get the details of the block + IBlockState state = world.getBlockState( pos ); + Block block = state.getBlock(); + String name = ((ResourceLocation)Block.blockRegistry.getNameForObject( block )).toString(); + int metadata = block.getMetaFromState( state ); + + Map table = new HashMap(); + table.put( "name", name ); + table.put( "metadata", metadata ); + + Map stateTable = new HashMap(); + for( Object o : block.getActualState( state, world, pos ).getProperties().entrySet() ) + { + ImmutableMap.Entry entry = (ImmutableMap.Entry)o; + String propertyName = entry.getKey().getName(); + Object value = entry.getValue(); + if( value instanceof String || value instanceof Number || value instanceof Boolean ) + { + stateTable.put( propertyName, value ); + } + else + { + stateTable.put( propertyName, value.toString() ); + } + } + table.put( "state", stateTable ); + // TODO: NBT data? + return table; + } + + @Override + public Object[] callMethod( ILuaContext context, int method, Object[] arguments ) throws LuaException, InterruptedException + { + switch( method ) + { + case 0: + { + // exec + if( arguments.length < 1 || !(arguments[0] instanceof String) ) + { + throw new LuaException( "Expected string" ); + } + final String command = (String)arguments[0]; + return context.executeMainThreadTask( new ILuaTask() + { + @Override + public Object[] execute() throws LuaException + { + return doCommand( command ); + } + } ); + } + case 1: + { + // execAsync + if( arguments.length < 1 || !(arguments[0] instanceof String) ) + { + throw new LuaException( "Expected string" ); + } + final String command = (String)arguments[0]; + long taskID = context.issueMainThreadTask( new ILuaTask() + { + @Override + public Object[] execute() throws LuaException + { + return doCommand( command ); + } + } ); + return new Object[] { taskID }; + } + case 2: + { + // list + return context.executeMainThreadTask( new ILuaTask() + { + @Override + public Object[] execute() throws LuaException + { + int i = 1; + Map result = new HashMap(); + MinecraftServer server = MinecraftServer.getServer(); + if( server != null ) + { + ICommandManager commandManager = server.getCommandManager(); + ICommandSender commmandSender = m_computer.getCommandSender(); + Map commands = commandManager.getCommands(); + for( Object entryObject : commands.entrySet() ) + { + Map.Entry entry = (Map.Entry)entryObject; + String name = (String)entry.getKey(); + ICommand command = (ICommand)entry.getValue(); + try + { + if( command.canCommandSenderUseCommand( commmandSender ) ) + { + result.put( i++, name ); + } + } + catch( Throwable t ) + { + // Ignore buggy command + } + } + } + return new Object[]{ result }; + } + } ); + } + case 3: + { + // getBlockPosition + // This is probably safe to do on the Lua thread. Probably. + BlockPos pos = m_computer.getPos(); + return new Object[] { pos.getX(), pos.getY(), pos.getZ() }; + } + case 4: + { + // getBlockInfos + if( arguments.length < 6 || + !(arguments[0] instanceof Number) || + !(arguments[1] instanceof Number) || + !(arguments[2] instanceof Number) || + !(arguments[3] instanceof Number) || + !(arguments[4] instanceof Number) || + !(arguments[5] instanceof Number) ) + { + throw new LuaException( "Expected number, number, number, number, number, number" ); + } + final int minx = ((Number)arguments[0]).intValue(); + final int miny = ((Number)arguments[1]).intValue(); + final int minz = ((Number)arguments[2]).intValue(); + final int maxx = ((Number)arguments[3]).intValue(); + final int maxy = ((Number)arguments[4]).intValue(); + final int maxz = ((Number)arguments[5]).intValue(); + return context.executeMainThreadTask( new ILuaTask() + { + @Override + public Object[] execute() throws LuaException + { + // Get the details of the block + World world = m_computer.getWorld(); + BlockPos min = new BlockPos( + Math.min( minx, maxx ), + Math.min( miny, maxy ), + Math.min( minz, maxz ) + ); + BlockPos max = new BlockPos( + Math.max( minx, maxx ), + Math.max( miny, maxy ), + Math.max( minz, maxz ) + ); + if( !WorldUtil.isBlockInWorld( world, min ) || !WorldUtil.isBlockInWorld( world, max ) ) + { + throw new LuaException( "Co-ordinates out or range" ); + } + if( ( max.getX() - min.getX() + 1 ) * ( max.getY() - min.getY() + 1 ) * ( max.getZ() - min.getZ() + 1 ) > 4096 ) + { + throw new LuaException( "Too many blocks" ); + } + int i=1; + Map results = new HashMap(); + for( int y=min.getY(); y<= max.getY(); ++y ) + { + for( int z = min.getZ(); z <= max.getZ(); ++z ) + { + for( int x = min.getX(); x <= max.getX(); ++x ) + { + BlockPos pos = new BlockPos( x, y, z ); + results.put( i++, getBlockInfo( world, pos ) ); + } + } + } + return new Object[]{ results }; + } + } ); + } + case 5: + { + // getBlockInfo + if( arguments.length < 3 || + !(arguments[0] instanceof Number) || + !(arguments[1] instanceof Number) || + !(arguments[2] instanceof Number) ) + { + throw new LuaException( "Expected number, number, number" ); + } + final int x = ((Number)arguments[0]).intValue(); + final int y = ((Number)arguments[1]).intValue(); + final int z = ((Number)arguments[2]).intValue(); + return context.executeMainThreadTask( new ILuaTask() + { + @Override + public Object[] execute() throws LuaException + { + // Get the details of the block + World world = m_computer.getWorld(); + BlockPos position = new BlockPos( x, y, z ); + if( WorldUtil.isBlockInWorld( world, position ) ) + { + return new Object[]{ getBlockInfo( world, position ) }; + } + else + { + throw new LuaException( "co-ordinates out or range" ); + } + } + } ); + } + default: + { + return null; + } + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/BlockCommandComputer.java b/src/main/java/dan200/computercraft/shared/computer/blocks/BlockCommandComputer.java new file mode 100644 index 0000000000..e5b6917b24 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/BlockCommandComputer.java @@ -0,0 +1,147 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.blocks; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.core.IComputer; +import dan200.computercraft.shared.peripheral.common.TilePeripheralBase; +import dan200.computercraft.shared.util.DirectionUtil; +import net.minecraft.block.material.Material; +import net.minecraft.block.properties.IProperty; +import net.minecraft.block.properties.PropertyDirection; +import net.minecraft.block.properties.PropertyEnum; +import net.minecraft.block.state.BlockState; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +public class BlockCommandComputer extends BlockComputerBase +{ + // Statics + + public static class Properties + { + public static final PropertyDirection FACING = PropertyDirection.create("facing", EnumFacing.Plane.HORIZONTAL); + public static final PropertyEnum STATE = PropertyEnum.create("state", ComputerState.class); + } + + // Members + + public BlockCommandComputer() + { + super( Material.iron ); + setBlockUnbreakable(); + setResistance( 6000000.0F ); + setUnlocalizedName( "computercraft:command_computer" ); + setCreativeTab( ComputerCraft.mainCreativeTab ); + setDefaultState( this.blockState.getBaseState() + .withProperty( Properties.FACING, EnumFacing.NORTH ) + .withProperty( Properties.STATE, ComputerState.Off ) + ); + } + + @Override + protected BlockState createBlockState() + { + return new BlockState(this, new IProperty[] { + Properties.FACING, + Properties.STATE + }); + } + + @Override + public IBlockState getStateFromMeta( int meta ) + { + EnumFacing dir = EnumFacing.getFront( meta & 0x7 ); + if( dir.getAxis() == EnumFacing.Axis.Y ) + { + dir = EnumFacing.NORTH; + } + return getDefaultState().withProperty( Properties.FACING, dir ); + } + + @Override + public int getMetaFromState( IBlockState state ) + { + return ((EnumFacing)state.getValue( Properties.FACING )).getIndex(); + } + + @Override + public IBlockState getActualState( IBlockState state, IBlockAccess world, BlockPos pos ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof IComputerTile ) + { + IComputer computer = ((IComputerTile)tile).getComputer(); + if( computer != null && computer.isOn() ) + { + if( computer.isCursorDisplayed() ) + { + return state.withProperty( Properties.STATE, ComputerState.Blinking ); + } + else + { + return state.withProperty( Properties.STATE, ComputerState.On ); + } + } + } + return state.withProperty( Properties.STATE, ComputerState.Off ); + } + + @Override + protected IBlockState getDefaultBlockState( ComputerFamily family, EnumFacing placedSide ) + { + if( placedSide.getAxis() != EnumFacing.Axis.Y ) + { + return getDefaultState().withProperty( Properties.FACING, placedSide ); + } + else + { + return getDefaultState(); + } + } + + @Override + public ComputerFamily getFamily( int damage ) + { + return ComputerFamily.Command; + } + + @Override + public ComputerFamily getFamily( IBlockState state ) + { + return ComputerFamily.Command; + } + + @Override + protected TileComputer createTile( ComputerFamily family ) + { + return new TileCommandComputer(); + } + + @Override + public void onBlockPlacedBy( World world, BlockPos pos, IBlockState state, EntityLivingBase player, ItemStack itemstack ) + { + // Not sure why this is necessary + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileCommandComputer ) + { + tile.setWorldObj( world ); // Not sure why this is necessary + tile.setPos( pos ); // Not sure why this is necessary + } + + // Set direction + EnumFacing dir = DirectionUtil.fromEntityRot( player ); + setDirection( world, pos, dir ); + } +} diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputer.java b/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputer.java new file mode 100644 index 0000000000..d23cecd1bf --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputer.java @@ -0,0 +1,179 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.blocks; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.core.IComputer; +import dan200.computercraft.shared.computer.items.ItemComputer; +import dan200.computercraft.shared.util.DirectionUtil; +import net.minecraft.block.material.Material; +import net.minecraft.block.properties.IProperty; +import net.minecraft.block.properties.PropertyBool; +import net.minecraft.block.properties.PropertyDirection; +import net.minecraft.block.properties.PropertyEnum; +import net.minecraft.block.state.BlockState; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +public class BlockComputer extends BlockComputerBase +{ + // Statics + public static class Properties + { + public static final PropertyDirection FACING = PropertyDirection.create("facing", EnumFacing.Plane.HORIZONTAL); + public static final PropertyBool ADVANCED = PropertyBool.create("advanced"); + public static final PropertyEnum STATE = PropertyEnum.create("state", ComputerState.class); + } + + // Members + + public BlockComputer() + { + super( Material.rock ); + setHardness( 2.0f ); + setUnlocalizedName( "computercraft:computer" ); + setCreativeTab( ComputerCraft.mainCreativeTab ); + setDefaultState( this.blockState.getBaseState() + .withProperty( Properties.FACING, EnumFacing.NORTH ) + .withProperty( Properties.ADVANCED, false ) + .withProperty( Properties.STATE, ComputerState.Off ) + ); + } + + @Override + protected BlockState createBlockState() + { + return new BlockState(this, new IProperty[] { + Properties.FACING, + Properties.ADVANCED, + Properties.STATE + }); + } + + @Override + public IBlockState getStateFromMeta( int meta ) + { + EnumFacing dir = EnumFacing.getFront( meta & 0x7 ); + if( dir.getAxis() == EnumFacing.Axis.Y ) + { + dir = EnumFacing.NORTH; + } + + IBlockState state = getDefaultState().withProperty( Properties.FACING, dir ); + if( meta > 8 ) + { + state = state.withProperty( Properties.ADVANCED, true ); + } + else + { + state = state.withProperty( Properties.ADVANCED, false ); + } + return state; + } + + @Override + public int getMetaFromState( IBlockState state ) + { + int meta = ((EnumFacing)state.getValue( Properties.FACING )).getIndex(); + if( (Boolean)state.getValue( Properties.ADVANCED ) ) + { + meta += 8; + } + return meta; + } + + @Override + protected IBlockState getDefaultBlockState( ComputerFamily family, EnumFacing placedSide ) + { + IBlockState state = getDefaultState(); + if( placedSide.getAxis() != EnumFacing.Axis.Y ) + { + state = state.withProperty( Properties.FACING, placedSide ); + } + + switch( family ) + { + case Normal: + default: + { + return state.withProperty( Properties.ADVANCED, false ); + } + case Advanced: + { + return state.withProperty( Properties.ADVANCED, true ); + } + } + } + + @Override + public IBlockState getActualState( IBlockState state, IBlockAccess world, BlockPos pos ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof IComputerTile ) + { + IComputer computer = ((IComputerTile)tile).getComputer(); + if( computer != null && computer.isOn() ) + { + if( computer.isCursorDisplayed() ) + { + return state.withProperty( Properties.STATE, ComputerState.Blinking ); + } + else + { + return state.withProperty( Properties.STATE, ComputerState.On ); + } + } + } + return state.withProperty( Properties.STATE, ComputerState.Off ); + } + + @Override + public ComputerFamily getFamily( int damage ) + { + return ((ItemComputer) Item.getItemFromBlock(this)).getFamily( damage ); + } + + @Override + public ComputerFamily getFamily( IBlockState state ) + { + if( (Boolean)state.getValue( Properties.ADVANCED ) ) { + return ComputerFamily.Advanced; + } else { + return ComputerFamily.Normal; + } + } + + @Override + protected TileComputer createTile( ComputerFamily family ) + { + return new TileComputer(); + } + + @Override + public void onBlockPlacedBy( World world, BlockPos pos, IBlockState state, EntityLivingBase player, ItemStack stack ) + { + // Not sure why this is necessary + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileComputer ) + { + tile.setWorldObj( world ); // Not sure why this is necessary + tile.setPos( pos ); // Not sure why this is necessary + } + + // Set direction + EnumFacing dir = DirectionUtil.fromEntityRot( player ); + setDirection( world, pos, dir ); + } +} diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java b/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java new file mode 100644 index 0000000000..358467072e --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java @@ -0,0 +1,80 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.blocks; + +import dan200.computercraft.shared.common.BlockDirectional; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.items.ItemComputerBase; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.item.Item; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +public abstract class BlockComputerBase extends BlockDirectional +{ + public BlockComputerBase( Material material ) + { + super( material ); + } + + @Override + public void onBlockAdded( World world, BlockPos pos, IBlockState state ) + { + super.onBlockAdded( world, pos, state ); + updateInput( world, pos ); + } + + @Override + public void setDirection( World world, BlockPos pos, EnumFacing dir ) + { + super.setDirection( world, pos, dir ); + updateInput( world, pos ); + } + + protected abstract IBlockState getDefaultBlockState( ComputerFamily family, EnumFacing placedSide ); + protected abstract ComputerFamily getFamily( int damage ); + protected abstract ComputerFamily getFamily( IBlockState state ); + protected abstract TileComputerBase createTile( ComputerFamily family ); + + @Override + protected final IBlockState getDefaultBlockState( int damage, EnumFacing placedSide ) + { + ItemComputerBase item = (ItemComputerBase)Item.getItemFromBlock( this ); + return getDefaultBlockState( item.getFamily( damage ), placedSide ); + } + + @Override + public final TileComputerBase createTile( IBlockState state ) + { + return createTile( getFamily( state ) ); + } + + @Override + public final TileComputerBase createTile( int damage ) + { + return createTile( getFamily( damage ) ); + } + + public final ComputerFamily getFamily( IBlockAccess world, BlockPos pos ) + { + return getFamily( world.getBlockState( pos ) ); + } + + protected void updateInput( IBlockAccess world, BlockPos pos ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileComputerBase ) + { + TileComputerBase computer = (TileComputerBase)tile; + computer.updateInput(); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerPeripheral.java b/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerPeripheral.java new file mode 100644 index 0000000000..fa4b9db117 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerPeripheral.java @@ -0,0 +1,104 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.blocks; + +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.shared.computer.core.ServerComputer; + +public class ComputerPeripheral + implements IPeripheral +{ + private final String m_type; + private final ServerComputer m_computer; + + public ComputerPeripheral( String type, ServerComputer computer ) + { + m_type = type; + m_computer = computer; + } + + // IPeripheral implementation + + @Override + public String getType() + { + return m_type; + } + + @Override + public String[] getMethodNames() + { + return new String[] { + "turnOn", + "shutdown", + "reboot", + "getID", + "isOn", + }; + } + + @Override + public Object[] callMethod( IComputerAccess computer, ILuaContext context, int method, Object[] arguments ) throws LuaException + { + switch( method ) + { + case 0: + { + // turnOn + m_computer.turnOn(); + return null; + } + case 1: + { + // shutdown + m_computer.shutdown(); + return null; + } + case 2: + { + // reboot + m_computer.reboot(); + return null; + } + case 3: + { + // getID + return new Object[] { + m_computer.assignID() + }; + } + case 4: + { + // isOn + return new Object[] { m_computer.isOn() }; + } + default: + { + return null; + } + } + } + + @Override + public void attach( IComputerAccess computer ) + { + } + + @Override + public void detach( IComputerAccess computer ) + { + } + + @Override + public boolean equals( IPeripheral other ) + { + return (other != null && other.getClass() == this.getClass()); + } +} diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerState.java b/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerState.java new file mode 100644 index 0000000000..bcebed3155 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerState.java @@ -0,0 +1,36 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.blocks; + +import net.minecraft.util.IStringSerializable; + +public enum ComputerState implements IStringSerializable +{ + Off( "off" ), + On( "on" ), + Blinking( "blinking" ); + + private String m_name; + + private ComputerState( String name ) + { + m_name = name; + } + + @Override + public String getName() + { + return m_name; + } + + @Override + public String toString() + { + return getName(); + } +} + diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/IComputerTile.java b/src/main/java/dan200/computercraft/shared/computer/blocks/IComputerTile.java new file mode 100644 index 0000000000..c2d8173c92 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/IComputerTile.java @@ -0,0 +1,20 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.blocks; + +import dan200.computercraft.shared.common.ITerminalTile; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.core.IComputer; + +public interface IComputerTile extends ITerminalTile +{ + public void setComputerID( int id ); + public void setLabel( String label ); + public IComputer getComputer(); + public IComputer createComputer(); + public ComputerFamily getFamily(); +} diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/TileCommandComputer.java b/src/main/java/dan200/computercraft/shared/computer/blocks/TileCommandComputer.java new file mode 100644 index 0000000000..8bbb2fca37 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/TileCommandComputer.java @@ -0,0 +1,182 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.blocks; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.computer.apis.CommandAPI; +import dan200.computercraft.shared.computer.core.IComputer; +import dan200.computercraft.shared.computer.core.ServerComputer; +import io.netty.buffer.ByteBuf; +import net.minecraft.block.state.IBlockState; +import net.minecraft.command.server.CommandBlockLogic; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.*; +import net.minecraft.world.World; + +import java.util.HashMap; +import java.util.Map; + +public class TileCommandComputer extends TileComputer +{ + public class CommandSender extends CommandBlockLogic + { + private Map m_outputTable; + + public CommandSender() + { + m_outputTable = new HashMap(); + } + + public void clearOutput() + { + m_outputTable.clear(); + } + + public Map getOutput() + { + return m_outputTable; + } + + public Map copyOutput() + { + return new HashMap( m_outputTable ); + } + + // ICommandSender + + @Override + public IChatComponent getDisplayName() + { + IComputer computer = TileCommandComputer.this.getComputer(); + if( computer != null ) + { + String label = computer.getLabel(); + if( label != null ) + { + return new ChatComponentText( computer.getLabel() ); + } + } + return new ChatComponentText( "@" ); + } + + @Override + public void addChatMessage( IChatComponent chatComponent ) + { + m_outputTable.put( m_outputTable.size() + 1, chatComponent.getUnformattedText() ); + } + + @Override + public boolean canCommandSenderUseCommand( int level, String command ) + { + return level <= 2; + } + + @Override + public BlockPos getPosition() + { + return TileCommandComputer.this.getPos(); + } + + @Override + public Vec3 getPositionVector() + { + BlockPos pos = getPosition(); + return new Vec3( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 ); + } + + @Override + public World getEntityWorld() + { + return TileCommandComputer.this.worldObj; + } + + @Override + public Entity getCommandSenderEntity() + { + return null; + } + + // CommandBlockLogic members intentionally left empty + // The only reason we extend it at all is so that "gameRule commandBlockOutput" applies to us + + @Override + public void updateCommand() + { + } + + @Override + public int func_145751_f() + { + return 0; + } + + @Override + public void func_145757_a( ByteBuf p_145757_1_ ) + { + } + } + + private CommandSender m_commandSender; + + public TileCommandComputer() + { + m_commandSender = new CommandSender(); + } + + @Override + public EnumFacing getDirection() + { + IBlockState state = getBlockState(); + return (EnumFacing)state.getValue( BlockCommandComputer.Properties.FACING ); + } + + @Override + public void setDirection( EnumFacing dir ) + { + if( dir.getAxis() == EnumFacing.Axis.Y ) + { + dir = EnumFacing.NORTH; + } + setBlockState( getBlockState().withProperty( BlockCommandComputer.Properties.FACING, dir ) ); + updateInput(); + } + + public CommandSender getCommandSender() + { + return m_commandSender; + } + + @Override + protected ServerComputer createComputer( int instanceID, int id ) + { + ServerComputer computer = super.createComputer( instanceID, id ); + computer.addAPI( new CommandAPI( this ) ); + return computer; + } + + @Override + public boolean isUsable( EntityPlayer player, boolean ignoreRange ) + { + MinecraftServer server = MinecraftServer.getServer(); + if( server == null || !server.isCommandBlockEnabled() ) + { + player.addChatMessage( new ChatComponentTranslation( "advMode.notEnabled" ) ); + return false; + } + else if( ComputerCraft.canPlayerUseCommands( player ) && player.capabilities.isCreativeMode ) + { + return super.isUsable( player, ignoreRange ); + } + else + { + player.addChatMessage( new ChatComponentTranslation( "advMode.notAllowed" ) ); + return false; + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputer.java b/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputer.java new file mode 100644 index 0000000000..9df410f56e --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputer.java @@ -0,0 +1,111 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.blocks; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.core.IComputer; +import dan200.computercraft.shared.computer.core.ServerComputer; +import dan200.computercraft.shared.computer.items.ComputerItemFactory; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumFacing; + +import java.util.List; + +public class TileComputer extends TileComputerBase +{ + // Statics + + // Members + + public TileComputer() + { + } + + @Override + protected ServerComputer createComputer( int instanceID, int id ) + { + ComputerFamily family = getFamily(); + ServerComputer computer = new ServerComputer( + worldObj, + id, + m_label, + instanceID, + family, + ComputerCraft.terminalWidth_computer, + ComputerCraft.terminalHeight_computer + ); + computer.setPosition( getPos() ); + return computer; + } + + @Override + public void getDroppedItems( List drops, int fortune, boolean creative, boolean silkTouch ) + { + IComputer computer = getComputer(); + if( !creative || (computer != null && computer.getLabel() != null) ) + { + drops.add( ComputerItemFactory.create( this ) ); + } + } + + @Override + public ItemStack getPickedItem() + { + return ComputerItemFactory.create( this ); + } + + @Override + public void openGUI( EntityPlayer player ) + { + ComputerCraft.openComputerGUI( player, this ); + } + + @Override + public final void readDescription( NBTTagCompound nbttagcompound ) + { + super.readDescription( nbttagcompound ); + updateBlock(); + } + + public boolean isUseableByPlayer( EntityPlayer player ) + { + return isUsable( player, false ); + } + + // IDirectionalTile + + @Override + public EnumFacing getDirection() + { + IBlockState state = getBlockState(); + return (EnumFacing)state.getValue( BlockComputer.Properties.FACING ); + } + + @Override + public void setDirection( EnumFacing dir ) + { + if( dir.getAxis() == EnumFacing.Axis.Y ) + { + dir = EnumFacing.NORTH; + } + setBlockState( getBlockState().withProperty( BlockComputer.Properties.FACING, dir ) ); + updateInput(); + } + + // For legacy reasons, computers invert the meaning of "left" and "right" + private static final int[] s_remapSide = { 0, 1, 2, 3, 5, 4 }; + + @Override + protected int remapLocalSide( int localSide ) + { + return s_remapSide[ localSide ]; + } +} diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java b/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java new file mode 100644 index 0000000000..6ab4efe424 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java @@ -0,0 +1,511 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.blocks; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.common.IDirectionalTile; +import dan200.computercraft.shared.common.ITerminal; +import dan200.computercraft.shared.common.TileGeneric; +import dan200.computercraft.shared.computer.core.ClientComputer; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.core.IComputer; +import dan200.computercraft.shared.computer.core.ServerComputer; +import dan200.computercraft.shared.util.DirectionUtil; +import dan200.computercraft.shared.util.PeripheralUtil; +import dan200.computercraft.shared.util.RedstoneUtil; +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ITickable; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; + +public abstract class TileComputerBase extends TileGeneric + implements IComputerTile, IDirectionalTile, ITickable +{ + protected int m_instanceID; + protected int m_computerID; + protected String m_label; + protected boolean m_on; + protected boolean m_startOn; + + protected TileComputerBase() + { + m_instanceID = -1; + m_computerID = -1; + m_label = null; + m_on = false; + m_startOn = false; + } + + @Override + public BlockComputerBase getBlock() + { + Block block = super.getBlock(); + if( block != null && block instanceof BlockComputerBase ) + { + return (BlockComputerBase)block; + } + return null; + } + + protected void unload() + { + if( m_instanceID >= 0 ) + { + if( !worldObj.isRemote ) + { + ComputerCraft.serverComputerRegistry.remove( m_instanceID ); + } + m_instanceID = -1; + } + } + + @Override + public void destroy() + { + unload(); + for( EnumFacing dir : EnumFacing.VALUES ) + { + RedstoneUtil.propogateRedstoneOutput( worldObj, getPos(), dir ); + } + } + + @Override + public void onChunkUnload() + { + unload(); + } + + @Override + public void invalidate() + { + unload(); + super.invalidate(); + } + + public abstract void openGUI( EntityPlayer player ); + + protected boolean canNameWithTag( EntityPlayer player ) + { + return false; + } + + protected boolean onDefaultComputerInteract( EntityPlayer player ) + { + if( !worldObj.isRemote ) + { + if( isUsable( player, false ) ) + { + createServerComputer().turnOn(); + openGUI( player ); + } + } + return true; + } + + @Override + public boolean onActivate( EntityPlayer player, EnumFacing side, float hitX, float hitY, float hitZ ) + { + ItemStack currentItem = player.getCurrentEquippedItem(); + if( currentItem != null && currentItem.getItem() == Items.name_tag && canNameWithTag( player ) ) + { + // Label to rename computer + if( !worldObj.isRemote ) + { + if( currentItem.hasDisplayName() ) + { + setLabel( currentItem.getDisplayName() ); + } + else + { + setLabel( null ); + } + currentItem.stackSize--; + } + return true; + } + else if( !player.isSneaking() ) + { + // Regular right click to activate computer + return onDefaultComputerInteract( player ); + } + return false; + } + + @Override + public boolean getRedstoneConnectivity( EnumFacing side ) + { + int localDir = remapLocalSide( DirectionUtil.toLocal( this, side ) ); + return !isRedstoneBlockedOnSide( localDir ); + } + + @Override + public int getRedstoneOutput( EnumFacing side ) + { + int localDir = remapLocalSide( DirectionUtil.toLocal( this, side ) ); + if( !isRedstoneBlockedOnSide( localDir ) ) + { + if( worldObj != null && !worldObj.isRemote ) + { + ServerComputer computer = getServerComputer(); + if( computer != null ) + { + return computer.getRedstoneOutput( localDir ); + } + } + } + return 0; + } + + @Override + public boolean getBundledRedstoneConnectivity( EnumFacing side ) + { + int localDir = remapLocalSide( DirectionUtil.toLocal( this, side ) ); + return !isRedstoneBlockedOnSide( localDir ); + } + + @Override + public int getBundledRedstoneOutput( EnumFacing side ) + { + int localDir = remapLocalSide( DirectionUtil.toLocal( this, side ) ); + if( !isRedstoneBlockedOnSide( localDir ) ) + { + if( !worldObj.isRemote ) + { + ServerComputer computer = getServerComputer(); + if( computer != null ) + { + return computer.getBundledRedstoneOutput( localDir ); + } + } + } + return 0; + } + + @Override + public void onNeighbourChange() + { + updateInput(); + } + + @Override + public void update() + { + if( !worldObj.isRemote ) + { + ServerComputer computer = createServerComputer(); + if( computer != null ) + { + if( m_startOn ) + { + computer.turnOn(); + m_startOn = false; + } + computer.keepAlive(); + if( computer.hasOutputChanged() ) + { + updateOutput(); + } + m_computerID = computer.getID(); + m_label = computer.getLabel(); + m_on = computer.isOn(); + } + } + else + { + ClientComputer computer = createClientComputer(); + if( computer != null ) + { + if( computer.hasOutputChanged() ) + { + updateBlock(); + } + } + } + } + + @Override + public void writeToNBT( NBTTagCompound nbttagcompound ) + { + super.writeToNBT( nbttagcompound ); + + // Save ID, label and power state + if( m_computerID >= 0 ) + { + nbttagcompound.setInteger( "computerID", m_computerID ); + } + if( m_label != null ) + { + nbttagcompound.setString( "label", m_label ); + } + nbttagcompound.setBoolean( "on", m_on ); + } + + @Override + public void readFromNBT( NBTTagCompound nbttagcompound ) + { + super.readFromNBT( nbttagcompound ); + + // Load ID + int id = -1; + if( nbttagcompound.hasKey( "computerID" ) ) + { + // Post-1.6 computers + id = nbttagcompound.getInteger( "computerID" ); + } + else if( nbttagcompound.hasKey( "userDir" ) ) + { + // Pre-1.6 computers + String userDir = nbttagcompound.getString( "userDir" ); + try + { + id = Integer.parseInt( userDir ); + } + catch( NumberFormatException e ) + { + // Ignore badly formatted data + } + } + m_computerID = id; + + // Load label + if( nbttagcompound.hasKey( "label" ) ) + { + m_label = nbttagcompound.getString( "label" ); + } + else + { + m_label = null; + } + + // Load power state + m_startOn = nbttagcompound.getBoolean( "on" ); + m_on = m_startOn; + } + + protected boolean isPeripheralBlockedOnSide( int localSide ) + { + return false; + } + + protected boolean isRedstoneBlockedOnSide( int localSide ) + { + return false; + } + + protected int remapLocalSide( int localSide ) + { + return localSide; + } + + public void updateInput() + { + if( worldObj == null || worldObj.isRemote ) + { + return; + } + + // Update redstone and peripherals + ServerComputer computer = getServerComputer(); + if( computer != null ) + { + BlockPos pos = computer.getPosition(); + for( EnumFacing dir : EnumFacing.VALUES ) + { + BlockPos offset = pos.offset( dir ); + EnumFacing offsetSide = dir.getOpposite(); + int localDir = remapLocalSide( DirectionUtil.toLocal( this, dir ) ); + if( !isRedstoneBlockedOnSide( localDir ) ) + { + computer.setRedstoneInput( localDir, RedstoneUtil.getRedstoneOutput( worldObj, offset, offsetSide ) ); + computer.setBundledRedstoneInput( localDir, RedstoneUtil.getBundledRedstoneOutput( worldObj, offset, offsetSide ) ); + } + if( !isPeripheralBlockedOnSide( localDir ) ) + { + computer.setPeripheral( localDir, PeripheralUtil.getPeripheral( worldObj, offset, offsetSide ) ); + } + } + } + } + + public void updateOutput() + { + // Update redstone + updateBlock(); + for( EnumFacing dir : EnumFacing.VALUES ) + { + RedstoneUtil.propogateRedstoneOutput( worldObj, getPos(), dir ); + } + } + + protected abstract ServerComputer createComputer( int instanceID, int id ); + + // ITerminalTile + + @Override + public ITerminal getTerminal() + { + return getComputer(); + } + + // IComputerTile + + @Override + public void setComputerID( int id ) + { + if( !worldObj.isRemote && m_computerID != id ) + { + m_computerID = id; + ServerComputer computer = getServerComputer(); + if( computer != null ) + { + computer.setID( m_computerID ); + } + markDirty(); + } + } + + @Override + public void setLabel( String label ) + { + if( !worldObj.isRemote ) + { + createServerComputer().setLabel( label ); + } + } + + @Override + public IComputer createComputer() + { + if( worldObj.isRemote ) + { + return createClientComputer(); + } + else + { + return createServerComputer(); + } + } + + @Override + public IComputer getComputer() + { + if( worldObj.isRemote ) + { + return getClientComputer(); + } + else + { + return getServerComputer(); + } + } + + @Override + public ComputerFamily getFamily() + { + BlockComputerBase block = getBlock(); + if( block != null ) + { + return block.getFamily( worldObj, getPos() ); + } + return ComputerFamily.Normal; + } + + public ServerComputer createServerComputer() + { + if( !worldObj.isRemote ) + { + boolean changed = false; + if( m_instanceID < 0 ) + { + m_instanceID = ComputerCraft.serverComputerRegistry.getUnusedInstanceID(); + changed = true; + } + if( !ComputerCraft.serverComputerRegistry.contains( m_instanceID ) ) + { + ServerComputer computer = createComputer( m_instanceID, m_computerID ); + ComputerCraft.serverComputerRegistry.add( m_instanceID, computer ); + changed = true; + } + if( changed ) + { + updateBlock(); + updateInput(); + } + return ComputerCraft.serverComputerRegistry.get( m_instanceID ); + } + return null; + } + + public ServerComputer getServerComputer() + { + if( !worldObj.isRemote ) + { + return ComputerCraft.serverComputerRegistry.get( m_instanceID ); + } + return null; + } + + public ClientComputer createClientComputer() + { + if( worldObj.isRemote ) + { + if( m_instanceID >= 0 ) + { + if( !ComputerCraft.clientComputerRegistry.contains( m_instanceID ) ) + { + ComputerCraft.clientComputerRegistry.add( m_instanceID, new ClientComputer( m_instanceID ) ); + } + return ComputerCraft.clientComputerRegistry.get( m_instanceID ); + } + } + return null; + } + + public ClientComputer getClientComputer() + { + if( worldObj.isRemote ) + { + return ComputerCraft.clientComputerRegistry.get( m_instanceID ); + } + return null; + } + + // Networking stuff + + @Override + public void writeDescription( NBTTagCompound nbttagcompound ) + { + super.writeDescription( nbttagcompound ); + nbttagcompound.setInteger( "instanceID", createServerComputer().getInstanceID() ); + } + + @Override + public void readDescription( NBTTagCompound nbttagcompound ) + { + super.readDescription( nbttagcompound ); + m_instanceID = nbttagcompound.getInteger( "instanceID" ); + } + + protected void transferStateFrom( TileComputerBase copy ) + { + if( copy.m_computerID != m_computerID || copy.m_instanceID != m_instanceID ) + { + unload(); + m_instanceID = copy.m_instanceID; + m_computerID = copy.m_computerID; + m_label = copy.m_label; + m_on = copy.m_on; + m_startOn = copy.m_startOn; + updateBlock(); + } + copy.m_instanceID = -1; + } +} diff --git a/src/main/java/dan200/computercraft/shared/computer/core/ClientComputer.java b/src/main/java/dan200/computercraft/shared/computer/core/ClientComputer.java new file mode 100644 index 0000000000..812f0c204c --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/core/ClientComputer.java @@ -0,0 +1,197 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.core; + +import com.google.common.base.Objects; +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.common.ClientTerminal; +import dan200.computercraft.shared.network.ComputerCraftPacket; +import dan200.computercraft.shared.network.INetworkedThing; +import dan200.computercraft.shared.util.NBTUtil; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; + +public class ClientComputer extends ClientTerminal + implements IComputer, INetworkedThing +{ + private final int m_instanceID; + + private int m_computerID; + private String m_label; + private boolean m_on; + private boolean m_blinking; + private boolean m_changed; + private NBTTagCompound m_userData; + + private boolean m_changedLastFrame; + + public ClientComputer( int instanceID ) + { + super( false ); + m_instanceID = instanceID; + + m_computerID = -1; + m_label = null; + m_on = false; + m_blinking = false; + m_changed = true; + m_userData = null; + m_changedLastFrame = false; + } + + @Override + public void update() + { + super.update(); + m_changedLastFrame = m_changed; + m_changed = false; + } + + public boolean hasOutputChanged() + { + return m_changedLastFrame; + } + + public NBTTagCompound getUserData() + { + return m_userData; + } + + public void requestState() + { + // Request state from server + ComputerCraftPacket packet = new ComputerCraftPacket(); + packet.m_packetType = ComputerCraftPacket.RequestComputerUpdate; + packet.m_dataInt = new int[] { getInstanceID() }; + ComputerCraft.sendToServer( packet ); + } + + // IComputer + + @Override + public int getInstanceID() + { + return m_instanceID; + } + + @Override + public int getID() + { + return m_computerID; + } + + @Override + public String getLabel() + { + return m_label; + } + + @Override + public boolean isOn() + { + return m_on; + } + + @Override + public boolean isCursorDisplayed() + { + return m_on && m_blinking; + } + + @Override + public void turnOn() + { + // Send turnOn to server + ComputerCraftPacket packet = new ComputerCraftPacket(); + packet.m_packetType = ComputerCraftPacket.TurnOn; + packet.m_dataInt = new int[] { m_instanceID }; + ComputerCraft.sendToServer( packet ); + } + + @Override + public void shutdown() + { + // Send shutdown to server + ComputerCraftPacket packet = new ComputerCraftPacket(); + packet.m_packetType = ComputerCraftPacket.Shutdown; + packet.m_dataInt = new int[] { m_instanceID }; + ComputerCraft.sendToServer( packet ); + } + + @Override + public void reboot() + { + // Send reboot to server + ComputerCraftPacket packet = new ComputerCraftPacket(); + packet.m_packetType = ComputerCraftPacket.Reboot; + packet.m_dataInt = new int[] { m_instanceID }; + ComputerCraft.sendToServer( packet ); + } + + @Override + public void queueEvent( String event ) + { + queueEvent( event, null ); + } + + @Override + public void queueEvent( String event, Object[] arguments ) + { + // Send event to server + ComputerCraftPacket packet = new ComputerCraftPacket(); + packet.m_packetType = ComputerCraftPacket.QueueEvent; + packet.m_dataInt = new int[] { m_instanceID }; + packet.m_dataString = new String[] { event }; + if( arguments != null ) + { + packet.m_dataNBT = NBTUtil.encodeObjects( arguments ); + } + ComputerCraft.sendToServer( packet ); + } + + public void readDescription( NBTTagCompound nbttagcompound ) + { + super.readDescription( nbttagcompound ); + + int oldID = m_computerID; + String oldLabel = m_label; + boolean oldOn = m_on; + boolean oldBlinking = m_blinking; + NBTTagCompound oldUserData = m_userData; + + m_computerID = nbttagcompound.getInteger( "id" ); + m_label = nbttagcompound.hasKey( "label" ) ? nbttagcompound.getString( "label" ) : null; + m_on = nbttagcompound.getBoolean( "on" ); + m_blinking = nbttagcompound.getBoolean( "blinking" ); + if( nbttagcompound.hasKey( "userData" ) ) + { + m_userData = (NBTTagCompound)(nbttagcompound.getCompoundTag( "userData" )).copy(); + } + else + { + m_userData = null; + } + + if( m_computerID != oldID || m_on != oldOn || m_blinking != oldBlinking || !Objects.equal( m_label, oldLabel ) || !Objects.equal( m_userData, oldUserData ) ) + { + m_changed = true; + } + } + + @Override + public void handlePacket( ComputerCraftPacket packet, EntityPlayer sender ) + { + switch( packet.m_packetType ) + { + case ComputerCraftPacket.ComputerChanged: + { + readDescription( packet.m_dataNBT ); + break; + } + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/computer/core/ClientComputerRegistry.java b/src/main/java/dan200/computercraft/shared/computer/core/ClientComputerRegistry.java new file mode 100644 index 0000000000..1b009eb4db --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/core/ClientComputerRegistry.java @@ -0,0 +1,47 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.core; + +public class ClientComputerRegistry extends ComputerRegistry +{ + public ClientComputerRegistry() + { + } + + public void update() + { + for( ClientComputer computer : getComputers() ) + { + computer.update(); + } + } + + @Override + public void add( int instanceID, ClientComputer computer ) + { + //System.out.println( "ADD CLIENT COMPUTER " + instanceID ); + super.add( instanceID, computer ); + computer.requestState(); + //System.out.println( getComputers().size() + " CLIENT COMPUTERS" ); + } + + @Override + public void remove( int instanceID ) + { + //System.out.println( "REMOVE CLIENT COMPUTER " + instanceID ); + super.remove( instanceID ); + //System.out.println( getComputers().size() + " CLIENT COMPUTERS" ); + } + + @Override + public void reset() + { + //System.out.println( "RESET CLIENT COMPUTERS" ); + super.reset(); + //System.out.println( getComputers().size() + " CLIENT COMPUTERS" ); + } +} diff --git a/src/main/java/dan200/computercraft/shared/computer/core/ComputerFamily.java b/src/main/java/dan200/computercraft/shared/computer/core/ComputerFamily.java new file mode 100644 index 0000000000..c57b306891 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/core/ComputerFamily.java @@ -0,0 +1,15 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.core; + +public enum ComputerFamily +{ + Normal, + Advanced, + Beginners, + Command +} diff --git a/src/main/java/dan200/computercraft/shared/computer/core/ComputerRegistry.java b/src/main/java/dan200/computercraft/shared/computer/core/ComputerRegistry.java new file mode 100644 index 0000000000..d8e500805c --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/core/ComputerRegistry.java @@ -0,0 +1,97 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.core; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +public class ComputerRegistry +{ + private Map m_computers; + private int m_nextUnusedInstanceID; + private int m_sessionID; + + protected ComputerRegistry() + { + m_computers = new HashMap(); + reset(); + } + + public int getSessionID() + { + return m_sessionID; + } + + public int getUnusedInstanceID() + { + return m_nextUnusedInstanceID++; + } + + public Collection getComputers() + { + return m_computers.values(); + } + + public TComputer get( int instanceID ) + { + if( instanceID >= 0 ) + { + if( m_computers.containsKey( instanceID ) ) + { + return m_computers.get( instanceID ); + } + } + return null; + } + + public TComputer lookup( int computerID ) + { + if( computerID >= 0 ) + { + for( TComputer computer : getComputers() ) + { + if( computer.getID() == computerID ) + { + return computer; + } + } + } + return null; + } + + public boolean contains( int instanceID ) + { + return m_computers.containsKey( instanceID ); + } + + public void add( int instanceID, TComputer computer ) + { + if( m_computers.containsKey( instanceID ) ) + { + remove( instanceID ); + } + m_computers.put( instanceID, computer ); + m_nextUnusedInstanceID = Math.max( m_nextUnusedInstanceID, instanceID + 1 ); + } + + public void remove( int instanceID ) + { + if( m_computers.containsKey( instanceID ) ) + { + m_computers.remove( instanceID ); + } + } + + public void reset() + { + m_computers.clear(); + m_nextUnusedInstanceID = 0; + m_sessionID = (new Random().nextInt()); + } +} diff --git a/src/main/java/dan200/computercraft/shared/computer/core/IComputer.java b/src/main/java/dan200/computercraft/shared/computer/core/IComputer.java new file mode 100644 index 0000000000..dfc5718c9e --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/core/IComputer.java @@ -0,0 +1,25 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.core; + +import dan200.computercraft.shared.common.ITerminal; + +public interface IComputer extends ITerminal +{ + public int getInstanceID(); + public int getID(); + public String getLabel(); + + public boolean isOn(); + public boolean isCursorDisplayed(); + public void turnOn(); + public void shutdown(); + public void reboot(); + + public void queueEvent( String event ); + public void queueEvent( String event, Object[] arguments ); +} diff --git a/src/main/java/dan200/computercraft/shared/computer/core/IComputerContainer.java b/src/main/java/dan200/computercraft/shared/computer/core/IComputerContainer.java new file mode 100644 index 0000000000..28ed13e33b --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/core/IComputerContainer.java @@ -0,0 +1,12 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.core; + +public interface IComputerContainer +{ + public IComputer getComputer(); +} diff --git a/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java b/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java new file mode 100644 index 0000000000..0e0eff95c4 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java @@ -0,0 +1,402 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.core; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.ComputerCraftAPI; +import dan200.computercraft.api.filesystem.IMount; +import dan200.computercraft.api.filesystem.IWritableMount; +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.core.apis.IAPIEnvironment; +import dan200.computercraft.core.apis.ILuaAPI; +import dan200.computercraft.core.computer.Computer; +import dan200.computercraft.core.computer.IComputerEnvironment; +import dan200.computercraft.shared.common.ServerTerminal; +import dan200.computercraft.shared.network.ComputerCraftPacket; +import dan200.computercraft.shared.network.INetworkedThing; +import dan200.computercraft.shared.util.NBTUtil; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.Loader; + +public class ServerComputer extends ServerTerminal + implements IComputer, IComputerEnvironment, INetworkedThing +{ + private final int m_instanceID; + + private World m_world; + private BlockPos m_position; + + private final Computer m_computer; + private NBTTagCompound m_userData; + private boolean m_changed; + + private boolean m_changedLastFrame; + private int m_ticksSincePing; + + public ServerComputer( World world, int computerID, String label, int instanceID, ComputerFamily family, int terminalWidth, int terminalHeight ) + { + super( family != ComputerFamily.Normal, terminalWidth, terminalHeight ); + m_instanceID = instanceID; + + m_world = world; + m_position = null; + + m_computer = new Computer( this, getTerminal(), computerID ); + m_computer.setLabel( label ); + m_userData = null; + m_changed = false; + + m_changedLastFrame = false; + m_ticksSincePing = 0; + } + + public World getWorld() + { + return m_world; + } + + public void setWorld( World world ) + { + m_world = world; + } + + public BlockPos getPosition() + { + return m_position; + } + + public void setPosition( BlockPos pos ) + { + m_position = new BlockPos( pos ); + } + + public IAPIEnvironment getAPIEnvironment() + { + return m_computer.getAPIEnvironment(); + } + + @Override + public void update() + { + super.update(); + m_computer.advance( 0.05 ); + + m_changedLastFrame = m_changed || m_computer.pollChanged(); + m_computer.clearChanged(); + m_changed = false; + + m_ticksSincePing++; + } + + public void keepAlive() + { + m_ticksSincePing = 0; + } + + public boolean hasTimedOut() + { + return m_ticksSincePing > 100; + } + + public boolean hasOutputChanged() + { + return m_changedLastFrame; + } + + public void unload() + { + m_computer.unload(); + } + + public NBTTagCompound getUserData() + { + if( m_userData == null ) + { + m_userData = new NBTTagCompound(); + } + return m_userData; + } + + public void updateUserData() + { + m_changed = true; + } + + public void broadcastState() + { + // Send state to client + ComputerCraftPacket packet = new ComputerCraftPacket(); + packet.m_packetType = ComputerCraftPacket.ComputerChanged; + packet.m_dataInt = new int[] { getInstanceID() }; + packet.m_dataNBT = new NBTTagCompound(); + writeDescription( packet.m_dataNBT ); + ComputerCraft.sendToAllPlayers( packet ); + } + + public void sendState( EntityPlayer player ) + { + // Send state to client + ComputerCraftPacket packet = new ComputerCraftPacket(); + packet.m_packetType = ComputerCraftPacket.ComputerChanged; + packet.m_dataInt = new int[] { getInstanceID() }; + packet.m_dataNBT = new NBTTagCompound(); + writeDescription( packet.m_dataNBT ); + ComputerCraft.sendToPlayer( player, packet ); + } + + public void broadcastDelete() + { + // Send deletion to client + ComputerCraftPacket packet = new ComputerCraftPacket(); + packet.m_packetType = ComputerCraftPacket.ComputerDeleted; + packet.m_dataInt = new int[] { getInstanceID() }; + ComputerCraft.sendToAllPlayers( packet ); + } + + public IWritableMount getRootMount() + { + return m_computer.getRootMount(); + } + + public int assignID() + { + return m_computer.assignID(); + } + + public void setID( int id ) + { + m_computer.setID( id ); + } + + // IComputer + + @Override + public int getInstanceID() + { + return m_instanceID; + } + + @Override + public int getID() + { + return m_computer.getID(); + } + + @Override + public String getLabel() + { + return m_computer.getLabel(); + } + + @Override + public boolean isOn() + { + return m_computer.isOn(); + } + + @Override + public boolean isCursorDisplayed() + { + return m_computer.isOn() && m_computer.isBlinking(); + } + + @Override + public void turnOn() + { + // Turn on + m_computer.turnOn(); + } + + @Override + public void shutdown() + { + // Shutdown + m_computer.shutdown(); + } + + @Override + public void reboot() + { + // Reboot + m_computer.reboot(); + } + + @Override + public void queueEvent( String event ) + { + // Queue event + queueEvent( event, null ); + } + + @Override + public void queueEvent( String event, Object[] arguments ) + { + // Queue event + m_computer.queueEvent( event, arguments ); + } + + public int getRedstoneOutput( int side ) + { + return m_computer.getRedstoneOutput( side ); + } + + public void setRedstoneInput( int side, int level ) + { + m_computer.setRedstoneInput( side, level ); + } + + public int getBundledRedstoneOutput( int side ) + { + return m_computer.getBundledRedstoneOutput( side ); + } + + public void setBundledRedstoneInput( int side, int combination ) + { + m_computer.setBundledRedstoneInput( side, combination ); + } + + public void addAPI( ILuaAPI api ) + { + m_computer.addAPI( api ); + } + + public void setPeripheral( int side, IPeripheral peripheral ) + { + m_computer.setPeripheral( side, peripheral ); + } + + public IPeripheral getPeripheral( int side ) + { + return m_computer.getPeripheral( side ); + } + + public void setLabel( String label ) + { + m_computer.setLabel( label ); + } + + // IComputerEnvironment implementation + + @Override + public double getTimeOfDay() + { + return (double)((m_world.getWorldTime() + 6000) % 24000) / 1000.0; + } + + @Override + public int getDay() + { + return (int)((m_world.getWorldTime() + 6000) / 24000) + 1; + } + + @Override + public IWritableMount createSaveDirMount( String subPath, long capacity ) + { + return ComputerCraftAPI.createSaveDirMount( m_world, subPath, capacity ); + } + + @Override + public IMount createResourceMount( String domain, String subPath ) + { + return ComputerCraftAPI.createResourceMount( ComputerCraft.class, domain, subPath ); + } + + @Override + public long getComputerSpaceLimit() + { + return ComputerCraft.computerSpaceLimit; + } + + @Override + public String getHostString() + { + return "ComputerCraft ${version} (Minecraft " + Loader.MC_VERSION + ")"; + } + + @Override + public int assignNewID() + { + return ComputerCraft.createUniqueNumberedSaveDir( m_world, "computer" ); + } + + // Networking stuff + + public void writeDescription( NBTTagCompound nbttagcompound ) + { + super.writeDescription( nbttagcompound ); + + nbttagcompound.setInteger( "id", m_computer.getID() ); + String label = m_computer.getLabel(); + if( label != null ) + { + nbttagcompound.setString( "label", label ); + } + nbttagcompound.setBoolean( "on", m_computer.isOn() ); + nbttagcompound.setBoolean( "blinking", m_computer.isBlinking() ); + if( m_userData != null ) + { + nbttagcompound.setTag( "userData", m_userData.copy() ); + } + } + + // INetworkedThing + + @Override + public void handlePacket( ComputerCraftPacket packet, EntityPlayer sender ) + { + // Receive packets sent from the client to the server + switch( packet.m_packetType ) + { + case ComputerCraftPacket.TurnOn: + { + // A player has turned the computer on + turnOn(); + break; + } + case ComputerCraftPacket.Reboot: + { + // A player has held down ctrl+r + reboot(); + break; + } + case ComputerCraftPacket.Shutdown: + { + // A player has held down ctrl+s + shutdown(); + break; + } + case ComputerCraftPacket.QueueEvent: + { + // A player has caused a UI event to be fired + String event = packet.m_dataString[0]; + Object[] arguments = null; + if( packet.m_dataNBT != null ) + { + arguments = NBTUtil.decodeObjects( packet.m_dataNBT ); + } + queueEvent( event, arguments ); + break; + } + case ComputerCraftPacket.SetLabel: + { + // A player wants to relabel a computer + String label = (packet.m_dataString != null && packet.m_dataString.length >= 1) ? packet.m_dataString[0] : null; + setLabel( label ); + break; + } + case ComputerCraftPacket.RequestComputerUpdate: + { + // A player asked for an update on the state of the terminal + sendState( sender ); + break; + } + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/computer/core/ServerComputerRegistry.java b/src/main/java/dan200/computercraft/shared/computer/core/ServerComputerRegistry.java new file mode 100644 index 0000000000..131add5f46 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/core/ServerComputerRegistry.java @@ -0,0 +1,76 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.core; + +import java.util.Iterator; + +public class ServerComputerRegistry extends ComputerRegistry +{ + public ServerComputerRegistry() + { + } + + public void update() + { + Iterator it = getComputers().iterator(); + while( it.hasNext() ) + { + ServerComputer computer = it.next(); + if( computer.hasTimedOut() ) + { + //System.out.println( "TIMED OUT SERVER COMPUTER " + computer.getInstanceID() ); + computer.unload(); + computer.broadcastDelete(); + it.remove(); + //System.out.println( getComputers().size() + " SERVER COMPUTERS" ); + } + else + { + computer.update(); + if( computer.hasTerminalChanged() || computer.hasOutputChanged() ) + { + computer.broadcastState(); + } + } + } + } + + @Override + public void add( int instanceID, ServerComputer computer ) + { + //System.out.println( "ADD SERVER COMPUTER " + instanceID ); + super.add( instanceID, computer ); + computer.broadcastState(); + //System.out.println( getComputers().size() + " SERVER COMPUTERS" ); + } + + @Override + public void remove( int instanceID ) + { + //System.out.println( "REMOVE SERVER COMPUTER " + instanceID ); + ServerComputer computer = get( instanceID ); + if( computer != null ) + { + computer.unload(); + computer.broadcastDelete(); + } + super.remove( instanceID ); + //System.out.println( getComputers().size() + " SERVER COMPUTERS" ); + } + + @Override + public void reset() + { + //System.out.println( "RESET SERVER COMPUTERS" ); + for( ServerComputer computer : getComputers() ) + { + computer.unload(); + } + super.reset(); + //System.out.println( getComputers().size() + " SERVER COMPUTERS" ); + } +} diff --git a/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputer.java b/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputer.java new file mode 100644 index 0000000000..76988d9643 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputer.java @@ -0,0 +1,27 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.inventory; + +import dan200.computercraft.shared.computer.blocks.TileComputer; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Container; + +public class ContainerComputer extends Container +{ + private TileComputer m_computer; + + public ContainerComputer( TileComputer computer ) + { + m_computer = computer; + } + + @Override + public boolean canInteractWith( EntityPlayer player ) + { + return m_computer.isUseableByPlayer( player ); + } +} diff --git a/src/main/java/dan200/computercraft/shared/computer/items/ComputerItemFactory.java b/src/main/java/dan200/computercraft/shared/computer/items/ComputerItemFactory.java new file mode 100644 index 0000000000..ea7b0d2847 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/items/ComputerItemFactory.java @@ -0,0 +1,51 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.items; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.computer.blocks.IComputerTile; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.core.IComputer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +public class ComputerItemFactory +{ + public static ItemStack create( IComputerTile computerTile ) + { + IComputer computer = computerTile.getComputer(); + if( computer != null ) + { + String label = computer.getLabel(); + int id = (label != null) ? computer.getID() : -1; + return create( id, label, computerTile.getFamily() ); + } + else + { + return create( -1, null, computerTile.getFamily() ); + } + } + + public static ItemStack create( int id, String label, ComputerFamily family ) + { + ItemComputer computer = ((ItemComputer)Item.getItemFromBlock( ComputerCraft.Blocks.computer )); + ItemCommandComputer commandComputer = ((ItemCommandComputer)Item.getItemFromBlock( ComputerCraft.Blocks.commandComputer )); + switch( family ) + { + case Normal: + case Advanced: + { + return computer.create( id, label, family ); + } + case Command: + { + return commandComputer.create( id, label, family ); + } + } + return null; + } +} diff --git a/src/main/java/dan200/computercraft/shared/computer/items/IComputerItem.java b/src/main/java/dan200/computercraft/shared/computer/items/IComputerItem.java new file mode 100644 index 0000000000..4ca1bae032 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/items/IComputerItem.java @@ -0,0 +1,17 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.items; + +import dan200.computercraft.shared.computer.core.ComputerFamily; +import net.minecraft.item.ItemStack; + +public interface IComputerItem +{ + public int getComputerID( ItemStack stack ); + public String getLabel( ItemStack stack ); + public ComputerFamily getFamily( ItemStack stack ); +} diff --git a/src/main/java/dan200/computercraft/shared/computer/items/ItemCommandComputer.java b/src/main/java/dan200/computercraft/shared/computer/items/ItemCommandComputer.java new file mode 100644 index 0000000000..bfe63c3282 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/items/ItemCommandComputer.java @@ -0,0 +1,76 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.items; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import net.minecraft.block.Block; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import java.util.List; + +public class ItemCommandComputer extends ItemComputer +{ + public ItemCommandComputer( Block block ) + { + super( block ); + setMaxStackSize( 64 ); + setHasSubtypes( true ); + setUnlocalizedName( "computercraft:command_computer" ); + setCreativeTab( ComputerCraft.mainCreativeTab ); + } + + public ItemStack create( int id, String label, ComputerFamily family ) + { + // Ignore types we can't handle + if( family != ComputerFamily.Command ) + { + return null; + } + + // Build the stack + ItemStack result = new ItemStack( this, 1, 0 ); + + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setInteger( "computerID", id ); + result.setTagCompound( nbt ); + + if( label != null ) + { + result.setStackDisplayName( label ); + } + + return result; + } + + @Override + public void getSubItems( Item itemID, CreativeTabs tabs, List list ) + { + list.add( ComputerItemFactory.create( -1, null, ComputerFamily.Command ) ); + } + + // IComputerItem implementation + + @Override + public int getComputerID( ItemStack stack ) + { + if( stack.hasTagCompound() && stack.getTagCompound().hasKey( "computerID" ) ) + { + return stack.getTagCompound().getInteger( "computerID" ); + } + return -1; + } + + @Override + public ComputerFamily getFamily( int damage ) + { + return ComputerFamily.Command; + } +} diff --git a/src/main/java/dan200/computercraft/shared/computer/items/ItemComputer.java b/src/main/java/dan200/computercraft/shared/computer/items/ItemComputer.java new file mode 100644 index 0000000000..42b0056ab7 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/items/ItemComputer.java @@ -0,0 +1,159 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.items; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.computer.blocks.IComputerTile; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +import java.util.List; + +public class ItemComputer extends ItemComputerBase +{ + public static int HIGHEST_DAMAGE_VALUE_ID = 16382; + + public ItemComputer( Block block ) + { + super( block ); + setMaxStackSize( 64 ); + setHasSubtypes( true ); + setUnlocalizedName( "computercraft:computer" ); + setCreativeTab( ComputerCraft.mainCreativeTab ); + } + + public ItemStack create( int id, String label, ComputerFamily family ) + { + // Ignore types we can't handle + if( family != ComputerFamily.Normal && family != ComputerFamily.Advanced ) + { + return null; + } + + // Build the damage + int damage = 0; + if( id >= 0 && id <= ItemComputer.HIGHEST_DAMAGE_VALUE_ID ) + { + damage = id + 1; + } + if( family == ComputerFamily.Advanced ) + { + damage += 0x4000; + } + + // Return the stack + ItemStack result = new ItemStack( this, 1, damage ); + if( id > ItemComputer.HIGHEST_DAMAGE_VALUE_ID ) + { + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setInteger( "computerID", id ); + result.setTagCompound( nbt ); + } + if( label != null ) + { + result.setStackDisplayName( label ); + } + return result; + } + + @Override + public void getSubItems( Item itemID, CreativeTabs tabs, List list ) + { + list.add( ComputerItemFactory.create( -1, null, ComputerFamily.Normal ) ); + list.add( ComputerItemFactory.create( -1, null, ComputerFamily.Advanced ) ); + } + + @Override + public boolean placeBlockAt( ItemStack stack, EntityPlayer player, World world, BlockPos pos, EnumFacing side, float hitX, float hitY, float hitZ, IBlockState newState ) + { + if( super.placeBlockAt( stack, player, world, pos, side, hitX, hitY, hitZ, newState ) ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof IComputerTile ) + { + IComputerTile computer = (IComputerTile)tile; + setupComputerAfterPlacement( stack, computer ); + } + return true; + } + return false; + } + + private void setupComputerAfterPlacement( ItemStack stack, IComputerTile computer ) + { + // Set ID + int id = getComputerID( stack ); + if( id >= 0 ) + { + computer.setComputerID( id ); + } + + // Set Label + String label = getLabel( stack ); + if( label != null ) + { + computer.setLabel( label ); + } + } + + @Override + public String getUnlocalizedName( ItemStack stack ) + { + switch( getFamily( stack ) ) + { + case Normal: + default: + { + return "tile.computercraft:computer"; + } + case Advanced: + { + return "tile.computercraft:advanced_computer"; + } + case Command: + { + return "tile.computercraft:command_computer"; + } + } + } + + // IComputerItem implementation + + @Override + public int getComputerID( ItemStack stack ) + { + if( stack.hasTagCompound() && stack.getTagCompound().hasKey( "computerID" ) ) + { + return stack.getTagCompound().getInteger( "computerID" ); + } + else + { + int damage = stack.getItemDamage() & 0x3fff; + return ( damage - 1 ); + } + } + + @Override + public ComputerFamily getFamily( int damage ) + { + if( (damage & 0x4000) != 0 ) + { + return ComputerFamily.Advanced; + } + return ComputerFamily.Normal; + } +} diff --git a/src/main/java/dan200/computercraft/shared/computer/items/ItemComputerBase.java b/src/main/java/dan200/computercraft/shared/computer/items/ItemComputerBase.java new file mode 100644 index 0000000000..fef975efcb --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/items/ItemComputerBase.java @@ -0,0 +1,114 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.computer.items; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.filesystem.IMount; +import dan200.computercraft.api.media.IMedia; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.core.ServerComputer; +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; + +import java.util.List; + +public abstract class ItemComputerBase extends ItemBlock implements IComputerItem, IMedia +{ + protected ItemComputerBase( Block block ) + { + super( block ); + } + + public abstract ComputerFamily getFamily( int damage ); + + @Override + public final int getMetadata( int damage ) + { + return damage; + } + + @Override + public void addInformation( ItemStack stack, EntityPlayer player, List list, boolean debug ) + { + if( debug ) + { + int id = getComputerID( stack ); + if( id >= 0 ) + { + list.add( "(Computer ID: " + id + ")" ); + } + } + } + + // IComputerItem implementation + + @Override + public abstract int getComputerID( ItemStack stack ); + + @Override + public String getLabel( ItemStack stack ) + { + if( stack.hasDisplayName() ) + { + return stack.getDisplayName(); + } + return null; + } + + @Override + public final ComputerFamily getFamily( ItemStack stack ) + { + int damage = stack.getItemDamage(); + return getFamily( damage ); + } + + // IMedia implementation + + @Override + public boolean setLabel( ItemStack stack, String label ) + { + if( label != null ) + { + stack.setStackDisplayName( label ); + } + else + { + stack.clearCustomName(); + } + return true; + } + + @Override + public String getAudioTitle( ItemStack stack ) + { + return null; + } + + @Override + public String getAudioRecordName( ItemStack stack ) + { + return null; + } + + @Override + public IMount createDataMount( ItemStack stack, World world ) + { + ComputerFamily family = getFamily( stack ); + if( family != ComputerFamily.Command ) + { + int id = getComputerID( stack ); + if( id >= 0 ) + { + return ComputerCraft.createSaveDirMount( world, "computer/" + id, ComputerCraft.computerSpaceLimit ); + } + } + return null; + } +} diff --git a/src/main/java/dan200/computercraft/shared/media/common/DefaultMediaProvider.java b/src/main/java/dan200/computercraft/shared/media/common/DefaultMediaProvider.java new file mode 100644 index 0000000000..50bbc57f25 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/media/common/DefaultMediaProvider.java @@ -0,0 +1,30 @@ +package dan200.computercraft.shared.media.common; + +import dan200.computercraft.api.media.IMedia; +import dan200.computercraft.api.media.IMediaProvider; +import dan200.computercraft.shared.media.items.RecordMedia; +import net.minecraft.item.Item; +import net.minecraft.item.ItemRecord; +import net.minecraft.item.ItemStack; + +public class DefaultMediaProvider implements IMediaProvider +{ + public DefaultMediaProvider() + { + } + + @Override + public IMedia getMedia( ItemStack stack ) + { + Item item = stack.getItem(); + if( item instanceof IMedia ) + { + return (IMedia)item; + } + else if( item instanceof ItemRecord ) + { + return new RecordMedia(); + } + return null; + } +} diff --git a/src/main/java/dan200/computercraft/shared/media/inventory/ContainerHeldItem.java b/src/main/java/dan200/computercraft/shared/media/inventory/ContainerHeldItem.java new file mode 100644 index 0000000000..f313654293 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/media/inventory/ContainerHeldItem.java @@ -0,0 +1,44 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.media.inventory; + +import dan200.computercraft.shared.util.InventoryUtil; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.item.ItemStack; + +public class ContainerHeldItem extends Container +{ + private final ItemStack m_stack; + private final int m_slot; + + public ContainerHeldItem( InventoryPlayer player ) + { + m_slot = player.currentItem; + m_stack = InventoryUtil.copyItem( player.getStackInSlot( m_slot ) ); + } + + public ItemStack getStack() + { + return m_stack; + } + + @Override + public boolean canInteractWith( EntityPlayer player ) + { + if( player != null && player.isEntityAlive() ) + { + ItemStack stack = player.inventory.getStackInSlot( m_slot ); + if( (stack == m_stack) || (stack != null && m_stack != null && stack.getItem() == m_stack.getItem()) ) + { + return true; + } + } + return false; + } +} diff --git a/src/main/java/dan200/computercraft/shared/media/items/ItemDiskExpanded.java b/src/main/java/dan200/computercraft/shared/media/items/ItemDiskExpanded.java new file mode 100644 index 0000000000..fa56c27c56 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/media/items/ItemDiskExpanded.java @@ -0,0 +1,67 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.media.items; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.util.Colour; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +public class ItemDiskExpanded extends ItemDiskLegacy +{ + public ItemDiskExpanded() + { + } + + public static ItemStack createFromIDAndColour( int id, String label, int colour ) + { + ItemStack stack = new ItemStack( ComputerCraft.Items.diskExpanded, 1, 0 ); + + NBTTagCompound nbt = stack.getTagCompound(); + if( nbt == null ) + { + nbt = new NBTTagCompound(); + stack.setTagCompound(nbt); + } + nbt.setInteger( "color", colour ); + ComputerCraft.Items.diskExpanded.setDiskID( stack, id ); + ComputerCraft.Items.diskExpanded.setLabel( stack, label ); + return stack; + } + + @Override + public int getDiskID( ItemStack stack ) + { + NBTTagCompound nbt = stack.getTagCompound(); + if( nbt != null && nbt.hasKey( "diskID" ) ) + { + return nbt.getInteger( "diskID" ); + } + return -1; + } + + @Override + protected void setDiskID( ItemStack stack, int id ) + { + if( id >= 0 ) + { + NBTTagCompound nbt = stack.getTagCompound(); + if( nbt == null ) + { + nbt = new NBTTagCompound(); + stack.setTagCompound( nbt ); + } + nbt.setInteger( "diskID", id ); + } + } + + public int getColor( ItemStack stack ) + { + NBTTagCompound nbt = stack.getTagCompound(); + return nbt != null && nbt.hasKey("color") ? nbt.getInteger("color") : Colour.values()[ Math.min(15, stack.getItemDamage()) ].getHex(); + } +} diff --git a/src/main/java/dan200/computercraft/shared/media/items/ItemDiskLegacy.java b/src/main/java/dan200/computercraft/shared/media/items/ItemDiskLegacy.java new file mode 100644 index 0000000000..8af27f32de --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/media/items/ItemDiskLegacy.java @@ -0,0 +1,158 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.media.items; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.ComputerCraftAPI; +import dan200.computercraft.api.filesystem.IMount; +import dan200.computercraft.api.media.IMedia; +import dan200.computercraft.shared.util.Colour; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +import java.util.List; + +public class ItemDiskLegacy extends Item + implements IMedia +{ + public ItemDiskLegacy() + { + setMaxStackSize( 1 ); + setHasSubtypes( true ); + setUnlocalizedName( "computercraft:disk" ); + setCreativeTab( ComputerCraft.mainCreativeTab ); + } + + @Override + public void getSubItems( Item itemID, CreativeTabs tabs, List list ) + { + for( int colour=0; colour<16; ++colour ) + { + ItemStack stack = createFromIDAndColour( -1, null, Colour.values()[ colour ].getHex() ); + if( stack.getItem() == this ) + { + list.add( stack ); + } + } + } + + public static ItemStack createFromIDAndColour( int id, String label, int colour ) + { + if( colour != Colour.Blue.getHex() ) + { + return ItemDiskExpanded.createFromIDAndColour( id, label, colour ); + } + + ItemStack stack = new ItemStack( ComputerCraft.Items.disk, 1 ); + ComputerCraft.Items.disk.setDiskID( stack, id ); + ComputerCraft.Items.disk.setLabel( stack, label ); + return stack; + } + + public int getDiskID( ItemStack stack ) + { + int damage = stack.getItemDamage(); + if( damage > 0 ) + { + return damage; + } + return -1; + } + + protected void setDiskID( ItemStack stack, int id ) + { + if( id > 0 ) { + stack.setItemDamage( id ); + } else { + stack.setItemDamage( 0 ); + } + } + + @Override + public void addInformation( ItemStack stack, EntityPlayer player, List list, boolean debug ) + { + if( debug ) + { + int id = getDiskID( stack ); + if( id >= 0 ) + { + list.add( "(Disk ID: " + id + ")" ); + } + } + } + + // IMedia implementation + + @Override + public String getLabel( ItemStack stack ) + { + if( stack.hasDisplayName() ) + { + return stack.getDisplayName(); + } + return null; + } + + @Override + public boolean setLabel( ItemStack stack, String label ) + { + if( label != null ) + { + stack.setStackDisplayName( label ); + } + else + { + stack.clearCustomName(); + } + return true; + } + + @Override + public String getAudioTitle( ItemStack stack ) + { + return null; + } + + @Override + public String getAudioRecordName( ItemStack stack ) + { + return null; + } + + @Override + public IMount createDataMount( ItemStack stack, World world ) + { + int diskID = getDiskID( stack ); + if( diskID < 0 ) + { + diskID = ComputerCraft.createUniqueNumberedSaveDir( world, "computer/disk" ); + setDiskID( stack, diskID ); + } + return ComputerCraftAPI.createSaveDirMount( world, "computer/disk/" + diskID, ComputerCraft.floppySpaceLimit ); + } + + @Override + public int getColorFromItemStack( ItemStack stack, int layer ) + { + return layer == 0 ? 0xffffff : getColor(stack); + } + + public int getColor( ItemStack stack ) + { + return Colour.Blue.getHex(); + } + + @Override + public boolean doesSneakBypassUse( World world, BlockPos pos, EntityPlayer player ) + { + return true; + } +} diff --git a/src/main/java/dan200/computercraft/shared/media/items/ItemPrintout.java b/src/main/java/dan200/computercraft/shared/media/items/ItemPrintout.java new file mode 100644 index 0000000000..a0665a26be --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/media/items/ItemPrintout.java @@ -0,0 +1,243 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.media.items; + +import dan200.computercraft.ComputerCraft; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.World; + +import java.util.List; + +public class ItemPrintout extends Item +{ + public static final int LINES_PER_PAGE = 21; + public static final int LINE_MAX_LENGTH = 25; + public static final int MAX_PAGES = 16; + + public enum Type + { + Single, + Multiple, + Book + } + + public ItemPrintout() + { + setMaxStackSize( 1 ); + setHasSubtypes( true ); + setUnlocalizedName( "computercraft:page" ); + setCreativeTab( ComputerCraft.mainCreativeTab ); + } + + @Override + public void getSubItems( Item itemID, CreativeTabs tabs, List list ) + { + list.add( createSingleFromTitleAndText( null, new String[ LINES_PER_PAGE ], new String[ LINES_PER_PAGE ] ) ); + list.add( createMultipleFromTitleAndText( null, new String[ 2*LINES_PER_PAGE ], new String[ 2*LINES_PER_PAGE ] ) ); + list.add( createBookFromTitleAndText( null, new String[ 2*LINES_PER_PAGE ], new String[ 2*LINES_PER_PAGE ] ) ); + } + + @Override + public void addInformation( ItemStack itemstack, EntityPlayer par2EntityPlayer, List list, boolean flag ) + { + String title = getTitle( itemstack ); + if( title != null && title.length() > 0 ) + { + list.add( title ); + } + } + + @Override + public String getUnlocalizedName( ItemStack stack ) + { + Type type = getType( stack ); + switch( type ) + { + case Single: + default: + { + return "item.computercraft:page"; + } + case Multiple: + { + return "item.computercraft:pages"; + } + case Book: + { + return "item.computercraft:book"; + } + } + } + + @Override + public ItemStack onItemRightClick( ItemStack stack, World world, EntityPlayer player ) + { + if( !world.isRemote ) + { + ComputerCraft.openPrintoutGUI( player ); + } + return stack; + } + + private static ItemStack createFromTitleAndText( Type type, String title, String[] text, String[] colours ) + { + // Calculate damage + int damage; + switch( type ) + { + case Single: + default: + { + damage = 0; + break; + } + case Multiple: + { + damage = 1; + break; + } + case Book: + { + damage = 2; + break; + } + } + + // Create stack + ItemStack stack = new ItemStack( ComputerCraft.Items.printout, 1, damage ); + + // Build NBT + NBTTagCompound nbt = new NBTTagCompound(); + if( title != null ) + { + nbt.setString( "title", title ); + } + if( text != null ) + { + nbt.setInteger( "pages", text.length / LINES_PER_PAGE ); + for(int i=0; i 0 ) + { + list.add( label ); + } + } + + @Override + public int getColorFromItemStack( ItemStack stack, int pass ) + { + return pass == 0 ? 0xffffff : getColour(stack); + } + + @Override + public boolean doesSneakBypassUse( World world, BlockPos pos, EntityPlayer player ) + { + return true; + } + + // IMedia implementation + + @Override + public String getLabel( ItemStack stack ) + { + return getTitle( stack ); + } + + @Override + public boolean setLabel( ItemStack stack, String label ) + { + return false; + } + + @Override + public String getAudioTitle( ItemStack stack ) + { + return null; + } + + @Override + public String getAudioRecordName( ItemStack stack ) + { + return null; + } + + @Override + public IMount createDataMount( ItemStack stack, World world ) + { + IMount rootTreasure = getTreasureMount(); + String subPath = getSubPath( stack ); + try + { + if( rootTreasure.exists( subPath ) ) + { + return new SubMount( rootTreasure, subPath ); + } + else if( rootTreasure.exists( "deprecated/" + subPath ) ) + { + return new SubMount( rootTreasure, "deprecated/" + subPath ); + } + else + { + return null; + } + } + catch( IOException e ) + { + return null; + } + } + + public static ItemStack create( String subPath, int colourIndex ) + { + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setString( "subPath", subPath ); + + int slash = subPath.indexOf( "/" ); + if( slash >= 0 ) + { + String author = subPath.substring( 0, slash ); + String title = subPath.substring( slash + 1 ); + nbt.setString( "title", "\"" + title + "\" by " + author ); + } + else + { + nbt.setString( "title", "untitled" ); + } + nbt.setInteger( "colour", Colour.values()[ colourIndex ].getHex() ); + + ItemStack result = new ItemStack( ComputerCraft.Items.treasureDisk, 1, 0 ); + result.setTagCompound( nbt ); + return result; + } + + public static void registerDungeonLoot() + { + if( s_treasureItems == null ) + { + // Get the list of all programs + List paths = new ArrayList(); + try + { + IMount treasure = getTreasureMount(); + if( treasure != null ) + { + List authors = new ArrayList(); + treasure.list( "", authors ); + for( String author : authors ) + { + if( treasure.isDirectory( author ) && !author.equals( "deprecated" ) ) + { + List titles = new ArrayList(); + treasure.list( author, titles ); + for( String title : titles ) + { + String path = author + "/" + title; + if( treasure.isDirectory( path ) ) + { + paths.add( path ); + } + } + } + } + } + } + catch( java.io.IOException e ) + { + // no items for us + } + + // Build creative tab + List allTreasure = new ArrayList(); + for( String path : paths ) + { + ItemStack stack = create( path, 4 ); + allTreasure.add( stack ); + } + s_treasureItems = allTreasure.toArray( new ItemStack[ allTreasure.size() ] ); + + // Register the loot + int n=0; + Random random = new Random(); + WeightedRandomChestContent[] content = new WeightedRandomChestContent[ paths.size() * ComputerCraft.treasureDiskLootFrequency ]; + WeightedRandomChestContent[] commonContent = new WeightedRandomChestContent[ paths.size() * ComputerCraft.treasureDiskLootFrequency ]; + for( String path : paths ) + { + // Don't use all the random colours + // We don't want to overload the probability matrix + for( int i=0; i= (leatherFound ? 1 : 2) ) + { + String[] text = new String[ numPages * ItemPrintout.LINES_PER_PAGE ]; + String[] colours = new String[ numPages * ItemPrintout.LINES_PER_PAGE ]; + int line = 0; + + for( int printout=0; printout 0 ) + { + m_dataByte[ k ] = new byte[ length ]; + buffer.getBytes( buffer.readerIndex(), m_dataByte[ k ] ); + } + } + } + boolean bNBT = buffer.readBoolean(); + if( !bNBT ) + { + m_dataNBT = null; + } + else + { + int byteLength = buffer.readInt(); + byte[] bytes = new byte[ byteLength ]; + buffer.getBytes( buffer.readerIndex(), bytes ); + try + { + ByteArrayInputStream bis = new ByteArrayInputStream( bytes ); + m_dataNBT = CompressedStreamTools.readCompressed( bis ); + } + catch( IOException e ) + { + m_dataNBT = null; + } + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/network/INetworkedThing.java b/src/main/java/dan200/computercraft/shared/network/INetworkedThing.java new file mode 100644 index 0000000000..e2c18c49e0 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/network/INetworkedThing.java @@ -0,0 +1,13 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.network; +import net.minecraft.entity.player.EntityPlayer; + +public interface INetworkedThing +{ + public void handlePacket( ComputerCraftPacket packet, EntityPlayer sender ); +} diff --git a/src/main/java/dan200/computercraft/shared/network/PacketHandler.java b/src/main/java/dan200/computercraft/shared/network/PacketHandler.java new file mode 100644 index 0000000000..0db6d67c25 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/network/PacketHandler.java @@ -0,0 +1,45 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.network; + +import dan200.computercraft.ComputerCraft; +import net.minecraft.network.NetHandlerPlayServer; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.network.FMLNetworkEvent; + +public class PacketHandler +{ + @SubscribeEvent + public void onClientPacket( FMLNetworkEvent.ClientCustomPacketEvent event ) + { + try + { + ComputerCraftPacket packet = new ComputerCraftPacket(); + packet.fromBytes( event.packet.payload() ); + ComputerCraft.handlePacket( packet, null ); + } + catch( Exception e ) + { + e.printStackTrace(); + } + } + + @SubscribeEvent + public void onServerPacket( FMLNetworkEvent.ServerCustomPacketEvent event ) + { + try + { + ComputerCraftPacket packet = new ComputerCraftPacket(); + packet.fromBytes( event.packet.payload() ); + ComputerCraft.handlePacket( packet, ((NetHandlerPlayServer)event.handler).playerEntity ); + } + catch( Exception e ) + { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/PeripheralType.java b/src/main/java/dan200/computercraft/shared/peripheral/PeripheralType.java new file mode 100644 index 0000000000..6c7cb14559 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/PeripheralType.java @@ -0,0 +1,38 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral; + +import net.minecraft.util.IStringSerializable; + +public enum PeripheralType implements IStringSerializable +{ + DiskDrive( "disk_drive" ), + Printer( "printer" ), + Monitor( "monitor" ), + AdvancedMonitor( "advanced_monitor" ), + WirelessModem( "wireless_modem" ), + WiredModem( "wired_modem" ), + Cable( "cable" ), + WiredModemWithCable( "wired_modem_with_cable" ), + AdvancedModem( "advanced_modem" ); + + private String m_name; + + private PeripheralType( String name ) + { + m_name = name; + } + + @Override + public String getName() + { + return m_name; + } + + @Override + public String toString() { return getName(); } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheral.java new file mode 100644 index 0000000000..ea924c0ea2 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheral.java @@ -0,0 +1,123 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.commandblock; + +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.ILuaTask; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.IPeripheral; +import net.minecraft.tileentity.TileEntityCommandBlock; + +public class CommandBlockPeripheral implements IPeripheral +{ + private final TileEntityCommandBlock m_commandBlock; + + public CommandBlockPeripheral( TileEntityCommandBlock commandBlock ) + { + m_commandBlock = commandBlock; + } + + // IPeripheral methods + + @Override + public String getType() + { + return "command"; + } + + @Override + public String[] getMethodNames() + { + return new String[] { + "getCommand", + "setCommand", + "runCommand", + }; + } + + @Override + public Object[] callMethod( IComputerAccess computer, ILuaContext context, int method, final Object[] arguments ) throws LuaException, InterruptedException + { + switch (method) + { + case 0: + { + // getCommand + return context.executeMainThreadTask( new ILuaTask() + { + @Override + public Object[] execute() throws LuaException + { + return new Object[] { + m_commandBlock.getCommandBlockLogic().getCommand() + }; + } + } ); + } + case 1: + { + // setCommand + if( arguments.length < 1 || !(arguments[0] instanceof String) ) + { + throw new LuaException( "Expected string" ); + } + + final String command = (String) arguments[ 0 ]; + context.issueMainThreadTask( new ILuaTask() + { + @Override + public Object[] execute() throws LuaException + { + m_commandBlock.getCommandBlockLogic().setCommand( command ); + m_commandBlock.getWorld().markBlockForUpdate( m_commandBlock.getPos() ); + return null; + } + } ); + return null; + } + case 2: + { + // runCommand + return context.executeMainThreadTask( new ILuaTask() + { + @Override + public Object[] execute() throws LuaException + { + m_commandBlock.getCommandBlockLogic().trigger( m_commandBlock.getWorld() ); + int result = m_commandBlock.getCommandBlockLogic().getSuccessCount(); + if( result > 0 ) + { + return new Object[] { true }; + } + else + { + return new Object[] { false, "Command failed" }; + } + } + } ); + } + } + return null; + } + + @Override + public void attach( IComputerAccess computer ) + { + } + + @Override + public void detach( IComputerAccess computer ) + { + } + + @Override + public boolean equals( IPeripheral other ) + { + return (other != null && other.getClass() == this.getClass()); + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheralProvider.java b/src/main/java/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheralProvider.java new file mode 100644 index 0000000000..8e29a74ba3 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheralProvider.java @@ -0,0 +1,30 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.commandblock; + +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.api.peripheral.IPeripheralProvider; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityCommandBlock; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +public class CommandBlockPeripheralProvider implements IPeripheralProvider +{ + @Override + public IPeripheral getPeripheral( World world, BlockPos pos, EnumFacing side ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileEntityCommandBlock ) + { + TileEntityCommandBlock commandBlock = (TileEntityCommandBlock)tile; + return new CommandBlockPeripheral( commandBlock ); + } + return null; + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCable.java b/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCable.java new file mode 100644 index 0000000000..27f6b396de --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCable.java @@ -0,0 +1,247 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.common; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.peripheral.PeripheralType; +import dan200.computercraft.shared.peripheral.modem.TileCable; +import net.minecraft.block.Block; +import net.minecraft.block.properties.IProperty; +import net.minecraft.block.properties.PropertyBool; +import net.minecraft.block.properties.PropertyEnum; +import net.minecraft.block.state.BlockState; +import net.minecraft.block.state.IBlockState; +import net.minecraft.item.Item; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.IBlockAccess; + +public class BlockCable extends BlockPeripheralBase +{ + // Statics + + public static class Properties + { + public static final PropertyEnum MODEM = PropertyEnum.create( "modem", BlockCableModemVariant.class ); + public static final PropertyBool CABLE = PropertyBool.create( "cable" ); + public static final PropertyBool NORTH = PropertyBool.create( "north" ); + public static final PropertyBool SOUTH = PropertyBool.create( "south" ); + public static final PropertyBool EAST = PropertyBool.create( "east" ); + public static final PropertyBool WEST = PropertyBool.create( "west" ); + public static final PropertyBool UP = PropertyBool.create( "up" ); + public static final PropertyBool DOWN = PropertyBool.create( "down" ); + } + + public static boolean isCable( IBlockAccess world, BlockPos pos ) + { + Block block = world.getBlockState( pos ).getBlock(); + if( block == ComputerCraft.Blocks.cable ) + { + switch( ComputerCraft.Blocks.cable.getPeripheralType( world, pos ) ) + { + case Cable: + case WiredModemWithCable: + { + return true; + } + } + } + return false; + } + + // Members + + public BlockCable() + { + setHardness( 1.5f ); + setUnlocalizedName( "computercraft:cable" ); + setCreativeTab( ComputerCraft.mainCreativeTab ); + setDefaultState( this.blockState.getBaseState() + .withProperty( Properties.MODEM, BlockCableModemVariant.None ) + .withProperty( Properties.CABLE, true ) + .withProperty( Properties.NORTH, false ) + .withProperty( Properties.SOUTH, false ) + .withProperty( Properties.EAST, false ) + .withProperty( Properties.WEST, false ) + .withProperty( Properties.UP, false ) + .withProperty( Properties.DOWN, false ) + ); + } + + @Override + protected BlockState createBlockState() + { + return new BlockState(this, new IProperty[] { + Properties.MODEM, + Properties.CABLE, + Properties.NORTH, + Properties.SOUTH, + Properties.EAST, + Properties.WEST, + Properties.UP, + Properties.DOWN, + }); + } + + @Override + public IBlockState getStateFromMeta( int meta ) + { + IBlockState state = getDefaultState(); + if( meta < 6 ) + { + state = state.withProperty( Properties.CABLE, false ); + state = state.withProperty( Properties.MODEM, BlockCableModemVariant.fromFacing( EnumFacing.getFront( meta ) ) ); + } + else if( meta < 12 ) + { + state = state.withProperty( Properties.CABLE, true ); + state = state.withProperty( Properties.MODEM, BlockCableModemVariant.fromFacing( EnumFacing.getFront( meta - 6 ) ) ); + } + else if( meta == 13 ) + { + state = state.withProperty( Properties.CABLE, true ); + state = state.withProperty( Properties.MODEM, BlockCableModemVariant.None ); + } + return state; + } + + @Override + public int getMetaFromState( IBlockState state ) + { + int meta = 0; + boolean cable = (Boolean)state.getValue( Properties.CABLE ); + BlockCableModemVariant modem = (BlockCableModemVariant)state.getValue( Properties.MODEM ); + if( cable && modem != BlockCableModemVariant.None ) + { + meta = 6 + modem.getFacing().getIndex(); + } + else if( modem != BlockCableModemVariant.None ) + { + meta = modem.getFacing().getIndex(); + } + else if( cable ) + { + meta = 13; + } + return meta; + } + + @Override + public IBlockState getDefaultBlockState( PeripheralType type, EnumFacing placedSide ) + { + switch( type ) + { + case Cable: + { + return getDefaultState() + .withProperty( Properties.CABLE, true ) + .withProperty( Properties.MODEM, BlockCableModemVariant.None ); + } + case WiredModem: + default: + { + return getDefaultState() + .withProperty( Properties.CABLE, false ) + .withProperty( Properties.MODEM, BlockCableModemVariant.fromFacing( placedSide.getOpposite() ) ); + } + case WiredModemWithCable: + { + return getDefaultState() + .withProperty( Properties.CABLE, true ) + .withProperty( Properties.MODEM, BlockCableModemVariant.fromFacing( placedSide.getOpposite() ) ); + } + } + } + + private boolean doesConnect( IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing dir ) + { + if( !((Boolean)state.getValue( Properties.CABLE )) ) + { + return false; + } + else if( ((BlockCableModemVariant)state.getValue( Properties.MODEM )).getFacing() == dir ) + { + return true; + } + else + { + return isCable( world, pos.offset( dir ) ); + } + } + + @Override + public IBlockState getActualState( IBlockState state, IBlockAccess world, BlockPos pos ) + { + state = state.withProperty( Properties.NORTH, doesConnect( state, world, pos, EnumFacing.NORTH ) ); + state = state.withProperty( Properties.SOUTH, doesConnect( state, world, pos, EnumFacing.SOUTH ) ); + state = state.withProperty( Properties.EAST, doesConnect( state, world, pos, EnumFacing.EAST ) ); + state = state.withProperty( Properties.WEST, doesConnect( state, world, pos, EnumFacing.WEST ) ); + state = state.withProperty( Properties.UP, doesConnect( state, world, pos, EnumFacing.UP ) ); + state = state.withProperty( Properties.DOWN, doesConnect( state, world, pos, EnumFacing.DOWN ) ); + + int anim; + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TilePeripheralBase ) + { + TilePeripheralBase peripheral = (TilePeripheralBase)tile; + anim = peripheral.getAnim(); + } + else + { + anim = 0; + } + + BlockCableModemVariant modem = ((BlockCableModemVariant)state.getValue( Properties.MODEM )); + if( modem != BlockCableModemVariant.None ) + { + modem = BlockCableModemVariant.values()[ + 1 + 6 * anim + modem.getFacing().getIndex() + ]; + } + state = state.withProperty( Properties.MODEM, modem ); + + return state; + } + + @Override + public boolean shouldSideBeRendered( IBlockAccess world, BlockPos pos, EnumFacing side ) + { + return true; + } + + @Override + public PeripheralType getPeripheralType( int damage ) + { + return ((ItemCable) Item.getItemFromBlock( this )).getPeripheralType( damage ); + } + + @Override + public PeripheralType getPeripheralType( IBlockState state ) + { + boolean cable = (Boolean)state.getValue( Properties.CABLE ); + BlockCableModemVariant modem = (BlockCableModemVariant)state.getValue( Properties.MODEM ); + if( cable && modem != BlockCableModemVariant.None ) + { + return PeripheralType.WiredModemWithCable; + } + else if( modem != BlockCableModemVariant.None ) + { + return PeripheralType.WiredModem; + } + else + { + return PeripheralType.Cable; + } + } + + @Override + public TilePeripheralBase createTile( PeripheralType type ) + { + return new TileCable(); + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCableModemVariant.java b/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCableModemVariant.java new file mode 100644 index 0000000000..ffb572ac60 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCableModemVariant.java @@ -0,0 +1,79 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.common; + +import net.minecraft.util.EnumFacing; +import net.minecraft.util.IStringSerializable; + +public enum BlockCableModemVariant implements IStringSerializable +{ + None( "none", null ), + DownOff( "down_off", EnumFacing.DOWN ), + UpOff( "up_off", EnumFacing.UP ), + NorthOff( "north_off", EnumFacing.NORTH ), + SouthOff( "south_off", EnumFacing.SOUTH ), + WestOff( "west_off", EnumFacing.WEST ), + EastOff( "east_off", EnumFacing.EAST ), + DownOn( "down_on", EnumFacing.DOWN ), + UpOn( "up_on", EnumFacing.UP ), + NorthOn( "north_on", EnumFacing.NORTH ), + SouthOn( "south_on", EnumFacing.SOUTH ), + WestOn( "west_on", EnumFacing.WEST ), + EastOn( "east_on", EnumFacing.EAST ), + DownOffPeripheral( "down_off_peripheral", EnumFacing.DOWN ), + UpOffPeripheral( "up_off_peripheral", EnumFacing.UP ), + NorthOffPeripheral( "north_off_peripheral", EnumFacing.NORTH ), + SouthOffPeripheral( "south_off_peripheral", EnumFacing.SOUTH ), + WestOffPeripheral( "west_off_peripheral", EnumFacing.WEST ), + EastOffPeripheral( "east_off_peripheral", EnumFacing.EAST ), + DownOnPeripheral( "down_on_peripheral", EnumFacing.DOWN ), + UpOnPeripheral( "up_on_peripheral", EnumFacing.UP ), + NorthOnPeripheral( "north_on_peripheral", EnumFacing.NORTH ), + SouthOnPeripheral( "south_on_peripheral", EnumFacing.SOUTH ), + WestOnPeripheral( "west_on_peripheral", EnumFacing.WEST ), + EastOnPeripheral( "east_on_peripheral", EnumFacing.EAST ); + + public static BlockCableModemVariant fromFacing( EnumFacing facing ) + { + switch( facing ) + { + case DOWN: return DownOff; + case UP: return UpOff; + case NORTH: return NorthOff; + case SOUTH: return SouthOff; + case WEST: return WestOff; + case EAST: return EastOff; + } + return NorthOff; + } + + private String m_name; + private EnumFacing m_facing; + + private BlockCableModemVariant( String name, EnumFacing facing ) + { + m_name = name; + m_facing = facing; + } + + @Override + public String getName() + { + return m_name; + } + + public EnumFacing getFacing() + { + return m_facing; + } + + @Override + public String toString() + { + return getName(); + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/common/BlockPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/common/BlockPeripheral.java new file mode 100644 index 0000000000..f5204cee8a --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/common/BlockPeripheral.java @@ -0,0 +1,586 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.common; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.peripheral.PeripheralType; +import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive; +import dan200.computercraft.shared.peripheral.modem.TileWirelessModem; +import dan200.computercraft.shared.peripheral.monitor.TileMonitor; +import dan200.computercraft.shared.peripheral.printer.TilePrinter; +import dan200.computercraft.shared.util.DirectionUtil; +import net.minecraft.block.properties.IProperty; +import net.minecraft.block.properties.PropertyDirection; +import net.minecraft.block.properties.PropertyEnum; +import net.minecraft.block.state.BlockState; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumWorldBlockLayer; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class BlockPeripheral extends BlockPeripheralBase +{ + public static class Properties + { + public static final PropertyDirection FACING = PropertyDirection.create( "facing",EnumFacing.Plane.HORIZONTAL ); + public static final PropertyEnum VARIANT = PropertyEnum.create( "variant", BlockPeripheralVariant.class ); + } + + public BlockPeripheral() + { + setHardness( 2.0f ); + setUnlocalizedName( "computercraft:peripheral" ); + setCreativeTab( ComputerCraft.mainCreativeTab ); + setDefaultState( this.blockState.getBaseState() + .withProperty( Properties.FACING, EnumFacing.NORTH ) + .withProperty( Properties.VARIANT, BlockPeripheralVariant.DiskDriveEmpty ) + ); + } + + @SideOnly( Side.CLIENT) + public EnumWorldBlockLayer getBlockLayer() + { + return EnumWorldBlockLayer.CUTOUT; + } + + @Override + protected BlockState createBlockState() + { + return new BlockState(this, new IProperty[] { + Properties.FACING, + Properties.VARIANT + }); + } + + @Override + public IBlockState getStateFromMeta( int meta ) + { + IBlockState state = getDefaultState(); + if( meta >= 2 && meta <= 5 ) + { + state = state.withProperty( Properties.VARIANT, BlockPeripheralVariant.DiskDriveEmpty ); + state = state.withProperty( Properties.FACING, EnumFacing.getFront( meta ) ); + } + else if( meta <= 9 ) + { + if( meta == 0 ) + { + state = state.withProperty( Properties.VARIANT, BlockPeripheralVariant.WirelessModemDownOff ); + state = state.withProperty( Properties.FACING, EnumFacing.NORTH ); + } + else if( meta == 1 ) + { + state = state.withProperty( Properties.VARIANT, BlockPeripheralVariant.WirelessModemUpOff ); + state = state.withProperty( Properties.FACING, EnumFacing.NORTH ); + } + else + { + state = state.withProperty( Properties.VARIANT, BlockPeripheralVariant.WirelessModemOff ); + state = state.withProperty( Properties.FACING, EnumFacing.getFront( meta - 4 ) ); + } + } + else if( meta == 10 ) + { + state = state.withProperty( Properties.VARIANT, BlockPeripheralVariant.Monitor ); + } + else if( meta == 11 ) + { + state = state.withProperty( Properties.VARIANT, BlockPeripheralVariant.PrinterEmpty ); + } + else if( meta == 12 ) + { + state = state.withProperty( Properties.VARIANT, BlockPeripheralVariant.AdvancedMonitor ); + } + return state; + } + + @Override + public int getMetaFromState( IBlockState state ) + { + int meta = 0; + BlockPeripheralVariant variant = (BlockPeripheralVariant)state.getValue( Properties.VARIANT ); + switch( variant.getPeripheralType() ) + { + case DiskDrive: + { + EnumFacing dir = (EnumFacing)state.getValue( Properties.FACING ); + if( dir.getAxis() == EnumFacing.Axis.Y ) { + dir = EnumFacing.NORTH; + } + meta = dir.getIndex(); + break; + } + case WirelessModem: + { + switch( variant ) + { + case WirelessModemDownOff: + case WirelessModemDownOn: + { + meta = 0; + break; + } + case WirelessModemUpOff: + case WirelessModemUpOn: + { + meta = 1; + break; + } + default: + { + EnumFacing dir = (EnumFacing)state.getValue( Properties.FACING ); + meta = dir.getIndex() + 4; + break; + } + } + break; + } + case Monitor: + { + meta = 10; + break; + } + case Printer: + { + meta = 11; + break; + } + case AdvancedMonitor: + { + meta = 12; + break; + } + } + return meta; + } + + @Override + public IBlockState getActualState( IBlockState state, IBlockAccess world, BlockPos pos ) + { + int anim; + EnumFacing dir; + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TilePeripheralBase ) + { + TilePeripheralBase peripheral = (TilePeripheralBase)tile; + anim = peripheral.getAnim(); + dir = peripheral.getDirection(); + } + else + { + anim = 0; + dir = (EnumFacing)state.getValue( Properties.FACING ); + switch( (BlockPeripheralVariant)state.getValue( BlockPeripheral.Properties.VARIANT ) ) + { + case WirelessModemDownOff: + case WirelessModemDownOn: + { + dir = EnumFacing.DOWN; + break; + } + case WirelessModemUpOff: + case WirelessModemUpOn: + { + dir = EnumFacing.UP; + break; + } + } + } + + PeripheralType type = getPeripheralType( state ); + switch( type ) + { + case DiskDrive: + { + state = state.withProperty( Properties.FACING, dir ); + switch( anim ) + { + case 0: + default: + { + state = state.withProperty( Properties.VARIANT, BlockPeripheralVariant.DiskDriveEmpty ); + break; + } + case 1: + { + state = state.withProperty( Properties.VARIANT, BlockPeripheralVariant.DiskDriveInvalid ); + break; + } + case 2: + { + state = state.withProperty( Properties.VARIANT, BlockPeripheralVariant.DiskDriveFull ); + break; + } + } + break; + } + case Printer: + { + state = state.withProperty( Properties.FACING, dir ); + switch( anim ) + { + case 0: + default: + { + state = state.withProperty( Properties.VARIANT, BlockPeripheralVariant.PrinterEmpty ); + break; + } + case 1: + { + state = state.withProperty( Properties.VARIANT, BlockPeripheralVariant.PrinterTopFull ); + break; + } + case 2: + { + state = state.withProperty( Properties.VARIANT, BlockPeripheralVariant.PrinterBottomFull ); + break; + } + case 3: + { + state = state.withProperty( Properties.VARIANT, BlockPeripheralVariant.PrinterBothFull ); + break; + } + } + break; + } + case WirelessModem: + { + switch( dir ) + { + case UP: + { + state = state.withProperty( Properties.FACING, EnumFacing.NORTH ); + switch( anim ) + { + case 0: + default: + { + state = state.withProperty( Properties.VARIANT, BlockPeripheralVariant.WirelessModemUpOff ); + break; + } + case 1: + { + state = state.withProperty( Properties.VARIANT, BlockPeripheralVariant.WirelessModemUpOn ); + break; + } + } + break; + } + case DOWN: + { + state = state.withProperty( Properties.FACING, EnumFacing.NORTH ); + switch( anim ) + { + case 0: + default: + { + state = state.withProperty( Properties.VARIANT, BlockPeripheralVariant.WirelessModemDownOff ); + break; + } + case 1: + { + state = state.withProperty( Properties.VARIANT, BlockPeripheralVariant.WirelessModemDownOn ); + break; + } + } + break; + } + default: + { + state = state.withProperty( Properties.FACING, dir ); + switch( anim ) + { + case 0: + default: + { + state = state.withProperty( Properties.VARIANT, BlockPeripheralVariant.WirelessModemOff ); + break; + } + case 1: + { + state = state.withProperty( Properties.VARIANT, BlockPeripheralVariant.WirelessModemOn ); + break; + } + } + break; + } + } + break; + } + case Monitor: + case AdvancedMonitor: + { + EnumFacing front; + int xIndex, yIndex, width, height; + if( tile != null && tile instanceof TileMonitor ) + { + TileMonitor monitor = (TileMonitor)tile; + dir = monitor.getDirection(); + front = monitor.getFront(); + xIndex = monitor.getXIndex(); + yIndex = monitor.getYIndex(); + width = monitor.getWidth(); + height = monitor.getHeight(); + } + else + { + dir = EnumFacing.NORTH; + front = EnumFacing.NORTH; + xIndex = 0; + yIndex = 0; + width = 1; + height = 1; + } + + BlockPeripheralVariant baseVariant; + if( front == EnumFacing.UP ) + { + baseVariant = (type == PeripheralType.AdvancedMonitor) ? + BlockPeripheralVariant.AdvancedMonitorUp : + BlockPeripheralVariant.MonitorUp; + } + else if( front == EnumFacing.DOWN ) + { + baseVariant = (type == PeripheralType.AdvancedMonitor) ? + BlockPeripheralVariant.AdvancedMonitorDown : + BlockPeripheralVariant.MonitorDown; + } + else + { + baseVariant = (type == PeripheralType.AdvancedMonitor) ? + BlockPeripheralVariant.AdvancedMonitor : + BlockPeripheralVariant.Monitor; + } + + int subType; + if( width == 1 && height == 1 ) + { + subType = 0; + } + else if( height == 1 ) + { + if( xIndex == 0 ) + { + subType = 1; + } + else if( xIndex == width - 1 ) + { + subType = 3; + } + else + { + subType = 2; + } + } + else if( width == 1 ) + { + if( yIndex == 0 ) + { + subType = 6; + } + else if( yIndex == height - 1 ) + { + subType = 4; + } + else + { + subType = 5; + } + } + else + { + if( xIndex == 0 ) + { + subType = 7; + } + else if( xIndex == width - 1 ) + { + subType = 9; + } + else + { + subType = 8; + } + if( yIndex == 0 ) + { + subType += 6; + } + else if( yIndex < height - 1 ) + { + subType += 3; + } + } + + state = state.withProperty( Properties.FACING, dir ); + state = state.withProperty( Properties.VARIANT, + BlockPeripheralVariant.values()[ baseVariant.ordinal() + subType ] + ); + break; + } + } + return state; + } + + @Override + public IBlockState getDefaultBlockState( PeripheralType type, EnumFacing placedSide ) + { + switch( type ) + { + case DiskDrive: + default: + { + IBlockState state = getDefaultState().withProperty( Properties.VARIANT, BlockPeripheralVariant.DiskDriveEmpty ); + if( placedSide.getAxis() != EnumFacing.Axis.Y ) + { + return state.withProperty( Properties.FACING, placedSide ); + } + else + { + return state.withProperty( Properties.FACING, EnumFacing.NORTH ); + } + } + case WirelessModem: + { + EnumFacing dir = placedSide.getOpposite(); + if( dir == EnumFacing.DOWN ) + { + return getDefaultState() + .withProperty( Properties.VARIANT, BlockPeripheralVariant.WirelessModemDownOff ) + .withProperty( Properties.FACING, EnumFacing.NORTH ); + } + else if( dir == EnumFacing.UP ) + { + return getDefaultState() + .withProperty( Properties.VARIANT, BlockPeripheralVariant.WirelessModemUpOff ) + .withProperty( Properties.FACING, EnumFacing.NORTH ); + } + else + { + return getDefaultState() + .withProperty( Properties.VARIANT, BlockPeripheralVariant.WirelessModemOff ) + .withProperty( Properties.FACING, dir ); + } + } + case Monitor: + { + return getDefaultState().withProperty( Properties.VARIANT, BlockPeripheralVariant.Monitor ); + } + case Printer: + { + return getDefaultState().withProperty( Properties.VARIANT, BlockPeripheralVariant.PrinterEmpty ); + } + case AdvancedMonitor: + { + return getDefaultState().withProperty( Properties.VARIANT, BlockPeripheralVariant.AdvancedMonitor ); + } + } + } + + @Override + public PeripheralType getPeripheralType( int damage ) + { + return ((ItemPeripheral)Item.getItemFromBlock(this)).getPeripheralType( damage ); + } + + @Override + public PeripheralType getPeripheralType( IBlockState state ) + { + return ((BlockPeripheralVariant)state.getValue( Properties.VARIANT )).getPeripheralType(); + } + + @Override + public TilePeripheralBase createTile( PeripheralType type ) + { + switch( type ) + { + case DiskDrive: + default: + { + return new TileDiskDrive(); + } + case WirelessModem: + { + return new TileWirelessModem(); + } + case Monitor: + case AdvancedMonitor: + { + return new TileMonitor(); + } + case Printer: + { + return new TilePrinter(); + } + } + } + + @Override + public void onBlockPlacedBy( World world, BlockPos pos, IBlockState state, EntityLivingBase player, ItemStack stack ) + { + // Not sure why this is necessary + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TilePeripheralBase ) + { + tile.setWorldObj( world ); // Not sure why this is necessary + tile.setPos( pos ); // Not sure why this is necessary + } + + switch( getPeripheralType( state ) ) + { + case DiskDrive: + case Printer: + { + EnumFacing dir = DirectionUtil.fromEntityRot( player ); + setDirection( world, pos, dir ); + if( stack.hasDisplayName() && tile != null && tile instanceof TilePeripheralBase ) + { + TilePeripheralBase peripheral = (TilePeripheralBase)tile; + peripheral.setLabel( stack.getDisplayName() ); + } + break; + } + case Monitor: + case AdvancedMonitor: + { + if( tile != null && tile instanceof TileMonitor ) + { + int direction = DirectionUtil.fromEntityRot( player ).getIndex(); + if( player.rotationPitch > 66.5F ) + { + direction += 12; + } + else if( player.rotationPitch < -66.5F ) + { + direction += 6; + } + + TileMonitor monitor = (TileMonitor)tile; + if( world.isRemote ) + { + monitor.setDir( direction ); + } + else + { + monitor.contractNeighbours(); + monitor.setDir( direction ); + monitor.contract(); + monitor.expand(); + } + } + break; + } + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/common/BlockPeripheralBase.java b/src/main/java/dan200/computercraft/shared/peripheral/common/BlockPeripheralBase.java new file mode 100644 index 0000000000..8b93ac5979 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/common/BlockPeripheralBase.java @@ -0,0 +1,73 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.common; + +import dan200.computercraft.shared.common.BlockDirectional; +import dan200.computercraft.shared.common.TileGeneric; +import dan200.computercraft.shared.peripheral.PeripheralType; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.item.Item; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +public abstract class BlockPeripheralBase extends BlockDirectional +{ + public BlockPeripheralBase() + { + super( Material.rock ); + } + + protected abstract IBlockState getDefaultBlockState( PeripheralType type, EnumFacing placedSide ); + protected abstract PeripheralType getPeripheralType( int damage ); + protected abstract PeripheralType getPeripheralType( IBlockState state ); + protected abstract TilePeripheralBase createTile( PeripheralType type ); + + @Override + public final boolean isOpaqueCube() + { + return false; + } + + @Override + public final boolean isFullCube() + { + return false; + } + + @Override + public final boolean canPlaceBlockOnSide( World world, BlockPos pos, EnumFacing side ) + { + return true; // ItemPeripheralBase handles this + } + + @Override + protected final IBlockState getDefaultBlockState( int damage, EnumFacing placedSide ) + { + ItemPeripheralBase item = (ItemPeripheralBase)Item.getItemFromBlock( this ); + return getDefaultBlockState( item.getPeripheralType( damage ), placedSide ); + } + + @Override + public final TileGeneric createTile( IBlockState state ) + { + return createTile( getPeripheralType( state ) ); + } + + @Override + public final TileGeneric createTile( int damage ) + { + return createTile( getPeripheralType( damage ) ); + } + + public final PeripheralType getPeripheralType( IBlockAccess world, BlockPos pos ) + { + return getPeripheralType( world.getBlockState( pos ) ); + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/common/BlockPeripheralVariant.java b/src/main/java/dan200/computercraft/shared/peripheral/common/BlockPeripheralVariant.java new file mode 100644 index 0000000000..15e403c176 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/common/BlockPeripheralVariant.java @@ -0,0 +1,149 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.common; + +import dan200.computercraft.shared.peripheral.PeripheralType; +import net.minecraft.util.IStringSerializable; + +public enum BlockPeripheralVariant implements IStringSerializable +{ + DiskDriveEmpty( "disk_drive_empty", PeripheralType.DiskDrive ), + DiskDriveFull( "disk_drive_full", PeripheralType.DiskDrive ), + DiskDriveInvalid( "disk_drive_invalid", PeripheralType.DiskDrive ), + PrinterEmpty( "printer_empty", PeripheralType.Printer ), + PrinterTopFull( "printer_top_full", PeripheralType.Printer ), + PrinterBottomFull( "printer_bottom_full", PeripheralType.Printer ), + PrinterBothFull( "printer_both_full", PeripheralType.Printer ), + WirelessModemOff( "wireless_modem_off", PeripheralType.WirelessModem ), + WirelessModemOn( "wireless_modem_on", PeripheralType.WirelessModem ), + WirelessModemUpOff( "wireless_modem_up_off", PeripheralType.WirelessModem ), + WirelessModemUpOn( "wireless_modem_up_on", PeripheralType.WirelessModem ), + WirelessModemDownOff( "wireless_modem_down_off", PeripheralType.WirelessModem ), + WirelessModemDownOn( "wireless_modem_down_on", PeripheralType.WirelessModem ), + Monitor( "monitor", PeripheralType.Monitor ), + MonitorR( "monitor_r", PeripheralType.Monitor ), + MonitorLR( "monitor_lr", PeripheralType.Monitor ), + MonitorL( "monitor_l", PeripheralType.Monitor ), + MonitorD( "monitor_d", PeripheralType.Monitor ), + MonitorUD( "monitor_ud", PeripheralType.Monitor ), + MonitorU( "monitor_u", PeripheralType.Monitor ), + MonitorRD( "monitor_rd", PeripheralType.Monitor ), + MonitorLRD( "monitor_lrd", PeripheralType.Monitor ), + MonitorLD( "monitor_ld", PeripheralType.Monitor ), + MonitorRUD( "monitor_rud", PeripheralType.Monitor ), + MonitorLRUD( "monitor_lrud", PeripheralType.Monitor ), + MonitorLUD( "monitor_lud", PeripheralType.Monitor ), + MonitorRU( "monitor_ru", PeripheralType.Monitor ), + MonitorLRU( "monitor_lru", PeripheralType.Monitor ), + MonitorLU( "monitor_lu", PeripheralType.Monitor ), + MonitorUp( "monitor_up", PeripheralType.Monitor ), + MonitorUpR( "monitor_up_r", PeripheralType.Monitor ), + MonitorUpLR( "monitor_up_lr", PeripheralType.Monitor ), + MonitorUpL( "monitor_up_l", PeripheralType.Monitor ), + MonitorUpD( "monitor_up_d", PeripheralType.Monitor ), + MonitorUpUD( "monitor_up_ud", PeripheralType.Monitor ), + MonitorUpU( "monitor_up_u", PeripheralType.Monitor ), + MonitorUpRD( "monitor_up_rd", PeripheralType.Monitor ), + MonitorUpLRD( "monitor_up_lrd", PeripheralType.Monitor ), + MonitorUpLD( "monitor_up_ld", PeripheralType.Monitor ), + MonitorUpRUD( "monitor_up_rud", PeripheralType.Monitor ), + MonitorUpLRUD( "monitor_up_lrud", PeripheralType.Monitor ), + MonitorUpLUD( "monitor_up_lud", PeripheralType.Monitor ), + MonitorUpRU( "monitor_up_ru", PeripheralType.Monitor ), + MonitorUpLRU( "monitor_up_lru", PeripheralType.Monitor ), + MonitorUpLU( "monitor_up_lu", PeripheralType.Monitor ), + MonitorDown( "monitor_down", PeripheralType.Monitor ), + MonitorDownR( "monitor_down_r", PeripheralType.Monitor ), + MonitorDownLR( "monitor_down_lr", PeripheralType.Monitor ), + MonitorDownL( "monitor_down_l", PeripheralType.Monitor ), + MonitorDownD( "monitor_down_d", PeripheralType.Monitor ), + MonitorDownUD( "monitor_down_ud", PeripheralType.Monitor ), + MonitorDownU( "monitor_down_u", PeripheralType.Monitor ), + MonitorDownRD( "monitor_down_rd", PeripheralType.Monitor ), + MonitorDownLRD( "monitor_down_lrd", PeripheralType.Monitor ), + MonitorDownLD( "monitor_down_ld", PeripheralType.Monitor ), + MonitorDownRUD( "monitor_down_rud", PeripheralType.Monitor ), + MonitorDownLRUD( "monitor_down_lrud", PeripheralType.Monitor ), + MonitorDownLUD( "monitor_down_lud", PeripheralType.Monitor ), + MonitorDownRU( "monitor_down_ru", PeripheralType.Monitor ), + MonitorDownLRU( "monitor_down_lru", PeripheralType.Monitor ), + MonitorDownLU( "monitor_down_lu", PeripheralType.Monitor ), + AdvancedMonitor( "advanced_monitor", PeripheralType.AdvancedMonitor ), + AdvancedMonitorR( "advanced_monitor_r", PeripheralType.AdvancedMonitor ), + AdvancedMonitorLR( "advanced_monitor_lr", PeripheralType.AdvancedMonitor ), + AdvancedMonitorL( "advanced_monitor_l", PeripheralType.AdvancedMonitor ), + AdvancedMonitorD( "advanced_monitor_d", PeripheralType.AdvancedMonitor ), + AdvancedMonitorUD( "advanced_monitor_ud", PeripheralType.AdvancedMonitor ), + AdvancedMonitorU( "advanced_monitor_u", PeripheralType.AdvancedMonitor ), + AdvancedMonitorRD( "advanced_monitor_rd", PeripheralType.AdvancedMonitor ), + AdvancedMonitorLRD( "advanced_monitor_lrd", PeripheralType.AdvancedMonitor ), + AdvancedMonitorLD( "advanced_monitor_ld", PeripheralType.AdvancedMonitor ), + AdvancedMonitorRUD( "advanced_monitor_rud", PeripheralType.AdvancedMonitor ), + AdvancedMonitorLRUD( "advanced_monitor_lrud", PeripheralType.AdvancedMonitor ), + AdvancedMonitorLUD( "advanced_monitor_lud", PeripheralType.AdvancedMonitor ), + AdvancedMonitorRU( "advanced_monitor_ru", PeripheralType.AdvancedMonitor ), + AdvancedMonitorLRU( "advanced_monitor_lru", PeripheralType.AdvancedMonitor ), + AdvancedMonitorLU( "advanced_monitor_lu", PeripheralType.AdvancedMonitor ), + AdvancedMonitorUp( "advanced_monitor_up", PeripheralType.AdvancedMonitor ), + AdvancedMonitorUpR( "advanced_monitor_up_r", PeripheralType.AdvancedMonitor ), + AdvancedMonitorUpLR( "advanced_monitor_up_lr", PeripheralType.AdvancedMonitor ), + AdvancedMonitorUpL( "advanced_monitor_up_l", PeripheralType.AdvancedMonitor ), + AdvancedMonitorUpD( "advanced_monitor_up_d", PeripheralType.AdvancedMonitor ), + AdvancedMonitorUpUD( "advanced_monitor_up_ud", PeripheralType.AdvancedMonitor ), + AdvancedMonitorUpU( "advanced_monitor_up_u", PeripheralType.AdvancedMonitor ), + AdvancedMonitorUpRD( "advanced_monitor_up_rd", PeripheralType.AdvancedMonitor ), + AdvancedMonitorUpLRD( "advanced_monitor_up_lrd", PeripheralType.AdvancedMonitor ), + AdvancedMonitorUpLD( "advanced_monitor_up_ld", PeripheralType.AdvancedMonitor ), + AdvancedMonitorUpRUD( "advanced_monitor_up_rud", PeripheralType.AdvancedMonitor ), + AdvancedMonitorUpLRUD( "advanced_monitor_up_lrud", PeripheralType.AdvancedMonitor ), + AdvancedMonitorUpLUD( "advanced_monitor_up_lud", PeripheralType.AdvancedMonitor ), + AdvancedMonitorUpRU( "advanced_monitor_up_ru", PeripheralType.AdvancedMonitor ), + AdvancedMonitorUpLRU( "advanced_monitor_up_lru", PeripheralType.AdvancedMonitor ), + AdvancedMonitorUpLU( "advanced_monitor_up_lu", PeripheralType.AdvancedMonitor ), + AdvancedMonitorDown( "advanced_monitor_down", PeripheralType.AdvancedMonitor ), + AdvancedMonitorDownR( "advanced_monitor_down_r", PeripheralType.AdvancedMonitor ), + AdvancedMonitorDownLR( "advanced_monitor_down_lr", PeripheralType.AdvancedMonitor ), + AdvancedMonitorDownL( "advanced_monitor_down_l", PeripheralType.AdvancedMonitor ), + AdvancedMonitorDownD( "advanced_monitor_down_d", PeripheralType.AdvancedMonitor ), + AdvancedMonitorDownUD( "advanced_monitor_down_ud", PeripheralType.AdvancedMonitor ), + AdvancedMonitorDownU( "advanced_monitor_down_u", PeripheralType.AdvancedMonitor ), + AdvancedMonitorDownRD( "advanced_monitor_down_rd", PeripheralType.AdvancedMonitor ), + AdvancedMonitorDownLRD( "advanced_monitor_down_lrd", PeripheralType.AdvancedMonitor ), + AdvancedMonitorDownLD( "advanced_monitor_down_ld", PeripheralType.AdvancedMonitor ), + AdvancedMonitorDownRUD( "advanced_monitor_down_rud", PeripheralType.AdvancedMonitor ), + AdvancedMonitorDownLRUD( "advanced_monitor_down_lrud", PeripheralType.AdvancedMonitor ), + AdvancedMonitorDownLUD( "advanced_monitor_down_lud", PeripheralType.AdvancedMonitor ), + AdvancedMonitorDownRU( "advanced_monitor_down_ru", PeripheralType.AdvancedMonitor ), + AdvancedMonitorDownLRU( "advanced_monitor_down_lru", PeripheralType.AdvancedMonitor ), + AdvancedMonitorDownLU( "advanced_monitor_down_lu", PeripheralType.AdvancedMonitor ); + + private String m_name; + private PeripheralType m_peripheralType; + + private BlockPeripheralVariant( String name, PeripheralType peripheralType ) + { + m_name = name; + m_peripheralType = peripheralType; + } + + @Override + public String getName() + { + return m_name; + } + + public PeripheralType getPeripheralType() + { + return m_peripheralType; + } + + @Override + public String toString() + { + return getName(); + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/common/DefaultPeripheralProvider.java b/src/main/java/dan200/computercraft/shared/peripheral/common/DefaultPeripheralProvider.java new file mode 100644 index 0000000000..6937282d83 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/common/DefaultPeripheralProvider.java @@ -0,0 +1,57 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.common; + +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.api.peripheral.IPeripheralProvider; +import dan200.computercraft.shared.computer.blocks.ComputerPeripheral; +import dan200.computercraft.shared.computer.blocks.TileComputerBase; +import dan200.computercraft.shared.turtle.blocks.TileTurtle; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +public class DefaultPeripheralProvider implements IPeripheralProvider +{ + public DefaultPeripheralProvider() + { + } + + @Override + public IPeripheral getPeripheral( World world, BlockPos pos, EnumFacing side ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null ) + { + // Handle our peripherals + if( tile instanceof IPeripheralTile ) + { + IPeripheralTile peripheralTile = (IPeripheralTile)tile; + return peripheralTile.getPeripheral( side ); + } + + // Handle our computers + if( tile instanceof TileComputerBase ) + { + TileComputerBase computerTile = (TileComputerBase)tile; + if( tile instanceof TileTurtle ) + { + if( !((TileTurtle)tile).hasMoved() ) + { + return new ComputerPeripheral( "turtle", computerTile.createServerComputer() ); + } + } + else + { + return new ComputerPeripheral( "computer", computerTile.createServerComputer() ); + } + } + } + return null; + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/common/IPeripheralItem.java b/src/main/java/dan200/computercraft/shared/peripheral/common/IPeripheralItem.java new file mode 100644 index 0000000000..ae5b199f79 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/common/IPeripheralItem.java @@ -0,0 +1,15 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.common; + +import dan200.computercraft.shared.peripheral.PeripheralType; +import net.minecraft.item.ItemStack; + +public interface IPeripheralItem +{ + public PeripheralType getPeripheralType( ItemStack stack ); +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/common/IPeripheralTile.java b/src/main/java/dan200/computercraft/shared/peripheral/common/IPeripheralTile.java new file mode 100644 index 0000000000..d3052e995f --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/common/IPeripheralTile.java @@ -0,0 +1,19 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.common; + +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.shared.common.IDirectionalTile; +import dan200.computercraft.shared.peripheral.PeripheralType; +import net.minecraft.util.EnumFacing; + +public interface IPeripheralTile extends IDirectionalTile +{ + public PeripheralType getPeripheralType(); + public IPeripheral getPeripheral( EnumFacing side ); + public String getLabel(); +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/common/ItemAdvancedModem.java b/src/main/java/dan200/computercraft/shared/peripheral/common/ItemAdvancedModem.java new file mode 100644 index 0000000000..1849e91744 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/common/ItemAdvancedModem.java @@ -0,0 +1,61 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.common; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.peripheral.PeripheralType; +import net.minecraft.block.Block; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +import java.util.List; + +public class ItemAdvancedModem extends ItemPeripheralBase +{ + public ItemAdvancedModem( Block block ) + { + super( block ); + setUnlocalizedName( "computercraft:advanced_modem" ); + setCreativeTab( ComputerCraft.mainCreativeTab ); + } + + public ItemStack create( PeripheralType type, String label, int quantity ) + { + ItemStack stack; + switch( type ) + { + case AdvancedModem: + { + stack = new ItemStack( this, quantity, 0 ); + break; + } + default: + { + // Ignore types we can't handle + return null; + } + } + if( label != null ) + { + stack.setStackDisplayName( label ); + } + return stack; + } + + @Override + public void getSubItems( Item itemID, CreativeTabs tabs, List list ) + { + list.add( PeripheralItemFactory.create( PeripheralType.AdvancedModem, null, 1 ) ); + } + + @Override + public PeripheralType getPeripheralType( int damage ) + { + return PeripheralType.AdvancedModem; + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/common/ItemCable.java b/src/main/java/dan200/computercraft/shared/peripheral/common/ItemCable.java new file mode 100644 index 0000000000..557212698a --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/common/ItemCable.java @@ -0,0 +1,174 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.common; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.peripheral.PeripheralType; +import dan200.computercraft.shared.peripheral.modem.TileCable; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +import java.util.List; + +public class ItemCable extends ItemPeripheralBase +{ + public ItemCable( Block block ) + { + super( block ); + setUnlocalizedName( "computercraft:cable" ); + setCreativeTab( ComputerCraft.mainCreativeTab ); + } + + public ItemStack create( PeripheralType type, String label, int quantity ) + { + ItemStack stack; + switch( type ) + { + case Cable: + { + stack = new ItemStack( this, quantity, 0 ); + break; + } + case WiredModem: + { + stack = new ItemStack( this, quantity, 1 ); + break; + } + default: + { + return null; + } + } + if( label != null ) + { + stack.setStackDisplayName( label ); + } + return stack; + } + + @Override + public void getSubItems( Item itemID, CreativeTabs tabs, List list ) + { + list.add( PeripheralItemFactory.create( PeripheralType.WiredModem, null, 1 ) ); + list.add( PeripheralItemFactory.create( PeripheralType.Cable, null, 1 ) ); + } + + @Override + public boolean onItemUse( ItemStack stack, EntityPlayer player, World world, BlockPos pos, EnumFacing side, float fx, float fy, float fz ) + { + if( !canPlaceBlockOnSide( world, pos, side, player, stack ) ) + { + return false; + } + + // Try to add a cable to a modem + PeripheralType type = getPeripheralType( stack ); + Block existing = world.getBlockState( pos ).getBlock(); + IBlockState existingState = world.getBlockState( pos ); + if( existing == ComputerCraft.Blocks.cable ) + { + PeripheralType existingType = ComputerCraft.Blocks.cable.getPeripheralType( world, pos ); + if( existingType == PeripheralType.WiredModem && type == PeripheralType.Cable ) + { + if( stack.stackSize > 0 ) + { + world.setBlockState( pos, existingState.withProperty( BlockCable.Properties.CABLE, true ), 3 ); + world.playSoundEffect( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, ComputerCraft.Blocks.cable.stepSound.getBreakSound(), (ComputerCraft.Blocks.cable.stepSound.getVolume() + 1.0F) / 2.0F, ComputerCraft.Blocks.cable.stepSound.getFrequency() * 0.8F); + stack.stackSize--; + + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileCable ) + { + TileCable cable = (TileCable)tile; + cable.networkChanged(); + } + return true; + } + return false; + } + } + + // Try to add on the side of something + if( existing != Blocks.air && (type == PeripheralType.Cable || existing.isSideSolid( world, pos, side )) ) + { + BlockPos offset = pos.offset( side ); + Block offsetExisting = world.getBlockState( offset ).getBlock(); + IBlockState offsetExistingState = world.getBlockState( offset ); + if( offsetExisting == ComputerCraft.Blocks.cable ) + { + // Try to add a modem to a cable + PeripheralType offsetExistingType = ComputerCraft.Blocks.cable.getPeripheralType( world, offset ); + if( offsetExistingType == PeripheralType.Cable && type == PeripheralType.WiredModem ) + { + if( stack.stackSize > 0 ) + { + world.setBlockState( offset, offsetExistingState.withProperty( BlockCable.Properties.MODEM, BlockCableModemVariant.fromFacing( side.getOpposite() ) ), 3 ); + world.playSoundEffect( offset.getX() + 0.5, offset.getY() + 0.5, offset.getZ() + 0.5, ComputerCraft.Blocks.cable.stepSound.getBreakSound(), (ComputerCraft.Blocks.cable.stepSound.getVolume() + 1.0F) / 2.0F, ComputerCraft.Blocks.cable.stepSound.getFrequency() * 0.8F); + stack.stackSize--; + + TileEntity tile = world.getTileEntity( offset ); + if( tile != null && tile instanceof TileCable ) + { + TileCable cable = (TileCable)tile; + cable.networkChanged(); + } + return true; + } + return false; + } + + // Try to add a cable to a modem + if( offsetExistingType == PeripheralType.WiredModem && type == PeripheralType.Cable ) + { + if( stack.stackSize > 0 ) + { + world.setBlockState( offset, offsetExistingState.withProperty( BlockCable.Properties.CABLE, true ), 3 ); + world.playSoundEffect( offset.getX() + 0.5, offset.getY() + 0.5, offset.getZ() + 0.5, ComputerCraft.Blocks.cable.stepSound.getBreakSound(), (ComputerCraft.Blocks.cable.stepSound.getVolume() + 1.0F) / 2.0F, ComputerCraft.Blocks.cable.stepSound.getFrequency() * 0.8F); + stack.stackSize--; + + TileEntity tile = world.getTileEntity( offset ); + if( tile != null && tile instanceof TileCable ) + { + TileCable cable = (TileCable)tile; + cable.networkChanged(); + } + return true; + } + return false; + } + } + } + + return super.onItemUse( stack, player, world, pos, side, fx, fy, fz ); + } + + @Override + public PeripheralType getPeripheralType( int damage ) + { + switch( damage ) + { + case 0: + default: + { + return PeripheralType.Cable; + } + case 1: + { + return PeripheralType.WiredModem; + } + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/common/ItemPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/common/ItemPeripheral.java new file mode 100644 index 0000000000..7d87115e83 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/common/ItemPeripheral.java @@ -0,0 +1,108 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.common; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.peripheral.PeripheralType; +import net.minecraft.block.Block; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +import java.util.List; + +public class ItemPeripheral extends ItemPeripheralBase +{ + public ItemPeripheral( Block block ) + { + super( block ); + setUnlocalizedName( "computercraft:peripheral" ); + setCreativeTab( ComputerCraft.mainCreativeTab ); + } + + public ItemStack create( PeripheralType type, String label, int quantity ) + { + ItemStack stack; + switch( type ) + { + case DiskDrive: + { + stack = new ItemStack( this, quantity, 0 ); + break; + } + case WirelessModem: + { + stack = new ItemStack( this, quantity, 1 ); + break; + } + case Monitor: + { + stack = new ItemStack( this, quantity, 2 ); + break; + } + case Printer: + { + stack = new ItemStack( this, quantity, 3 ); + break; + } + case AdvancedMonitor: + { + stack = new ItemStack( this, quantity, 4 ); + break; + } + default: + { + // Ignore types we can't handle + return null; + } + } + if( label != null ) + { + stack.setStackDisplayName( label ); + } + return stack; + } + + @Override + public void getSubItems( Item itemID, CreativeTabs tabs, List list ) + { + list.add( PeripheralItemFactory.create( PeripheralType.DiskDrive, null, 1 ) ); + list.add( PeripheralItemFactory.create( PeripheralType.Printer, null, 1 ) ); + list.add( PeripheralItemFactory.create( PeripheralType.Monitor, null, 1 ) ); + list.add( PeripheralItemFactory.create( PeripheralType.AdvancedMonitor, null, 1 ) ); + list.add( PeripheralItemFactory.create( PeripheralType.WirelessModem, null, 1 ) ); + } + + @Override + public PeripheralType getPeripheralType( int damage ) + { + switch( damage ) + { + case 0: + default: + { + return PeripheralType.DiskDrive; + } + case 1: + { + return PeripheralType.WirelessModem; + } + case 2: + { + return PeripheralType.Monitor; + } + case 3: + { + return PeripheralType.Printer; + } + case 4: + { + return PeripheralType.AdvancedMonitor; + } + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/common/ItemPeripheralBase.java b/src/main/java/dan200/computercraft/shared/peripheral/common/ItemPeripheralBase.java new file mode 100644 index 0000000000..99fc52bce6 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/common/ItemPeripheralBase.java @@ -0,0 +1,108 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.common; + +import dan200.computercraft.shared.peripheral.PeripheralType; +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +public abstract class ItemPeripheralBase extends ItemBlock implements IPeripheralItem +{ + protected ItemPeripheralBase( Block block ) + { + super( block ); + setMaxStackSize( 64 ); + setHasSubtypes( true ); + } + + public abstract PeripheralType getPeripheralType( int damage ); + + @Override + public final int getMetadata( int damage ) + { + return damage; + } + + @Override + public boolean canPlaceBlockOnSide( World world, BlockPos pos, EnumFacing side, EntityPlayer player, ItemStack stack ) // canPlaceItemBlockOnSide + { + PeripheralType type = getPeripheralType( stack ); + switch( type ) + { + case WirelessModem: + case WiredModem: + case AdvancedModem: + { + return world.isSideSolid( pos, side ); + } + case Cable: + { + return true; + } + default: + { + return super.canPlaceBlockOnSide( world, pos, side, player, stack ); + } + } + } + + @Override + public String getUnlocalizedName( ItemStack stack ) + { + PeripheralType type = getPeripheralType( stack ); + switch( type ) + { + case DiskDrive: + default: + { + return "tile.computercraft:drive"; + } + case Printer: + { + return "tile.computercraft:printer"; + } + case Monitor: + { + return "tile.computercraft:monitor"; + } + case AdvancedMonitor: + { + return "tile.computercraft:advanced_monitor"; + } + case WirelessModem: + { + return "tile.computercraft:wireless_modem"; + } + case WiredModem: + case WiredModemWithCable: + { + return "tile.computercraft:wired_modem"; + } + case Cable: + { + return "tile.computercraft:cable"; + } + case AdvancedModem: + { + return "tile.computercraft:advanced_modem"; + } + } + } + + // IPeripheralItem implementation + + @Override + public final PeripheralType getPeripheralType( ItemStack stack ) + { + return getPeripheralType( stack.getItemDamage() ); + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/common/PeripheralItemFactory.java b/src/main/java/dan200/computercraft/shared/peripheral/common/PeripheralItemFactory.java new file mode 100644 index 0000000000..55768d3bfc --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/common/PeripheralItemFactory.java @@ -0,0 +1,48 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.common; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.peripheral.PeripheralType; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +public class PeripheralItemFactory +{ + public static ItemStack create( IPeripheralTile tile ) + { + return create( tile.getPeripheralType(), tile.getLabel(), 1 ); + } + + public static ItemStack create( PeripheralType type, String label, int quantity ) + { + ItemPeripheral peripheral = ((ItemPeripheral)Item.getItemFromBlock( ComputerCraft.Blocks.peripheral )); + ItemCable cable = ((ItemCable)Item.getItemFromBlock( ComputerCraft.Blocks.cable )); + ItemAdvancedModem advancedModem = ((ItemAdvancedModem)Item.getItemFromBlock( ComputerCraft.Blocks.advancedModem )); + switch( type ) + { + case DiskDrive: + case Printer: + case Monitor: + case AdvancedMonitor: + case WirelessModem: + { + return peripheral.create( type, label, quantity ); + } + case WiredModem: + case Cable: + { + return cable.create( type, label, quantity ); + } + case AdvancedModem: + { + return advancedModem.create( type, label, quantity ); + } + } + return null; + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/common/TilePeripheralBase.java b/src/main/java/dan200/computercraft/shared/peripheral/common/TilePeripheralBase.java new file mode 100644 index 0000000000..294e6bdb5f --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/common/TilePeripheralBase.java @@ -0,0 +1,192 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.common; + +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.shared.common.IDirectionalTile; +import dan200.computercraft.shared.common.TileGeneric; +import dan200.computercraft.shared.peripheral.PeripheralType; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ITickable; +import net.minecraft.util.EnumFacing; + +import java.util.List; + +public abstract class TilePeripheralBase extends TileGeneric + implements IPeripheralTile, IDirectionalTile, ITickable +{ + // Statics + + private EnumFacing m_dir; + private int m_anim; + private boolean m_changed; + + private String m_label; + + public TilePeripheralBase() + { + m_dir = EnumFacing.NORTH; + m_anim = 0; + m_changed = false; + + m_label = null; + } + + + @Override + public BlockPeripheralBase getBlock() + { + return (BlockPeripheralBase)super.getBlock(); + } + + @Override + public void getDroppedItems( List drops, int fortune, boolean creative, boolean silkTouch ) + { + if( !creative ) + { + drops.add( PeripheralItemFactory.create( this ) ); + } + } + + @Override + public ItemStack getPickedItem() + { + return PeripheralItemFactory.create( this ); + } + + // IPeripheralTile implementation + + @Override + public final PeripheralType getPeripheralType() + { + return getBlock().getPeripheralType( getBlockState() ); + } + + @Override + public IPeripheral getPeripheral( EnumFacing side ) + { + return null; + } + + @Override + public String getLabel() + { + if( m_label != null && m_label.length() > 0 ) + { + return m_label; + } + return null; + } + + public void setLabel( String label ) + { + m_label = label; + } + + // IDirectionalTile implementation + + @Override + public EnumFacing getDirection() + { + return m_dir; + } + + @Override + public void setDirection( EnumFacing dir ) + { + if( dir != m_dir ) + { + m_dir = dir; + m_changed = true; + } + } + + public synchronized int getAnim() + { + return m_anim; + } + + public synchronized void setAnim( int anim ) + { + if( anim != m_anim ) + { + m_anim = anim; + m_changed = true; + } + } + + @Override + public synchronized void update() + { + if( m_changed ) + { + updateBlock(); + m_changed = false; + } + } + + @Override + public void readFromNBT( NBTTagCompound nbttagcompound ) + { + // Read properties + super.readFromNBT(nbttagcompound); + if( nbttagcompound.hasKey( "dir" ) ) + { + m_dir = EnumFacing.getFront( nbttagcompound.getInteger( "dir" ) ); + } + if( nbttagcompound.hasKey( "anim" ) ) + { + m_anim = nbttagcompound.getInteger( "anim" ); + } + if( nbttagcompound.hasKey( "label" ) ) + { + m_label = nbttagcompound.getString( "label" ); + } + } + + @Override + public void writeToNBT( NBTTagCompound nbttagcompound ) + { + // Write properties + super.writeToNBT( nbttagcompound ); + nbttagcompound.setInteger( "dir", m_dir.getIndex() ); + nbttagcompound.setInteger( "anim", m_anim ); + if( m_label != null ) + { + nbttagcompound.setString( "label", m_label ); + } + } + + @Override + public void readDescription( NBTTagCompound nbttagcompound ) + { + super.readDescription( nbttagcompound ); + m_dir = EnumFacing.getFront( nbttagcompound.getInteger( "dir" ) ); + m_anim = nbttagcompound.getInteger( "anim" ); + if( nbttagcompound.hasKey( "label" ) ) + { + m_label = nbttagcompound.getString( "label" ); + } + else + { + m_label = null; + } + } + + @Override + public void writeDescription( NBTTagCompound nbttagcompound ) + { + super.writeDescription( nbttagcompound ); + nbttagcompound.setInteger( "dir", m_dir.getIndex() ); + nbttagcompound.setInteger( "anim", m_anim ); + if( m_label != null ) + { + nbttagcompound.setString( "label", m_label ); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/ContainerDiskDrive.java b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/ContainerDiskDrive.java new file mode 100644 index 0000000000..d74fb87160 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/ContainerDiskDrive.java @@ -0,0 +1,85 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.diskdrive; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; + +public class ContainerDiskDrive extends Container +{ + private final TileDiskDrive m_diskDrive; + + public ContainerDiskDrive( IInventory playerInventory, TileDiskDrive diskDrive ) + { + m_diskDrive = diskDrive; + addSlotToContainer(new Slot( m_diskDrive, 0, 8 + 4 * 18, 35)); + + for(int j = 0; j < 3; j++) + { + for(int i1 = 0; i1 < 9; i1++) + { + addSlotToContainer(new Slot(playerInventory, i1 + j * 9 + 9, 8 + i1 * 18, 84 + j * 18)); + } + } + + for(int k = 0; k < 9; k++) + { + addSlotToContainer(new Slot(playerInventory, k, 8 + k * 18, 142)); + } + } + + @Override + public boolean canInteractWith( EntityPlayer player ) + { + return m_diskDrive.isUseableByPlayer( player ); + } + + @Override + public ItemStack transferStackInSlot( EntityPlayer player, int i ) + { + ItemStack itemstack = null; + Slot slot = (Slot)inventorySlots.get(i); + if(slot != null && slot.getHasStack()) + { + ItemStack itemstack1 = slot.getStack(); + itemstack = itemstack1.copy(); + if(i == 0 ) + { + if(!mergeItemStack(itemstack1, 1, 37, true)) + { + return null; + } + } + else if( !mergeItemStack(itemstack1, 0, 1, false) ) + { + return null; + } + + if(itemstack1.stackSize == 0) + { + slot.putStack(null); + } + else + { + slot.onSlotChanged(); + } + + if(itemstack1.stackSize != itemstack.stackSize) + { + slot.onPickupFromSlot(player, itemstack1); + } + else + { + return null; + } + } + return itemstack; + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDrivePeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDrivePeripheral.java new file mode 100644 index 0000000000..e48826a3b1 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDrivePeripheral.java @@ -0,0 +1,199 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.diskdrive; + +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.media.IMedia; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.shared.media.items.ItemDiskLegacy; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +public class DiskDrivePeripheral implements IPeripheral +{ + private final TileDiskDrive m_diskDrive; + + public DiskDrivePeripheral( TileDiskDrive diskDrive ) + { + m_diskDrive = diskDrive; + } + + @Override + public String getType() + { + return "drive"; + } + + @Override + public String[] getMethodNames() + { + return new String[] { + "isDiskPresent", + "getDiskLabel", + "setDiskLabel", + "hasData", + "getMountPath", + "hasAudio", + "getAudioTitle", + "playAudio", + "stopAudio", + "ejectDisk", + "getDiskID" + }; + } + + @Override + public Object[] callMethod( IComputerAccess computer, ILuaContext context, int method, Object[] arguments ) throws LuaException + { + switch( method ) + { + case 0: + { + // isPresent + return new Object[] { + m_diskDrive.getDiskStack() != null + }; + } + case 1: + { + // getDiskLabel + IMedia media = m_diskDrive.getDiskMedia(); + if( media != null ) + { + return new Object[] { media.getLabel( m_diskDrive.getDiskStack() ) }; + } + return null; + } + case 2: + { + // setDiskLabel + String label = null; + if( arguments.length > 0 ) + { + if( arguments[0] != null && !(arguments[0] instanceof String) ) + { + throw new LuaException( "Expected string" ); + } + label = (String)arguments[0]; + } + + IMedia media = m_diskDrive.getDiskMedia(); + if( media != null ) + { + ItemStack disk = m_diskDrive.getDiskStack(); + if( media.setLabel( disk, label ) ) + { + m_diskDrive.setDiskStack( disk ); + } + else + { + throw new LuaException( "Disk label cannot be changed" ); + } + } + return null; + } + case 3: + { + // hasData + return new Object[] { + m_diskDrive.getDiskMountPath( computer ) != null + }; + } + case 4: + { + // getMountPath + return new Object[] { + m_diskDrive.getDiskMountPath( computer ) + }; + } + case 5: + { + // hasAudio + IMedia media = m_diskDrive.getDiskMedia(); + if( media != null ) + { + return new Object[] { media.getAudioRecordName( m_diskDrive.getDiskStack() ) != null }; + } + return new Object[] { false }; + } + case 6: + { + // getAudioTitle + IMedia media = m_diskDrive.getDiskMedia(); + if( media != null ) + { + return new Object[] { media.getAudioTitle( m_diskDrive.getDiskStack() ) }; + } + return new Object[] { false }; + } + case 7: + { + // playAudio + m_diskDrive.playDiskAudio(); + return null; + } + case 8: + { + // stopAudio + m_diskDrive.stopDiskAudio(); + return null; + } + case 9: + { + // eject + m_diskDrive.ejectDisk(); + return null; + } + case 10: + { + // getDiskID + ItemStack disk = m_diskDrive.getDiskStack(); + if( disk != null ) + { + Item item = disk.getItem(); + if( item instanceof ItemDiskLegacy ) + { + return new Object[] { ((ItemDiskLegacy)item).getDiskID( disk ) }; + } + } + return null; + } + default: + { + return null; + } + } + } + + @Override + public void attach( IComputerAccess computer ) + { + m_diskDrive.mount( computer ); + } + + @Override + public void detach( IComputerAccess computer ) + { + m_diskDrive.unmount( computer ); + } + + @Override + public boolean equals( IPeripheral other ) + { + if( other instanceof DiskDrivePeripheral ) + { + DiskDrivePeripheral otherDiskDrive = (DiskDrivePeripheral)other; + if( otherDiskDrive.m_diskDrive == this.m_diskDrive ) + { + return true; + } + } + return false; + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java new file mode 100644 index 0000000000..96ca3d0342 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java @@ -0,0 +1,683 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.diskdrive; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.filesystem.IMount; +import dan200.computercraft.api.filesystem.IWritableMount; +import dan200.computercraft.api.media.IMedia; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.shared.peripheral.PeripheralType; +import dan200.computercraft.shared.peripheral.common.BlockPeripheral; +import dan200.computercraft.shared.peripheral.common.TilePeripheralBase; +import dan200.computercraft.shared.util.InventoryUtil; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ITickable; +import net.minecraft.util.*; +import net.minecraft.world.World; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +public class TileDiskDrive extends TilePeripheralBase + implements IInventory, ITickable +{ + // Statics + + private static final int BLOCKEVENT_PLAY_RECORD = 0; + private static final int BLOCKEVENT_STOP_RECORD = 1; + + private static class MountInfo + { + public String mountPath; + } + + // Members + + private final Map m_computers; + + private ItemStack m_diskStack; + private IMount m_diskMount; + + private boolean m_recordQueued; + private boolean m_recordPlaying; + private boolean m_restartRecord; + private boolean m_ejectQueued; + + public TileDiskDrive() + { + m_computers = new HashMap(); + + m_diskStack = null; + m_diskMount = null; + + m_recordQueued = false; + m_recordPlaying = false; + m_restartRecord = false; + } + + @Override + public void destroy() + { + ejectContents( true ); + synchronized( this ) + { + if( m_recordPlaying ) + { + sendBlockEvent( BLOCKEVENT_STOP_RECORD ); + } + } + } + + @Override + public boolean onActivate( EntityPlayer player, EnumFacing side, float hitX, float hitY, float hitZ ) + { + if( player.isSneaking() ) + { + // Try to put a disk into the drive + if( !worldObj.isRemote ) + { + ItemStack disk = player.getCurrentEquippedItem(); + if( disk != null && getStackInSlot(0) == null ) + { + if( ComputerCraft.getMedia( disk ) != null ) + { + setInventorySlotContents( 0, disk ); + player.destroyCurrentEquippedItem(); + return true; + } + } + } + } + else + { + // Open the GUI + if( !worldObj.isRemote ) + { + ComputerCraft.openDiskDriveGUI( player, this ); + } + return true; + } + return false; + } + + @Override + public EnumFacing getDirection() + { + IBlockState state = getBlockState(); + return (EnumFacing)state.getValue( BlockPeripheral.Properties.FACING ); + } + + @Override + public void setDirection( EnumFacing dir ) + { + if( dir.getAxis() == EnumFacing.Axis.Y ) + { + dir = EnumFacing.NORTH; + } + setBlockState( getBlockState().withProperty( BlockPeripheral.Properties.FACING, dir ) ); + } + + @Override + public void readFromNBT(NBTTagCompound nbttagcompound) + { + super.readFromNBT(nbttagcompound); + if( nbttagcompound.hasKey( "item" ) ) + { + NBTTagCompound item = nbttagcompound.getCompoundTag( "item" ); + m_diskStack = ItemStack.loadItemStackFromNBT( item ); + m_diskMount = null; + } + } + + @Override + public void writeToNBT(NBTTagCompound nbttagcompound) + { + super.writeToNBT(nbttagcompound); + if( m_diskStack != null ) + { + NBTTagCompound item = new NBTTagCompound(); + m_diskStack.writeToNBT( item ); + nbttagcompound.setTag( "item", item ); + } + } + + @Override + public void update() + { + super.update(); + + // Ejection + synchronized( this ) + { + if( m_ejectQueued ) + { + ejectContents( false ); + m_ejectQueued = false; + } + } + + // Music + synchronized( this ) + { + if( m_recordPlaying != m_recordQueued || m_restartRecord ) + { + m_restartRecord = false; + if( m_recordQueued ) + { + IMedia contents = getDiskMedia(); + String record = (contents != null) ? contents.getAudioRecordName( m_diskStack ) : null; + if( record != null ) + { + m_recordPlaying = true; + sendBlockEvent( BLOCKEVENT_PLAY_RECORD ); + } + else + { + m_recordQueued = false; + } + } + else + { + sendBlockEvent( BLOCKEVENT_STOP_RECORD ); + m_recordPlaying = false; + } + } + } + } + + // IInventory implementation + + @Override + public int getSizeInventory() + { + return 1; + } + + @Override + public ItemStack getStackInSlot(int i) + { + return m_diskStack; + } + + @Override + public ItemStack removeStackFromSlot(int i) + { + ItemStack result = m_diskStack; + m_diskStack = null; + m_diskMount = null; + + return result; + } + + @Override + public ItemStack decrStackSize(int i, int j) + { + if (m_diskStack == null) + { + return null; + } + + if (m_diskStack.stackSize <= j) + { + ItemStack disk = m_diskStack; + setInventorySlotContents( 0, null ); + return disk; + } + + ItemStack part = m_diskStack.splitStack(j); + if (m_diskStack.stackSize == 0) + { + setInventorySlotContents( 0, null ); + } + else + { + setInventorySlotContents( 0, m_diskStack ); + } + return part; + } + + @Override + public void setInventorySlotContents( int i, ItemStack itemStack ) + { + if( worldObj.isRemote ) + { + m_diskStack = itemStack; + m_diskMount = null; + markDirty(); + return; + } + + synchronized( this ) + { + if( InventoryUtil.areItemsStackable( itemStack, m_diskStack ) ) + { + m_diskStack = itemStack; + return; + } + + // Unmount old disk + if( m_diskStack != null ) + { + Set computers = m_computers.keySet(); + Iterator it = computers.iterator(); + while( it.hasNext() ) + { + IComputerAccess computer = it.next(); + unmountDisk( computer ); + } + } + + // Stop music + if( m_recordPlaying ) + { + sendBlockEvent( BLOCKEVENT_STOP_RECORD ); + m_recordPlaying = false; + m_recordQueued = false; + } + + // Swap disk over + m_diskStack = itemStack; + m_diskMount = null; + markDirty(); + + // Update contents + updateAnim(); + + // Mount new disk + if( m_diskStack != null ) + { + Set computers = m_computers.keySet(); + Iterator it = computers.iterator(); + while( it.hasNext() ) + { + IComputerAccess computer = it.next(); + mountDisk( computer ); + } + } + } + } + + @Override + public boolean hasCustomName() + { + return getLabel() != null; + } + + @Override + public String getName() + { + String label = getLabel(); + if( label != null ) + { + return label; + } + else + { + return "tile.computercraft:drive.name"; + } + } + + @Override + public IChatComponent getDisplayName() + { + if( hasCustomName() ) + { + return new ChatComponentText( getName() ); + } + else + { + return new ChatComponentTranslation( getName() ); + } + } + + @Override + public int getInventoryStackLimit() + { + return 64; + } + + @Override + public void openInventory( EntityPlayer player ) + { + } + + @Override + public void closeInventory( EntityPlayer player ) + { + } + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) + { + return true; + } + + @Override + public boolean isUseableByPlayer( EntityPlayer player ) + { + return isUsable( player, false ); + } + + @Override + public void clear() + { + synchronized( this ) + { + setInventorySlotContents( 0, null ); + } + } + + @Override + public int getFieldCount() + { + return 0; + } + + @Override + public int getField(int id) + { + return 0; + } + + @Override + public void setField(int id, int value) + { + } + + // IPeripheralTile implementation + + @Override + public IPeripheral getPeripheral( EnumFacing side ) + { + return new DiskDrivePeripheral( this ); + } + + public ItemStack getDiskStack() + { + synchronized( this ) + { + return getStackInSlot( 0 ); + } + } + + public void setDiskStack( ItemStack stack ) + { + synchronized( this ) + { + setInventorySlotContents( 0, stack ); + } + } + + public IMedia getDiskMedia() + { + return ComputerCraft.getMedia( getDiskStack() ); + } + + public String getDiskMountPath( IComputerAccess computer ) + { + synchronized( this ) + { + if( m_computers.containsKey( computer ) ) + { + MountInfo info = m_computers.get( computer ); + return info.mountPath; + } + } + return null; + } + + public void mount( IComputerAccess computer ) + { + synchronized( this ) + { + m_computers.put( computer, new MountInfo() ); + mountDisk( computer ); + } + } + + public void unmount( IComputerAccess computer ) + { + synchronized( this ) + { + unmountDisk( computer ); + m_computers.remove( computer ); + } + } + + public void playDiskAudio() + { + synchronized( this ) + { + IMedia media = getDiskMedia(); + if( media != null && media.getAudioTitle( m_diskStack ) != null ) + { + m_recordQueued = true; + m_restartRecord = m_recordPlaying; + } + } + } + + public void stopDiskAudio() + { + synchronized( this ) + { + m_recordQueued = false; + m_restartRecord = false; + } + } + + public void ejectDisk() + { + synchronized( this ) + { + if( !m_ejectQueued ) + { + m_ejectQueued = true; + } + } + } + + // private methods + + private synchronized void mountDisk( IComputerAccess computer ) + { + if( m_diskStack != null ) + { + MountInfo info = m_computers.get( computer ); + IMedia contents = getDiskMedia(); + if( contents != null ) + { + if( m_diskMount == null ) + { + m_diskMount = contents.createDataMount( m_diskStack, worldObj ); + } + if( m_diskMount != null ) + { + if( m_diskMount instanceof IWritableMount) + { + // Try mounting at the lowest numbered "disk" name we can + int n = 1; + while( info.mountPath == null ) + { + info.mountPath = computer.mountWritable( (n==1) ? "disk" : ("disk" + n), (IWritableMount)m_diskMount ); + n++; + } + } + else + { + // Try mounting at the lowest numbered "disk" name we can + int n = 1; + while( info.mountPath == null ) + { + info.mountPath = computer.mount( (n==1) ? "disk" : ("disk" + n), m_diskMount ); + n++; + } + } + } + else + { + info.mountPath = null; + } + } + computer.queueEvent( "disk", new Object[] { computer.getAttachmentName() } ); + } + } + + private synchronized void unmountDisk( IComputerAccess computer ) + { + if( m_diskStack != null ) + { + MountInfo info = m_computers.get( computer ); + assert( info != null ); + if( info.mountPath != null ) + { + computer.unmount( info.mountPath ); + info.mountPath = null; + } + computer.queueEvent( "disk_eject", new Object[] { computer.getAttachmentName() } ); + } + } + + private synchronized void updateAnim() + { + if( m_diskStack != null ) + { + IMedia contents = getDiskMedia(); + if( contents != null ) { + setAnim( 2 ); + } else { + setAnim( 1 ); + } + } + else + { + setAnim( 0 ); + } + } + + private synchronized void ejectContents( boolean destroyed ) + { + if( worldObj.isRemote ) + { + return; + } + + if( m_diskStack != null ) + { + // Remove the disks from the inventory + ItemStack disks = m_diskStack; + setInventorySlotContents( 0, null ); + + // Spawn the item in the world + int xOff = 0; + int zOff = 0; + if( !destroyed ) + { + EnumFacing dir = getDirection(); + xOff = dir.getFrontOffsetX(); + zOff = dir.getFrontOffsetZ(); + } + + BlockPos pos = getPos(); + double x = (double)pos.getX() + 0.5 + ((double)xOff * 0.5); + double y = (double)pos.getY() + 0.75; + double z = (double)pos.getZ() + 0.5 + ((double)zOff * 0.5); + EntityItem entityitem = new EntityItem( worldObj, x, y, z, disks ); + entityitem.motionX = (double)xOff * 0.15; + entityitem.motionY = 0.0; + entityitem.motionZ = (double)zOff * 0.15; + + worldObj.spawnEntityInWorld(entityitem); + if( !destroyed ) + { + worldObj.playAuxSFX(1000, getPos(), 0); + } + } + } + + @Override + public final void readDescription( NBTTagCompound nbttagcompound ) + { + super.readDescription( nbttagcompound ); + if( nbttagcompound.hasKey( "item" ) ) + { + m_diskStack = ItemStack.loadItemStackFromNBT( nbttagcompound.getCompoundTag( "item" ) ); + } + else + { + m_diskStack = null; + } + updateBlock(); + } + + @Override + public void writeDescription( NBTTagCompound nbttagcompound ) + { + super.writeDescription( nbttagcompound ); + if( m_diskStack != null ) + { + NBTTagCompound item = new NBTTagCompound(); + m_diskStack.writeToNBT( item ); + nbttagcompound.setTag( "item", item ); + } + } + + @Override + public void onBlockEvent( int eventID, int eventParameter ) + { + super.onBlockEvent( eventID, eventParameter ); + switch( eventID ) + { + case BLOCKEVENT_PLAY_RECORD: + { + playRecord(); + break; + } + case BLOCKEVENT_STOP_RECORD: + { + stopRecord(); + break; + } + } + } + + @Override + public boolean shouldRefresh( World world, BlockPos pos, IBlockState oldState, IBlockState newState ) + { + return super.shouldRefresh( world, pos, oldState, newState ) || ComputerCraft.Blocks.peripheral.getPeripheralType( newState ) != PeripheralType.DiskDrive; + } + + // Private methods + + private void playRecord() + { + IMedia contents = getDiskMedia(); + String record = (contents != null) ? contents.getAudioRecordName( m_diskStack ) : null; + if( record != null ) + { + ComputerCraft.playRecord( record, contents.getAudioTitle( m_diskStack ), worldObj, getPos() ); + } + else + { + ComputerCraft.playRecord( null, null, worldObj, getPos() ); + } + } + + private void stopRecord() + { + ComputerCraft.playRecord( null, null, worldObj, getPos() ); + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/BlockAdvancedModem.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/BlockAdvancedModem.java new file mode 100644 index 0000000000..e13c1a32d5 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/BlockAdvancedModem.java @@ -0,0 +1,117 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.modem; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.peripheral.PeripheralType; +import dan200.computercraft.shared.peripheral.common.BlockPeripheralBase; +import dan200.computercraft.shared.peripheral.common.TilePeripheralBase; +import net.minecraft.block.properties.IProperty; +import net.minecraft.block.properties.PropertyBool; +import net.minecraft.block.properties.PropertyDirection; +import net.minecraft.block.state.BlockState; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +public class BlockAdvancedModem extends BlockPeripheralBase +{ + public static class Properties + { + public static final PropertyDirection FACING = PropertyDirection.create( "facing" ); + public static final PropertyBool ON = PropertyBool.create( "on" ); + } + + public BlockAdvancedModem() + { + setHardness( 2.0f ); + setUnlocalizedName( "computercraft:advanced_modem" ); + setCreativeTab( ComputerCraft.mainCreativeTab ); + setDefaultState( this.blockState.getBaseState() + .withProperty( Properties.FACING, EnumFacing.NORTH ) + .withProperty( Properties.ON, false ) + ); + } + + @Override + protected BlockState createBlockState() + { + return new BlockState(this, new IProperty[] { + Properties.FACING, + Properties.ON + }); + } + + @Override + public IBlockState getStateFromMeta( int meta ) + { + IBlockState state = getDefaultState(); + state = state.withProperty( Properties.FACING, EnumFacing.getFront( meta ) ); + state = state.withProperty( Properties.ON, false ); + return state; + } + + @Override + public int getMetaFromState( IBlockState state ) + { + EnumFacing dir = (EnumFacing) state.getValue( Properties.FACING ); + return dir.getIndex(); + } + + @Override + public IBlockState getActualState( IBlockState state, IBlockAccess world, BlockPos pos ) + { + int anim; + EnumFacing dir; + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TilePeripheralBase ) + { + TilePeripheralBase peripheral = (TilePeripheralBase) tile; + anim = peripheral.getAnim(); + dir = peripheral.getDirection(); + } + else + { + anim = 0; + dir = (EnumFacing)state.getValue( Properties.FACING ); + } + + state = state.withProperty( Properties.FACING, dir ); + state = state.withProperty( Properties.ON, anim > 0 ); + return state; + } + + @Override + public IBlockState getDefaultBlockState( PeripheralType type, EnumFacing placedSide ) + { + EnumFacing dir = placedSide.getOpposite(); + return getDefaultState().withProperty( Properties.FACING, dir ); + } + + @Override + public PeripheralType getPeripheralType( int damage ) + { + return PeripheralType.AdvancedModem; + } + + @Override + public PeripheralType getPeripheralType( IBlockState state ) + { + return PeripheralType.AdvancedModem; + } + + @Override + public TilePeripheralBase createTile( PeripheralType type ) + { + return new TileAdvancedModem(); + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/INetwork.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/INetwork.java new file mode 100644 index 0000000000..983edf787e --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/INetwork.java @@ -0,0 +1,18 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.modem; + +import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +public interface INetwork +{ + public void addReceiver( IReceiver receiver ); + public void removeReceiver( IReceiver receiver ); + public void transmit( int channel, int replyChannel, Object payload, World world, Vec3 pos, double range, boolean interdimensional, Object senderObject ); + public boolean isWireless(); +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/IReceiver.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/IReceiver.java new file mode 100644 index 0000000000..b7eab1287c --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/IReceiver.java @@ -0,0 +1,20 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.modem; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +public interface IReceiver +{ + public int getChannel(); + public World getWorld(); + public Vec3 getWorldPosition(); + public boolean isInterdimensional(); + public double getReceiveRange(); + public void receiveSameDimension( int replyChannel, Object payload, double distance, Object senderObject ); + public void receiveDifferentDimension( int replyChannel, Object payload, Object senderObject ); +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemPeripheral.java new file mode 100644 index 0000000000..d8220f4631 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemPeripheral.java @@ -0,0 +1,406 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.modem; + +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.IPeripheral; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public abstract class ModemPeripheral + implements IPeripheral +{ + private static class SingleChannelReceiver implements IReceiver + { + private ModemPeripheral m_owner; + private int m_channel; + + public SingleChannelReceiver( ModemPeripheral owner, int channel ) + { + m_owner = owner; + m_channel = channel; + } + + // IReceiver implementation + + @Override + public int getChannel() + { + return m_channel; + } + + @Override + public World getWorld() + { + return m_owner.getWorld(); + } + + @Override + public Vec3 getWorldPosition() + { + return m_owner.getWorldPosition(); + } + + @Override + public boolean isInterdimensional() + { + return m_owner.isInterdimensional(); + } + + @Override + public double getReceiveRange() + { + return m_owner.getReceiveRange(); + } + + @Override + public void receiveSameDimension( int replyChannel, Object payload, double distance, Object senderObject ) + { + if( senderObject != m_owner ) + { + m_owner.receiveSameDimension( m_channel, replyChannel, payload, distance ); + } + } + + @Override + public void receiveDifferentDimension( int replyChannel, Object payload, Object senderObject ) + { + if( senderObject != m_owner ) + { + m_owner.receiveDifferentDimension( m_channel, replyChannel, payload ); + } + } + } + + private INetwork m_network; + private IComputerAccess m_computer; + private Map m_channels; + + private boolean m_open; + private boolean m_changed; + + public ModemPeripheral() + { + m_network = null; + m_computer = null; + + m_channels = new HashMap(); + m_open = false; + m_changed = true; + } + + private synchronized void setNetwork( INetwork network ) + { + if( m_network != network ) + { + // Leave old network + if( m_network != null ) + { + Iterator it = m_channels.values().iterator(); + while( it.hasNext() ) + { + m_network.removeReceiver( it.next() ); + } + } + + // Set new network + m_network = network; + + // Join new network + if( m_network != null ) + { + Iterator it = m_channels.values().iterator(); + while( it.hasNext() ) + { + m_network.addReceiver( it.next() ); + } + } + } + } + + protected void switchNetwork() + { + setNetwork( getNetwork() ); + } + + protected abstract World getWorld(); + + protected abstract Vec3 getPosition(); + + public synchronized void destroy() + { + setNetwork( null ); + m_channels.clear(); + m_open = false; + } + + public synchronized boolean pollChanged() + { + if( m_changed ) + { + m_changed = false; + return true; + } + return false; + } + + protected abstract double getTransmitRange(); + + protected abstract boolean isInterdimensional(); + + public synchronized boolean isActive() + { + return (m_computer != null) && m_open; + } + + public synchronized Vec3 getWorldPosition() + { + return getPosition(); + } + + public synchronized double getReceiveRange() + { + return getTransmitRange(); + } + + public void receiveSameDimension( int channel, int replyChannel, Object payload, double distance ) + { + synchronized (m_channels) + { + if( m_computer != null && m_channels.containsKey( channel ) ) + { + m_computer.queueEvent( "modem_message", new Object[] { + m_computer.getAttachmentName(), channel, replyChannel, payload, distance + } ); + } + } + } + + public void receiveDifferentDimension( int channel, int replyChannel, Object payload ) + { + synchronized (m_channels) + { + if( m_computer != null && m_channels.containsKey( channel ) ) + { + m_computer.queueEvent( "modem_message", new Object[] { + m_computer.getAttachmentName(), channel, replyChannel, payload + } ); + } + } + } + + protected abstract INetwork getNetwork(); + + // IPeripheral implementation + + @Override + public String getType() + { + return "modem"; + } + + @Override + public String[] getMethodNames() + { + return new String[] { + "open", + "isOpen", + "close", + "closeAll", + "transmit", + "isWireless", + }; + } + + private static int parseChannel( Object[] arguments, int index ) throws LuaException + { + if( arguments.length <= index || !(arguments[index] instanceof Double) ) + { + throw new LuaException( "Expected number" ); + } + int channel = (int)((Double)arguments[index]).doubleValue(); + if( channel < 0 || channel > 65535 ) + { + throw new LuaException( "Expected number in range 0-65535" ); + } + return channel; + } + + @Override + public Object[] callMethod( IComputerAccess computer, ILuaContext context, int method, Object[] arguments ) throws LuaException, InterruptedException + { + switch( method ) + { + case 0: + { + // open + int channel = parseChannel( arguments, 0 ); + synchronized( this ) + { + if( !m_channels.containsKey( channel ) ) + { + if( m_channels.size() >= 128 ) + { + throw new LuaException( "Too many open channels" ); + } + + IReceiver receiver = new SingleChannelReceiver( this, channel ); + m_channels.put( channel, receiver ); + if( m_network != null ) + { + m_network.addReceiver( receiver ); + } + if( !m_open ) + { + m_open = true; + m_changed = true; + } + } + } + return null; + } + case 1: + { + // isOpen + int channel = parseChannel( arguments, 0 ); + synchronized( this ) + { + boolean open = m_channels.containsKey( channel ); + return new Object[] { open }; + } + } + case 2: + { + // close + int channel = parseChannel( arguments, 0 ); + synchronized( this ) + { + if( m_channels.containsKey( channel ) ) + { + IReceiver receiver = m_channels.get( channel ); + if( m_network != null ) + { + m_network.removeReceiver( receiver ); + } + m_channels.remove( channel ); + + if( m_channels.size() == 0 ) + { + m_open = false; + m_changed = true; + } + } + } + return null; + } + case 3: + { + // closeAll + synchronized( this ) + { + if( m_channels.size() > 0 ) + { + if( m_network != null ) + { + Iterator it = m_channels.values().iterator(); + while( it.hasNext() ) + { + m_network.removeReceiver( it.next() ); + } + } + m_channels.clear(); + + if( m_open ) + { + m_open = false; + m_changed = true; + } + } + } + return null; + } + case 4: + { + // transmit + int channel = parseChannel( arguments, 0 ); + int replyChannel = parseChannel( arguments, 1 ); + Object payload = (arguments.length >= 3) ? arguments[2] : null; + synchronized( this ) + { + World world = getWorld(); + Vec3 position = getPosition(); + if( world != null && position != null && m_network != null) + { + m_network.transmit( channel, replyChannel, payload, world, position, getTransmitRange(), isInterdimensional(), this ); + } + } + return null; + } + case 5: + { + // isWireless + synchronized( this ) + { + if( m_network != null ) + { + return new Object[] { m_network.isWireless() }; + } + } + return new Object[] { false }; + } + default: + { + return null; + } + } + } + + @Override + public synchronized void attach( IComputerAccess computer ) + { + m_computer = computer; + setNetwork( getNetwork() ); + m_open = !m_channels.isEmpty(); + } + + @Override + public synchronized void detach( IComputerAccess computer ) + { + if( m_network != null ) + { + Iterator it = m_channels.values().iterator(); + while( it.hasNext() ) + { + m_network.removeReceiver( it.next() ); + } + m_channels.clear(); + m_network = null; + } + + m_computer = null; + + if( m_open ) + { + m_open = false; + m_changed = true; + } + } + + @Override + public abstract boolean equals( IPeripheral other ); + + public IComputerAccess getComputer() + { + return m_computer; + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/TileAdvancedModem.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/TileAdvancedModem.java new file mode 100644 index 0000000000..37879407ce --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/TileAdvancedModem.java @@ -0,0 +1,84 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.modem; + +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.shared.peripheral.common.BlockPeripheral; +import net.minecraft.block.state.IBlockState; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +public class TileAdvancedModem extends TileModemBase +{ + // Statics + + private static class Peripheral extends WirelessModemPeripheral + { + private TileModemBase m_entity; + + public Peripheral( TileModemBase entity ) + { + super( true ); + m_entity = entity; + } + + @Override + public World getWorld() + { + return m_entity.getWorld(); + } + + @Override + protected Vec3 getPosition() + { + BlockPos pos = m_entity.getPos().offset( m_entity.getDirection() ); + return new Vec3( (double)pos.getX(), (double)pos.getY(), (double)pos.getZ() ); + } + + @Override + public boolean equals( IPeripheral other ) + { + if( other instanceof Peripheral ) + { + Peripheral otherModem = (Peripheral)other; + return otherModem.m_entity == m_entity; + } + return false; + } + } + + // Members + + public TileAdvancedModem() + { + } + + @Override + public EnumFacing getDirection() + { + // Wireless Modem + IBlockState state = getBlockState(); + return (EnumFacing)state.getValue( BlockPeripheral.Properties.FACING ); + } + + @Override + public void setDirection( EnumFacing dir ) + { + // Wireless Modem + setBlockState( getBlockState() + .withProperty( BlockPeripheral.Properties.FACING, dir ) + ); + } + + @Override + protected ModemPeripheral createPeripheral() + { + return new Peripheral( this ); + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/TileCable.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/TileCable.java new file mode 100644 index 0000000000..c60849606d --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/TileCable.java @@ -0,0 +1,1041 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.modem; + +import com.google.common.base.Objects; +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.filesystem.IMount; +import dan200.computercraft.api.filesystem.IWritableMount; +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.shared.common.BlockGeneric; +import dan200.computercraft.shared.peripheral.PeripheralType; +import dan200.computercraft.shared.peripheral.common.BlockCable; +import dan200.computercraft.shared.peripheral.common.BlockCableModemVariant; +import dan200.computercraft.shared.peripheral.common.PeripheralItemFactory; +import dan200.computercraft.shared.util.IDAssigner; +import dan200.computercraft.shared.util.PeripheralUtil; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.*; +import net.minecraft.world.World; + +import java.io.File; +import java.util.*; + +public class TileCable extends TileModemBase + implements INetwork +{ + // Statics + + private static class Peripheral extends ModemPeripheral + { + private TileCable m_entity; + + public Peripheral( TileCable entity ) + { + m_entity = entity; + } + + @Override + protected boolean isInterdimensional() + { + return false; + } + + @Override + protected double getTransmitRange() + { + return 256.0; + } + + @Override + protected INetwork getNetwork() + { + return m_entity; + } + + @Override + protected World getWorld() + { + return m_entity.getWorld(); + } + + @Override + protected Vec3 getPosition() + { + EnumFacing direction = m_entity.getDirection(); + BlockPos pos = m_entity.getPos().offset( direction ); + return new Vec3( (double)pos.getX() + 0.5, (double)pos.getY() + 0.5, (double)pos.getZ() + 0.5 ); + } + + @Override + public String[] getMethodNames() + { + String[] methods = super.getMethodNames(); + String[] newMethods = new String[ methods.length + 5 ]; + System.arraycopy( methods, 0, newMethods, 0, methods.length ); + newMethods[ methods.length ] = "getNamesRemote"; + newMethods[ methods.length + 1 ] = "isPresentRemote"; + newMethods[ methods.length + 2 ] = "getTypeRemote"; + newMethods[ methods.length + 3 ] = "getMethodsRemote"; + newMethods[ methods.length + 4 ] = "callRemote"; + return newMethods; + } + + private String parseString( Object[] arguments, int index ) throws LuaException + { + if( arguments.length < (index + 1) || !(arguments[index] instanceof String) ) + { + throw new LuaException( "Expected string" ); + } + return (String)arguments[index]; + } + + @Override + public Object[] callMethod( IComputerAccess computer, ILuaContext context, int method, Object[] arguments ) throws LuaException, InterruptedException + { + String[] methods = super.getMethodNames(); + switch( method - methods.length ) + { + case 0: + { + // getNamesRemote + synchronized( m_entity.m_peripheralsByName ) + { + int idx = 1; + Map table = new HashMap(); + Iterator it = m_entity.m_peripheralWrappersByName.keySet().iterator(); + while( it.hasNext() ) + { + String name = it.next(); + table.put( idx++, name ); + } + return new Object[] { table }; + } + } + case 1: + { + // isPresentRemote + String type = m_entity.getTypeRemote( parseString( arguments, 0 ) ); + return new Object[] { type != null }; + } + case 2: + { + // getTypeRemote + String type = m_entity.getTypeRemote( parseString( arguments, 0 ) ); + if( type != null ) + { + return new Object[] { type }; + } + return null; + } + case 3: + { + // getMethodsRemote + String[] methodNames = m_entity.getMethodNamesRemote( parseString( arguments, 0 ) ); + if( methodNames != null ) + { + Map table = new HashMap(); + for(int i=0; i it = m_entity.m_peripheralsByName.keySet().iterator(); + while( it.hasNext() ) + { + String periphName = it.next(); + IPeripheral peripheral = m_entity.m_peripheralsByName.get( periphName ); + if( peripheral != null ) + { + m_entity.attachPeripheral( periphName, peripheral ); + } + } + } + } + + @Override + public synchronized void detach( IComputerAccess computer ) + { + synchronized( m_entity.m_peripheralsByName ) + { + Iterator it = m_entity.m_peripheralsByName.keySet().iterator(); + while( it.hasNext() ) + { + String periphName = it.next(); + m_entity.detachPeripheral( periphName ); + } + } + super.detach( computer ); + } + + @Override + public boolean equals( IPeripheral other ) + { + if( other instanceof Peripheral ) + { + Peripheral otherModem = (Peripheral)other; + return otherModem.m_entity == m_entity; + } + return false; + } + } + + private static int s_nextUniqueSearchID = 1; + + // Members + + private Map> m_receivers; + private Queue m_transmitQueue; + + private boolean m_peripheralAccessAllowed; + private int m_attachedPeripheralID; + + private Map m_peripheralsByName; + private Map m_peripheralWrappersByName; + private boolean m_peripheralsKnown; + private boolean m_destroyed; + + private int m_lastSearchID; + + public TileCable() + { + m_receivers = new HashMap>(); + m_transmitQueue = new LinkedList(); + + m_peripheralAccessAllowed = false; + m_attachedPeripheralID = -1; + + m_peripheralsByName = new HashMap(); + m_peripheralWrappersByName = new HashMap(); + m_peripheralsKnown = false; + m_destroyed = false; + + m_lastSearchID = 0; + } + + @Override + public void destroy() + { + if( !m_destroyed ) + { + m_destroyed = true; + networkChanged(); + } + super.destroy(); + } + + @Override + public EnumFacing getDirection() + { + IBlockState state = getBlockState(); + BlockCableModemVariant modem = (BlockCableModemVariant)state.getValue( BlockCable.Properties.MODEM ); + if( modem != BlockCableModemVariant.None ) + { + return modem.getFacing(); + } + else + { + return EnumFacing.NORTH; + } + } + + @Override + public void setDirection( EnumFacing dir ) + { + IBlockState state = getBlockState(); + BlockCableModemVariant modem = ( BlockCableModemVariant )state.getValue( BlockCable.Properties.MODEM ); + if( modem != BlockCableModemVariant.None ) + { + setBlockState( state.withProperty( BlockCable.Properties.MODEM, BlockCableModemVariant.fromFacing( dir ) ) ); + } + } + + @Override + public void getDroppedItems( List drops, int fortune, boolean creative, boolean silkTouch ) + { + if( !creative ) + { + PeripheralType type = getPeripheralType(); + switch( type ) + { + case Cable: + case WiredModem: + { + drops.add( PeripheralItemFactory.create( type, getLabel(), 1 ) ); + break; + } + case WiredModemWithCable: + { + drops.add( PeripheralItemFactory.create( PeripheralType.WiredModem, getLabel(), 1 ) ); + drops.add( PeripheralItemFactory.create( PeripheralType.Cable, null, 1 ) ); + break; + } + } + } + } + + @Override + public ItemStack getPickedItem() + { + if( getPeripheralType() == PeripheralType.WiredModemWithCable ) + { + return PeripheralItemFactory.create( PeripheralType.WiredModem, getLabel(), 1 ); + } + else + { + return super.getPickedItem(); + } + } + + @Override + public void onNeighbourChange() + { + EnumFacing dir = getDirection(); + if( !worldObj.isSideSolid( + getPos().offset( dir ), + dir.getOpposite() + ) ) + { + switch( getPeripheralType() ) + { + case WiredModem: + { + // Drop everything and remove block + ((BlockGeneric)getBlockType()).dropAllItems( worldObj, getPos(), 0, false, false ); + worldObj.setBlockToAir( getPos() ); + break; + } + case WiredModemWithCable: + { + // Drop the modem and convert to cable + ((BlockGeneric)getBlockType()).dropItem( worldObj, getPos(), PeripheralItemFactory.create( PeripheralType.WiredModem, getLabel(), 1 ) ); + setLabel( null ); + setBlockState( getBlockState().withProperty( BlockCable.Properties.MODEM, BlockCableModemVariant.None ) ); + break; + } + } + } + } + + public AxisAlignedBB getModemBounds() + { + return super.getBounds(); + } + + public AxisAlignedBB getCableBounds() + { + double xMin = 0.375; + double yMin = 0.375; + double zMin = 0.375; + double xMax = 0.625; + double yMax = 0.625; + double zMax = 0.625; + BlockPos pos = getPos(); + if( BlockCable.isCable( worldObj, pos.west() ) ) + { + xMin = 0.0; + } + if( BlockCable.isCable( worldObj, pos.east() ) ) + { + xMax = 1.0; + } + if( BlockCable.isCable( worldObj, pos.down() ) ) + { + yMin = 0.0; + } + if( BlockCable.isCable( worldObj, pos.up() ) ) + { + yMax = 1.0; + } + if( BlockCable.isCable( worldObj, pos.north() ) ) + { + zMin = 0.0; + } + if( BlockCable.isCable( worldObj, pos.south() ) ) + { + zMax = 1.0; + } + return new AxisAlignedBB( xMin, yMin, zMin, xMax, yMax, zMax ); + } + + @Override + public AxisAlignedBB getBounds() + { + PeripheralType type = getPeripheralType(); + switch( type ) + { + case WiredModem: + default: + { + return getModemBounds(); + } + case Cable: + { + return getCableBounds(); + } + case WiredModemWithCable: + { + AxisAlignedBB modem = getModemBounds(); + AxisAlignedBB cable = getCableBounds(); + return new AxisAlignedBB( + Math.min( modem.minX, cable.minX ), + Math.min( modem.minY, cable.minY ), + Math.min( modem.minZ, cable.minZ ), + Math.max( modem.maxX, cable.maxX ), + Math.max( modem.maxY, cable.maxY ), + Math.max( modem.maxZ, cable.maxZ ) + ); + } + } + } + + @Override + public void getCollisionBounds( List bounds ) + { + PeripheralType type = getPeripheralType(); + if( type == PeripheralType.WiredModem || type == PeripheralType.WiredModemWithCable ) + { + bounds.add( getModemBounds() ); + } + if( type == PeripheralType.Cable || type == PeripheralType.WiredModemWithCable ) + { + bounds.add( getCableBounds() ); + } + } + + @Override + public boolean onActivate( EntityPlayer player, EnumFacing side, float hitX, float hitY, float hitZ ) + { + if( getPeripheralType() == PeripheralType.WiredModemWithCable && !player.isSneaking() ) + { + if( !worldObj.isRemote ) + { + // On server, we interacted if a peripheral was found + String oldPeriphName = getConnectedPeripheralName(); + togglePeripheralAccess(); + String periphName = getConnectedPeripheralName(); + + if( !Objects.equal( periphName, oldPeriphName ) ) + { + if( oldPeriphName != null ) + { + player.addChatMessage( + new ChatComponentTranslation( "gui.computercraft:wired_modem.peripheral_disconnected", oldPeriphName ) + ); + } + if( periphName != null ) + { + player.addChatMessage( + new ChatComponentTranslation( "gui.computercraft:wired_modem.peripheral_connected", periphName ) + ); + } + return true; + } + } + else + { + // On client, we can't know this, so we assume so to be safe + // The server will correct us if we're wrong + return true; + } + } + return false; + } + + @Override + public void readFromNBT(NBTTagCompound nbttagcompound) + { + // Read properties + super.readFromNBT(nbttagcompound); + m_peripheralAccessAllowed = nbttagcompound.getBoolean( "peripheralAccess" ); + m_attachedPeripheralID = nbttagcompound.getInteger( "peripheralID" ); + } + + @Override + public void writeToNBT(NBTTagCompound nbttagcompound) + { + // Write properties + super.writeToNBT(nbttagcompound); + nbttagcompound.setBoolean( "peripheralAccess", m_peripheralAccessAllowed ); + nbttagcompound.setInteger( "peripheralID", m_attachedPeripheralID ); + } + + @Override + protected ModemPeripheral createPeripheral() + { + return new Peripheral( this ); + } + + @Override + protected void updateAnim() + { + int anim = 0; + if( m_modem.isActive() ) + { + anim += 1; + } + if( m_peripheralAccessAllowed ) + { + anim += 2; + } + setAnim( anim ); + } + + // IPeripheralTile + + @Override + public IPeripheral getPeripheral( EnumFacing side ) + { + if( getPeripheralType() != PeripheralType.Cable ) + { + return super.getPeripheral( side ); + } + return null; + } + + @Override + public void update() + { + super.update(); + if( !worldObj.isRemote ) + { + synchronized( m_peripheralsByName ) + { + if( !m_peripheralsKnown ) + { + findPeripherals(); + m_peripheralsKnown = true; + } + } + synchronized( m_transmitQueue ) + { + while( m_transmitQueue.peek() != null ) + { + Packet p = m_transmitQueue.remove(); + if( p != null ) + { + dispatchPacket( p ); + } + } + } + } + } + + // INetwork implementation + + @Override + public void addReceiver( IReceiver receiver ) + { + synchronized( m_receivers ) + { + int channel = receiver.getChannel(); + Set receivers = m_receivers.get( channel ); + if( receivers == null ) + { + receivers = new HashSet(); + m_receivers.put( channel, receivers ); + } + receivers.add( receiver ); + } + } + + @Override + public void removeReceiver( IReceiver receiver ) + { + synchronized( m_receivers ) + { + int channel = receiver.getChannel(); + Set receivers = m_receivers.get( channel ); + if( receivers != null ) + { + receivers.remove( receiver ); + } + } + } + + @Override + public void transmit( int channel, int replyChannel, Object payload, World world, Vec3 pos, double range, boolean interdimensional, Object senderObject ) + { + Packet p = new Packet(); + p.channel = channel; + p.replyChannel = replyChannel; + p.payload = payload; + p.senderObject = senderObject; + synchronized( m_transmitQueue ) + { + m_transmitQueue.offer(p); + } + } + + @Override + public boolean isWireless() + { + return false; + } + + private void attachPeripheral( String periphName, IPeripheral peripheral ) + { + if( !m_peripheralWrappersByName.containsKey( periphName ) ) + { + RemotePeripheralWrapper wrapper = new RemotePeripheralWrapper( peripheral, m_modem.getComputer(), periphName ); + m_peripheralWrappersByName.put( periphName, wrapper ); + wrapper.attach(); + } + } + + private void detachPeripheral( String periphName ) + { + if( m_peripheralWrappersByName.containsKey( periphName ) ) + { + RemotePeripheralWrapper wrapper = m_peripheralWrappersByName.get( periphName ); + m_peripheralWrappersByName.remove( periphName ); + wrapper.detach(); + } + } + + private String getTypeRemote( String remoteName ) + { + synchronized( m_peripheralsByName ) + { + RemotePeripheralWrapper wrapper = m_peripheralWrappersByName.get( remoteName ); + if( wrapper != null ) + { + return wrapper.getType(); + } + } + return null; + } + + private String[] getMethodNamesRemote( String remoteName ) + { + synchronized( m_peripheralsByName ) + { + RemotePeripheralWrapper wrapper = m_peripheralWrappersByName.get( remoteName ); + if( wrapper != null ) + { + return wrapper.getMethodNames(); + } + } + return null; + } + + private Object[] callMethodRemote( String remoteName, ILuaContext context, String method, Object[] arguments ) throws LuaException, InterruptedException + { + RemotePeripheralWrapper wrapper; + synchronized( m_peripheralsByName ) + { + wrapper = m_peripheralWrappersByName.get( remoteName ); + } + if( wrapper != null ) + { + return wrapper.callMethod( context, method, arguments ); + } + throw new LuaException( "No peripheral: "+remoteName ); + } + + public void networkChanged() + { + if( !worldObj.isRemote ) + { + if( !m_destroyed ) + { + // If this modem is alive, rebuild the network + searchNetwork( new ICableVisitor() { + public void visit( TileCable modem, int distance ) + { + synchronized( modem.m_peripheralsByName ) + { + modem.m_peripheralsKnown = false; + } + } + } ); + } + else + { + // If this modem is dead, rebuild the neighbours' networks + for( EnumFacing dir : EnumFacing.values() ) + { + BlockPos offset = getPos().offset( dir ); + if( offset.getY() >= 0 && offset.getY() < worldObj.getHeight() && BlockCable.isCable( worldObj, offset ) ) + { + TileEntity tile = worldObj.getTileEntity( offset ); + if( tile != null && tile instanceof TileCable ) + { + TileCable modem = (TileCable)tile; + modem.networkChanged(); + } + } + } + } + } + } + + // private stuff + + // Packet sending + + private class Packet + { + public int channel; + public int replyChannel; + public Object payload; + public Object senderObject; + } + + private void dispatchPacket( final Packet packet ) + { + searchNetwork( new ICableVisitor() { + public void visit( TileCable modem, int distance ) + { + modem.receivePacket( packet, distance ); + } + } ); + } + + private void receivePacket( Packet packet, int distanceTravelled ) + { + synchronized( m_receivers ) + { + Set receivers = m_receivers.get( packet.channel ); + if( receivers != null ) + { + Iterator it = receivers.iterator(); + while( it.hasNext() ) + { + IReceiver receiver = it.next(); + receiver.receiveSameDimension( packet.replyChannel, packet.payload, (double)distanceTravelled, packet.senderObject ); + } + } + } + } + + // Remote peripheral control + + private static class RemotePeripheralWrapper implements IComputerAccess + { + private IPeripheral m_peripheral; + private IComputerAccess m_computer; + private String m_name; + + private String m_type; + private String[] m_methods; + private Map m_methodMap; + + public RemotePeripheralWrapper( IPeripheral peripheral, IComputerAccess computer, String name ) + { + m_peripheral = peripheral; + m_computer = computer; + m_name = name; + + m_type = peripheral.getType(); + m_methods = peripheral.getMethodNames(); + assert( m_type != null ); + assert( m_methods != null ); + + m_methodMap = new HashMap(); + for( int i=0; i newPeripheralsByName = new HashMap(); + if( getPeripheralType() == PeripheralType.WiredModemWithCable ) + { + searchNetwork( new ICableVisitor() { + public void visit( TileCable modem, int distance ) + { + if( modem != origin ) + { + IPeripheral peripheral = modem.getConnectedPeripheral(); + String periphName = modem.getConnectedPeripheralName(); + if( peripheral != null && periphName != null ) + { + newPeripheralsByName.put( periphName, peripheral ); + } + } + } + } ); + } + //System.out.println( newPeripheralsByName.size()+" peripherals discovered" ); + + // Detach all the old peripherals + Iterator it = m_peripheralsByName.keySet().iterator(); + while( it.hasNext() ) + { + String periphName = it.next(); + if( !newPeripheralsByName.containsKey( periphName ) ) + { + detachPeripheral( periphName ); + it.remove(); + } + } + + // Attach all the new peripherals + Iterator it2 = newPeripheralsByName.keySet().iterator(); + while( it2.hasNext() ) + { + String periphName = it2.next(); + if( !m_peripheralsByName.containsKey( periphName ) ) + { + IPeripheral peripheral = newPeripheralsByName.get( periphName ); + if( peripheral != null ) + { + m_peripheralsByName.put( periphName, peripheral ); + if( isAttached() ) + { + attachPeripheral( periphName, peripheral ); + } + } + } + } + //System.out.println( m_peripheralsByName.size()+" connected" ); + } + } + + public void togglePeripheralAccess() + { + if( !m_peripheralAccessAllowed ) + { + m_peripheralAccessAllowed = true; + if( getConnectedPeripheral() == null ) + { + m_peripheralAccessAllowed = false; + return; + } + } + else + { + m_peripheralAccessAllowed = false; + } + updateAnim(); + networkChanged(); + } + + public String getConnectedPeripheralName() + { + IPeripheral periph = getConnectedPeripheral(); + if( periph != null ) + { + String type = periph.getType(); + if( m_attachedPeripheralID < 0 ) + { + m_attachedPeripheralID = IDAssigner.getNextIDFromFile(new File( + ComputerCraft.getWorldDir(worldObj), + "computer/lastid_" + type + ".txt" + )); + } + return type + "_" + m_attachedPeripheralID; + } + return null; + } + + private IPeripheral getConnectedPeripheral() + { + if( m_peripheralAccessAllowed ) + { + if( getPeripheralType() == PeripheralType.WiredModemWithCable ) + { + EnumFacing facing = getDirection(); + BlockPos neighbour = getPos().offset( facing ); + return PeripheralUtil.getPeripheral( worldObj, neighbour, facing.getOpposite() ); + } + } + return null; + } + + // Generic network search stuff + + private static interface ICableVisitor + { + public void visit( TileCable modem, int distance ); + } + + private static class SearchLoc + { + public World world; + public BlockPos pos; + public int distanceTravelled; + } + + private static void enqueue( Queue queue, World world, BlockPos pos, int distanceTravelled ) + { + int y = pos.getY(); + if( y >= 0 && y < world.getHeight() && BlockCable.isCable( world, pos ) ) + { + SearchLoc loc = new SearchLoc(); + loc.world = world; + loc.pos = pos; + loc.distanceTravelled = distanceTravelled; + queue.offer( loc ); + } + } + + private static void visitBlock( Queue queue, SearchLoc location, int searchID, ICableVisitor visitor ) + { + if( location.distanceTravelled >= 256 ) + { + return; + } + + TileEntity tile = location.world.getTileEntity( location.pos ); + if( tile != null && tile instanceof TileCable ) + { + TileCable modem = (TileCable)tile; + if( !modem.m_destroyed && modem.m_lastSearchID != searchID ) + { + modem.m_lastSearchID = searchID; + visitor.visit( modem, location.distanceTravelled + 1 ); + + enqueue( queue, location.world, location.pos.up(), location.distanceTravelled + 1 ); + enqueue( queue, location.world, location.pos.down(), location.distanceTravelled + 1 ); + enqueue( queue, location.world, location.pos.south(), location.distanceTravelled + 1 ); + enqueue( queue, location.world, location.pos.north(), location.distanceTravelled + 1 ); + enqueue( queue, location.world, location.pos.east(), location.distanceTravelled + 1 ); + enqueue( queue, location.world, location.pos.west(), location.distanceTravelled + 1 ); + } + } + } + + private void searchNetwork( ICableVisitor visitor ) + { + int searchID = ++s_nextUniqueSearchID; + Queue queue = new LinkedList(); + enqueue( queue, worldObj, getPos(), 1 ); + + int visited = 0; + while( queue.peek() != null ) + { + SearchLoc loc = queue.remove(); + visitBlock( queue, loc, searchID, visitor ); + visited++; + } + //System.out.println( "Visited "+visited+" common" ); + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/TileModemBase.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/TileModemBase.java new file mode 100644 index 0000000000..45d79fc86a --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/TileModemBase.java @@ -0,0 +1,136 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.modem; + +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.shared.common.BlockGeneric; +import dan200.computercraft.shared.peripheral.common.TilePeripheralBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.EnumFacing; + +public abstract class TileModemBase extends TilePeripheralBase +{ + protected ModemPeripheral m_modem; + + protected TileModemBase() + { + m_modem = createPeripheral(); + } + + protected abstract ModemPeripheral createPeripheral(); + + @Override + public synchronized void destroy() + { + if( m_modem != null ) + { + m_modem.destroy(); + m_modem = null; + } + } + + @Override + public boolean isSolidOnSide( int side ) + { + return false; + } + + @Override + public void onNeighbourChange() + { + EnumFacing dir = getDirection(); + if( !worldObj.isSideSolid( + getPos().offset( dir ), + dir.getOpposite() + ) ) + { + // Drop everything and remove block + ((BlockGeneric)getBlockType()).dropAllItems( worldObj, getPos(), 0, false, false ); + worldObj.setBlockToAir( getPos() ); + } + } + + @Override + public AxisAlignedBB getBounds() + { + switch( getDirection() ) + { + case UP: + default: + { + return new AxisAlignedBB( 0.125, 0.8125, 0.125, 0.875, 1.0, 0.875 ); + } + case DOWN: + { + return new AxisAlignedBB( 0.125, 0.0, 0.125, 0.875, 0.1875, 0.875 ); + } + case NORTH: + { + return new AxisAlignedBB( 0.125, 0.125, 0.0, 0.875, 0.875, 0.1875 ); + } + case SOUTH: + { + return new AxisAlignedBB( 0.125, 0.125, 0.8125, 0.875, 0.875, 1.0 ); + } + case WEST: + { + return new AxisAlignedBB( 0.0, 0.125, 0.125, 0.1875, 0.875, 0.875 ); + } + case EAST: + { + return new AxisAlignedBB( 0.8125, 0.125, 0.125, 1.0, 0.875, 0.875 ); + } + } + } + + @Override + public void update() + { + super.update(); + if( !worldObj.isRemote && m_modem.pollChanged() ) + { + updateAnim(); + } + } + + protected void updateAnim() + { + if( m_modem.isActive() ) + { + setAnim(1); + } + else + { + setAnim(0); + } + } + + @Override + public final void readDescription( NBTTagCompound nbttagcompound ) + { + super.readDescription( nbttagcompound ); + updateBlock(); + } + + // IPeripheralTile implementation + + @Override + public IPeripheral getPeripheral( EnumFacing side ) + { + if( side == getDirection() ) + { + return m_modem; + } + return null; + } + + protected boolean isAttached() + { + return (m_modem != null) && (m_modem.getComputer() != null); + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/TileWirelessModem.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/TileWirelessModem.java new file mode 100644 index 0000000000..c585e928b6 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/TileWirelessModem.java @@ -0,0 +1,127 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.modem; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.shared.peripheral.PeripheralType; +import dan200.computercraft.shared.peripheral.common.BlockPeripheral; +import dan200.computercraft.shared.peripheral.common.BlockPeripheralVariant; +import net.minecraft.block.state.IBlockState; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +public class TileWirelessModem extends TileModemBase +{ + // Statics + + private static class Peripheral extends WirelessModemPeripheral + { + private TileModemBase m_entity; + + public Peripheral( TileModemBase entity ) + { + super( false ); + m_entity = entity; + } + + @Override + protected World getWorld() + { + return m_entity.getWorld(); + } + + @Override + protected Vec3 getPosition() + { + BlockPos pos = m_entity.getPos().offset( m_entity.getDirection() ); + return new Vec3( (double)pos.getX(), (double)pos.getY(), (double)pos.getZ() ); + } + + @Override + public boolean equals( IPeripheral other ) + { + if( other instanceof Peripheral ) + { + Peripheral otherModem = (Peripheral)other; + return otherModem.m_entity == m_entity; + } + return false; + } + } + + // Members + + public TileWirelessModem() + { + } + + @Override + public EnumFacing getDirection() + { + // Wireless Modem + IBlockState state = getBlockState(); + switch( (BlockPeripheralVariant)state.getValue( BlockPeripheral.Properties.VARIANT ) ) + { + case WirelessModemDownOff: + case WirelessModemDownOn: + { + return EnumFacing.DOWN; + } + case WirelessModemUpOff: + case WirelessModemUpOn: + { + return EnumFacing.UP; + } + default: + { + return (EnumFacing)state.getValue( BlockPeripheral.Properties.FACING ); + } + } + } + + @Override + public void setDirection( EnumFacing dir ) + { + // Wireless Modem + if( dir == EnumFacing.UP ) + { + setBlockState( getBlockState() + .withProperty( BlockPeripheral.Properties.VARIANT, BlockPeripheralVariant.WirelessModemUpOff ) + .withProperty( BlockPeripheral.Properties.FACING, EnumFacing.NORTH ) + ); + } + else if( dir == EnumFacing.DOWN ) + { + setBlockState( getBlockState() + .withProperty( BlockPeripheral.Properties.VARIANT, BlockPeripheralVariant.WirelessModemDownOff ) + .withProperty( BlockPeripheral.Properties.FACING, EnumFacing.NORTH ) + ); + } + else + { + setBlockState( getBlockState() + .withProperty( BlockPeripheral.Properties.VARIANT, BlockPeripheralVariant.WirelessModemOff ) + .withProperty( BlockPeripheral.Properties.FACING, dir ) + ); + } + } + + @Override + protected ModemPeripheral createPeripheral() + { + return new Peripheral( this ); + } + + @Override + public boolean shouldRefresh( World world, BlockPos pos, IBlockState oldState, IBlockState newState ) + { + return super.shouldRefresh( world, pos, oldState, newState ) || ComputerCraft.Blocks.peripheral.getPeripheralType( newState ) != PeripheralType.WirelessModem; + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/WirelessModemPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/WirelessModemPeripheral.java new file mode 100644 index 0000000000..2d55aaca64 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/WirelessModemPeripheral.java @@ -0,0 +1,63 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.modem; + +import dan200.computercraft.ComputerCraft; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +public abstract class WirelessModemPeripheral extends ModemPeripheral +{ + private boolean m_advanced; + + public WirelessModemPeripheral( boolean advanced ) + { + m_advanced = advanced; + } + + @Override + protected boolean isInterdimensional() + { + return m_advanced; + } + + @Override + protected double getTransmitRange() + { + if( m_advanced ) + { + return (double)Integer.MAX_VALUE; + } + else + { + World world = getWorld(); + if( world != null ) + { + Vec3 position = getPosition(); + double minRange = (double) ComputerCraft.modem_range; + double maxRange = (double) ComputerCraft.modem_highAltitudeRange; + if( world.isRaining() && world.isThundering() ) + { + minRange = (double) ComputerCraft.modem_rangeDuringStorm; + maxRange = (double) ComputerCraft.modem_highAltitudeRangeDuringStorm; + } + if( position.yCoord > 96.0 && maxRange > minRange ) + { + return minRange + ( position.yCoord - 96.0 ) * ( ( maxRange - minRange ) / ( ( world.getHeight() - 1 ) - 96.0 ) ); + } + return minRange; + } + return 0.0; + } + } + + @Override + protected INetwork getNetwork() + { + return WirelessNetwork.getUniversal(); + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/WirelessNetwork.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/WirelessNetwork.java new file mode 100644 index 0000000000..997b8b2a64 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/WirelessNetwork.java @@ -0,0 +1,104 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.modem; + +import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +import java.util.*; + +public class WirelessNetwork implements INetwork +{ + private static WirelessNetwork s_universalNetwork = null; + + public static WirelessNetwork getUniversal() + { + if( s_universalNetwork == null ) + { + s_universalNetwork = new WirelessNetwork(); + } + return s_universalNetwork; + } + + public static void resetNetworks() + { + s_universalNetwork = null; + } + + private Map> m_receivers; + + private WirelessNetwork() + { + m_receivers = new HashMap>(); + } + + @Override + public synchronized void addReceiver( IReceiver receiver ) + { + int channel = receiver.getChannel(); + Set receivers = m_receivers.get( channel ); + if( receivers == null ) + { + receivers = new HashSet(); + m_receivers.put( channel, receivers ); + } + receivers.add( receiver ); + } + + @Override + public synchronized void removeReceiver( IReceiver receiver ) + { + int channel = receiver.getChannel(); + Set receivers = m_receivers.get( channel ); + if( receivers != null ) + { + receivers.remove( receiver ); + } + } + + @Override + public synchronized void transmit( int channel, int replyChannel, Object payload, World world, Vec3 pos, double range, boolean interdimensional, Object senderObject ) + { + Set receivers = m_receivers.get( channel ); + if( receivers != null ) + { + Iterator it = receivers.iterator(); + while( it.hasNext() ) + { + IReceiver receiver = it.next(); + tryTransmit( receiver, replyChannel, payload, world, pos, range, interdimensional, senderObject ); + } + } + } + + private void tryTransmit( IReceiver receiver, int replyChannel, Object payload, World world, Vec3 pos, double range, boolean interdimensional, Object senderObject ) + { + if( receiver.getWorld() == world ) + { + Vec3 position = receiver.getWorldPosition(); + double receiveRange = Math.max( range, receiver.getReceiveRange() ); // Ensure range is symmetrical + double distanceSq = position.squareDistanceTo( pos ); + if( interdimensional || receiver.isInterdimensional() || distanceSq <= ( receiveRange * receiveRange ) ) + { + receiver.receiveSameDimension( replyChannel, payload, Math.sqrt( distanceSq ), senderObject ); + } + } + else + { + if( interdimensional || receiver.isInterdimensional() ) + { + receiver.receiveDifferentDimension( replyChannel, payload, senderObject ); + } + } + } + + @Override + public boolean isWireless() + { + return true; + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorPeripheral.java new file mode 100644 index 0000000000..366794271d --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorPeripheral.java @@ -0,0 +1,250 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.monitor; + +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.core.terminal.Terminal; + +public class MonitorPeripheral implements IPeripheral +{ + private final TileMonitor m_monitor; + + public MonitorPeripheral( TileMonitor monitor ) + { + m_monitor = monitor; + } + + // IPeripheral implementation + + @Override + public String getType() + { + return "monitor"; + } + + @Override + public String[] getMethodNames() + { + return new String[] { + "write", + "scroll", + "setCursorPos", + "setCursorBlink", + "getCursorPos", + "getSize", + "clear", + "clearLine", + "setTextScale", + "setTextColour", + "setTextColor", + "setBackgroundColour", + "setBackgroundColor", + "isColour", + "isColor", + "getTextColour", + "getTextColor", + "getBackgroundColour", + "getBackgroundColor", + "blit" + }; + } + + @Override + public Object[] callMethod( IComputerAccess computer, ILuaContext context, int method, Object args[] ) throws LuaException + { + switch( method ) + { + case 0: + { + // write + String text; + if( args.length > 0 && args[0] != null ) { + text = args[0].toString(); + } else { + text = ""; + } + Terminal terminal = m_monitor.getTerminal().getTerminal(); + terminal.write( text ); + terminal.setCursorPos( terminal.getCursorX() + text.length(), terminal.getCursorY() ); + return null; + } + case 1: + { + // scroll + if( args.length < 1 || !(args[0] instanceof Number) ) + { + throw new LuaException( "Expected number" ); + } + Terminal terminal = m_monitor.getTerminal().getTerminal(); + terminal.scroll( ((Number)(args[0])).intValue() ); + return null; + } + case 2: + { + // setCursorPos + if( args.length < 2 || !(args[0] instanceof Number) || !(args[1] instanceof Number) ) + { + throw new LuaException( "Expected number, number" ); + } + int x = ((Number)args[0]).intValue() - 1; + int y = ((Number)args[1]).intValue() - 1; + Terminal terminal = m_monitor.getTerminal().getTerminal(); + terminal.setCursorPos( x, y ); + return null; + } + case 3: + { + // setCursorBlink + if( args.length < 1 || !(args[0] instanceof Boolean) ) + { + throw new LuaException( "Expected boolean" ); + } + Terminal terminal = m_monitor.getTerminal().getTerminal(); + terminal.setCursorBlink( ((Boolean)args[0]).booleanValue() ); + return null; + } + case 4: + { + // getCursorPos + Terminal terminal = m_monitor.getTerminal().getTerminal(); + return new Object[] { + terminal.getCursorX() + 1, + terminal.getCursorY() + 1 + }; + } + case 5: + { + // getSize + Terminal terminal = m_monitor.getTerminal().getTerminal(); + return new Object[] { + terminal.getWidth(), + terminal.getHeight() + }; + } + case 6: + { + // clear + Terminal terminal = m_monitor.getTerminal().getTerminal(); + terminal.clear(); + return null; + } + case 7: + { + // clearLine + Terminal terminal = m_monitor.getTerminal().getTerminal(); + terminal.clearLine(); + return null; + } + case 8: + { + // setTextScale + if( args.length < 1 || !(args[0] instanceof Number) ) + { + throw new LuaException( "Expected number" ); + } + int scale = (int)(((Number)args[0]).doubleValue() * 2.0); + if( scale < 1 || scale > 10 ) + { + throw new LuaException( "Expected number in range 0.5-5" ); + } + m_monitor.setTextScale( scale ); + return null; + } + case 9: + case 10: + { + // setTextColour/setTextColor + int colour = dan200.computercraft.core.apis.TermAPI.parseColour( args, m_monitor.getTerminal().isColour() ); + Terminal terminal = m_monitor.getTerminal().getTerminal(); + terminal.setTextColour( colour ); + return null; + } + case 11: + case 12: + { + // setBackgroundColour/setBackgroundColor + int colour = dan200.computercraft.core.apis.TermAPI.parseColour( args, m_monitor.getTerminal().isColour() ); + Terminal terminal = m_monitor.getTerminal().getTerminal(); + terminal.setBackgroundColour( colour ); + return null; + } + case 13: + case 14: + { + // isColour/isColor + return new Object[] { + m_monitor.getTerminal().isColour() + }; + } + case 15: + case 16: + { + // getTextColour/getTextColor + Terminal terminal = m_monitor.getTerminal().getTerminal(); + return dan200.computercraft.core.apis.TermAPI.encodeColour( terminal.getTextColour() ); + } + case 17: + case 18: + { + // getBackgroundColour/getBackgroundColor + Terminal terminal = m_monitor.getTerminal().getTerminal(); + return dan200.computercraft.core.apis.TermAPI.encodeColour( terminal.getBackgroundColour() ); + } + case 19: + { + // blit + if( args.length < 3 || !(args[0] instanceof String) || !(args[1] instanceof String) || !(args[2] instanceof String) ) + { + throw new LuaException( "Expected string, string, string" ); + } + + String text = (String)args[0]; + String textColour = (String)args[1]; + String backgroundColour = (String)args[2]; + if( textColour.length() != text.length() || backgroundColour.length() != text.length() ) + { + throw new LuaException( "Arguments must be the same length" ); + } + + Terminal terminal = m_monitor.getTerminal().getTerminal(); + terminal.blit( text, textColour, backgroundColour ); + terminal.setCursorPos( terminal.getCursorX() + text.length(), terminal.getCursorY() ); + return null; + } + } + return null; + } + + @Override + public void attach( IComputerAccess computer ) + { + m_monitor.addComputer( computer ); + } + + @Override + public void detach( IComputerAccess computer ) + { + m_monitor.removeComputer( computer ); + } + + @Override + public boolean equals( IPeripheral other ) + { + if( other != null && other instanceof MonitorPeripheral ) + { + MonitorPeripheral otherMonitor = (MonitorPeripheral)other; + if( otherMonitor.m_monitor == this.m_monitor ) + { + return true; + } + } + return false; + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java new file mode 100644 index 0000000000..23139ea0cf --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java @@ -0,0 +1,865 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.monitor; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.core.terminal.Terminal; +import dan200.computercraft.shared.common.ClientTerminal; +import dan200.computercraft.shared.common.ITerminal; +import dan200.computercraft.shared.common.ITerminalTile; +import dan200.computercraft.shared.common.ServerTerminal; +import dan200.computercraft.shared.peripheral.PeripheralType; +import dan200.computercraft.shared.peripheral.common.TilePeripheralBase; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +import java.util.HashSet; +import java.util.Set; + +public class TileMonitor extends TilePeripheralBase + implements ITerminalTile +{ + // Statics + + public static final double RENDER_BORDER = (2.0 / 16.0); + public static final double RENDER_MARGIN = (0.5 / 16.0); + public static final double RENDER_PIXEL_SCALE = (1.0 / 64.0); + + private static final int MAX_WIDTH = 8; + private static final int MAX_HEIGHT = 6; + + // Members + + private ServerTerminal m_serverTerminal; + private ClientTerminal m_clientTerminal; + private final Set m_computers; + + public long m_lastRenderFrame = -1; // For rendering use only + public int m_renderDisplayList = -1; // For rendering use only + + private boolean m_destroyed; + private boolean m_ignoreMe; + private boolean m_changed; + + private int m_textScale; + private int m_width; + private int m_height; + private int m_xIndex; + private int m_yIndex; + + private int m_dir; + private boolean m_sizeChangedQueued; + + public TileMonitor() + { + m_computers = new HashSet(); + + m_destroyed = false; + m_ignoreMe = false; + m_textScale = 2; + + m_width = 1; + m_height = 1; + m_xIndex = 0; + m_yIndex = 0; + m_changed = false; + + m_dir = 2; + } + + @Override + public void destroy() + { + if( !m_destroyed ) + { + m_destroyed = true; + if( !worldObj.isRemote ) + { + contractNeighbours(); + } + } + if( m_renderDisplayList >= 0 ) + { + ComputerCraft.deleteDisplayLists( m_renderDisplayList, 3 ); + m_renderDisplayList = -1; + } + } + + @Override + public boolean onActivate( EntityPlayer player, EnumFacing side, float hitX, float hitY, float hitZ ) + { + if( !player.isSneaking() && getFront() == side ) + { + if( !worldObj.isRemote ) + { + monitorTouched( hitX, hitY, hitZ ); + } + return true; + } + return false; + } + + @Override + public void writeToNBT( NBTTagCompound nbttagcompound ) + { + super.writeToNBT(nbttagcompound); + nbttagcompound.setInteger( "xIndex", m_xIndex ); + nbttagcompound.setInteger( "yIndex", m_yIndex ); + nbttagcompound.setInteger( "width", m_width ); + nbttagcompound.setInteger( "height", m_height ); + nbttagcompound.setInteger( "dir", m_dir ); + } + + @Override + public void readFromNBT( NBTTagCompound nbttagcompound ) + { + super.readFromNBT(nbttagcompound); + m_xIndex = nbttagcompound.getInteger("xIndex"); + m_yIndex = nbttagcompound.getInteger("yIndex"); + m_width = nbttagcompound.getInteger("width"); + m_height = nbttagcompound.getInteger("height"); + m_dir = nbttagcompound.getInteger("dir"); + } + + @Override + public void update() + { + super.update(); + + if( !worldObj.isRemote ) + { + if( m_sizeChangedQueued ) + { + for( IComputerAccess computer : m_computers ) + { + computer.queueEvent( "monitor_resize", new Object[] { + computer.getAttachmentName() + } ); + } + m_sizeChangedQueued = false; + } + + if( m_serverTerminal != null ) + { + m_serverTerminal.update(); + if( m_serverTerminal.hasTerminalChanged() ) + { + updateBlock(); + } + } + + if( m_clientTerminal != null ) + { + m_clientTerminal.update(); + } + } + } + + public boolean pollChanged() + { + if( m_changed ) + { + m_changed = false; + return true; + } + return false; + } + + // IPeripheralTile implementation + + @Override + public IPeripheral getPeripheral( EnumFacing side ) + { + return new MonitorPeripheral( this ); + } + + public void setTextScale( int scale ) + { + TileMonitor origin = getOrigin(); + if( origin != null ) + { + synchronized( origin ) + { + if( origin.m_textScale != scale ) + { + origin.m_textScale = scale; + origin.rebuildTerminal(); + origin.updateBlock(); + } + } + } + } + + // Networking stuff + + @Override + public void writeDescription( NBTTagCompound nbttagcompound ) + { + super.writeDescription( nbttagcompound ); + nbttagcompound.setInteger( "xIndex", m_xIndex ); + nbttagcompound.setInteger( "yIndex", m_yIndex ); + nbttagcompound.setInteger( "width", m_width ); + nbttagcompound.setInteger( "height", m_height ); + nbttagcompound.setInteger( "textScale", m_textScale ); + nbttagcompound.setInteger( "monitorDir", m_dir ); + ((ServerTerminal)getLocalTerminal()).writeDescription( nbttagcompound ); + } + + @Override + public final void readDescription( NBTTagCompound nbttagcompound ) + { + super.readDescription( nbttagcompound ); + + int oldXIndex = m_xIndex; + int oldYIndex = m_yIndex; + int oldWidth = m_width; + int oldHeight = m_height; + int oldTextScale = m_textScale; + int oldDir = m_dir; + + m_xIndex = nbttagcompound.getInteger( "xIndex" ); + m_yIndex = nbttagcompound.getInteger( "yIndex" ); + m_width = nbttagcompound.getInteger( "width" ); + m_height = nbttagcompound.getInteger( "height" ); + m_textScale = nbttagcompound.getInteger( "textScale" ); + m_dir = nbttagcompound.getInteger( "monitorDir" ); + ((ClientTerminal)getLocalTerminal()).readDescription( nbttagcompound ); + m_changed = true; + + if( oldXIndex != m_xIndex || oldYIndex != m_yIndex || + oldWidth != m_width || oldHeight != m_height || + oldTextScale != m_textScale || oldDir != m_dir ) + { + updateBlock(); + } + } + + // ITerminalTile implementation + + @Override + public ITerminal getTerminal() + { + TileMonitor origin = getOrigin(); + if( origin != null ) + { + return origin.getLocalTerminal(); + } + return null; + } + + private ITerminal getLocalTerminal() + { + if( !worldObj.isRemote ) + { + if( m_serverTerminal == null ) + { + m_serverTerminal = new ServerTerminal( + getPeripheralType() == PeripheralType.AdvancedMonitor + ); + } + return m_serverTerminal; + } + else + { + if( m_clientTerminal == null ) + { + m_clientTerminal = new ClientTerminal( + getPeripheralType() == PeripheralType.AdvancedMonitor + ); + } + return m_clientTerminal; + } + } + + // Sizing and placement stuff + + public double getTextScale() + { + return (double)m_textScale * 0.5; + } + + private void rebuildTerminal() + { + Terminal oldTerm = getTerminal().getTerminal(); + int oldWidth = (oldTerm != null) ? oldTerm.getWidth() : -1; + int oldHeight = (oldTerm != null) ? oldTerm.getHeight() : -1; + + double textScale = getTextScale(); + int termWidth = (int)Math.max( + Math.round( ((double)m_width - 2.0 * ( TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN )) / (textScale * 6.0 * TileMonitor.RENDER_PIXEL_SCALE) ), + 1.0 + ); + int termHeight = (int)Math.max( + Math.round( ((double)m_height - 2.0 * ( TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN )) / (textScale * 9.0 * TileMonitor.RENDER_PIXEL_SCALE) ), + 1.0 + ); + ((ServerTerminal)getLocalTerminal()).resize( termWidth, termHeight ); + + if( oldWidth != termWidth || oldHeight != termHeight ) + { + getLocalTerminal().getTerminal().clear(); + for( int y=0; y= 0 && y < worldObj.getHeight() ) + { + if( worldObj.isBlockLoaded( pos ) ) + { + TileEntity tile = worldObj.getTileEntity( pos ); + if( tile != null && tile instanceof TileMonitor ) + { + TileMonitor monitor = (TileMonitor)tile; + if( monitor.getDir() == getDir() && + monitor.getLocalTerminal().isColour() == getLocalTerminal().isColour() && + !monitor.m_destroyed && !monitor.m_ignoreMe ) + { + return monitor; + } + } + } + + } + return null; + } + + private TileMonitor getNeighbour( int x, int y ) + { + BlockPos pos = getPos(); + EnumFacing right = getRight(); + EnumFacing down = getDown(); + int xOffset = -m_xIndex + x; + int yOffset = -m_yIndex + y; + return getSimilarMonitorAt( + pos.offset( right, xOffset ).offset( down, yOffset ) + ); + } + + public TileMonitor getOrigin() + { + return getNeighbour( 0, 0 ); + } + + private void resize( int width, int height ) + { + // Update the positions and indexes of the other monitors + BlockPos pos = getPos(); + EnumFacing right = getRight(); + EnumFacing down = getDown(); + for( int y=0; y 0 ) { + TileMonitor left = getNeighbour( m_xIndex - 1, m_yIndex ); + if( left != null ) { + left.contract( ); + } + } + if( m_xIndex + 1 < m_width ) { + TileMonitor right = getNeighbour( m_xIndex + 1, m_yIndex ); + if( right != null ) { + right.contract(); + } + } + if( m_yIndex > 0 ) { + TileMonitor below = getNeighbour( m_xIndex, m_yIndex - 1 ); + if( below != null ) { + below.contract(); + } + } + if( m_yIndex + 1 < m_height ) { + TileMonitor above = getNeighbour( m_xIndex, m_yIndex + 1 ); + if( above != null ) { + above.contract(); + } + } + m_ignoreMe = false; + } + + public void contract() + { + int height = m_height; + int width = m_width; + + TileMonitor origin = getOrigin(); + if( origin == null ) + { + TileMonitor right = null; + TileMonitor below = null; + if( width > 1 ) { + right = getNeighbour( 1, 0 ); + } + if( height > 1 ) { + below = getNeighbour( 0, 1 ); + } + if( right != null ) { + right.resize( width - 1, 1 ); + } + if( below != null ) { + below.resize( width, height - 1 ); + } + if( right != null ) { + right.expand(); + } + if( below != null ) { + below.expand(); + } + return; + } + + for( int y=0; y 0 ) { + above = origin; + above.resize( width, y ); + } + if( x > 0 ) { + left = origin.getNeighbour( 0, y ); + left.resize( x, 1 ); + } + if( x + 1 < width ) { + right = origin.getNeighbour( x + 1, y ); + right.resize( width - (x + 1), 1 ); + } + if( y + 1 < height ) { + below = origin.getNeighbour( 0, y + 1 ); + below.resize( width, height - (y + 1) ); + } + + // Re-expand + if( above != null ) { + above.expand(); + } + if( left != null ) { + left.expand(); + } + if( right != null ) { + right.expand(); + } + if( below != null ) { + below.expand(); + } + return; + } + } + } + } + + public void monitorTouched( float xPos, float yPos, float zPos ) + { + int side = getDir(); + XYPair pair = convertToXY( xPos, yPos, zPos, side ); + pair = new XYPair( pair.x + m_xIndex, pair.y + m_height - m_yIndex - 1 ); + + if (pair.x > (m_width - RENDER_BORDER) || pair.y > (m_height - RENDER_BORDER) || pair.x < (RENDER_BORDER) || pair.y < (RENDER_BORDER)) + { + return; + } + + Terminal originTerminal = getTerminal().getTerminal(); + if( originTerminal == null ) + { + return; + } + if( !getTerminal().isColour() ) + { + return; + } + + double xCharWidth = ((double)m_width - ((RENDER_BORDER + RENDER_MARGIN) * 2.0)) / ((double)originTerminal.getWidth()); + double yCharHeight = ((double)m_height - ((RENDER_BORDER + RENDER_MARGIN) * 2.0)) / ((double)originTerminal.getHeight()); + + int xCharPos = (int)Math.min((double)originTerminal.getWidth(), Math.max(((pair.x - RENDER_BORDER - RENDER_MARGIN) / xCharWidth) + 1.0, 1.0)); + int yCharPos = (int)Math.min((double)originTerminal.getHeight(), Math.max(((pair.y - RENDER_BORDER - RENDER_MARGIN) / yCharHeight) + 1.0, 1.0)); + + for( int y=0; y 0); + } + } + + @Override + public boolean canInteractWith( EntityPlayer player ) + { + return m_printer.isUseableByPlayer( player ); + } + + @Override + public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int i) + { + ItemStack itemstack = null; + Slot slot = (Slot)inventorySlots.get(i); + if( slot != null && slot.getHasStack() ) + { + ItemStack itemstack1 = slot.getStack(); + itemstack = itemstack1.copy(); + if( i < 13 ) + { + // Transfer from printer to inventory + if(!mergeItemStack(itemstack1, 13, 49, true)) + { + return null; + } + } + else + { + // Transfer from inventory to printer + if( itemstack1.getItem() == Items.dye ) + { + if( !mergeItemStack(itemstack1, 0, 1, false) ) + { + return null; + } + } + else //if is paper + { + if( !mergeItemStack(itemstack1, 1, 13, false) ) + { + return null; + } + } + } + + if(itemstack1.stackSize == 0) + { + slot.putStack(null); + } + else + { + slot.onSlotChanged(); + } + + if(itemstack1.stackSize != itemstack.stackSize) + { + slot.onPickupFromSlot(par1EntityPlayer, itemstack1); + } + else + { + return null; + } + } + return itemstack; + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterPeripheral.java new file mode 100644 index 0000000000..e489d1981d --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterPeripheral.java @@ -0,0 +1,174 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.printer; + +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.core.terminal.Terminal; + +public class PrinterPeripheral implements IPeripheral +{ + private final TilePrinter m_printer; + + public PrinterPeripheral( TilePrinter printer ) + { + m_printer = printer; + } + + @Override + public String getType() + { + return "printer"; + } + + @Override + public String[] getMethodNames() + { + return new String[] { + "write", + "setCursorPos", + "getCursorPos", + "getPageSize", + "newPage", + "endPage", + "getInkLevel", + "setPageTitle", + "getPaperLevel", + }; + } + + @Override + public Object[] callMethod( IComputerAccess computer, ILuaContext context, int method, Object[] args ) throws LuaException + { + switch( method ) + { + case 0: + { + // write + String text; + if( args.length > 0 && args[0] != null ) { + text = args[0].toString(); + } else { + text = ""; + } + + Terminal page = getCurrentPage(); + page.write( text ); + page.setCursorPos( page.getCursorX() + text.length(), page.getCursorY() ); + return null; + } + case 1: + { + // setCursorPos + if( args.length != 2 || args[0] == null || !(args[0] instanceof Number) || args[1] == null || !(args[1] instanceof Number) ) + { + throw new LuaException( "Expected number, number" ); + } + + int x = ((Number)args[0]).intValue() - 1; + int y = ((Number)args[1]).intValue() - 1; + Terminal page = getCurrentPage(); + page.setCursorPos( x, y ); + return null; + } + case 2: + { + // getCursorPos + Terminal page = getCurrentPage(); + int x = page.getCursorX(); + int y = page.getCursorY(); + return new Object[] { x + 1, y + 1 }; + } + case 3: + { + // getPageSize + Terminal page = getCurrentPage(); + int width = page.getWidth(); + int height = page.getHeight(); + return new Object[] { width, height }; + } + case 4: + { + // newPage + return new Object[] { m_printer.startNewPage() }; + } + case 5: + { + // endPage + getCurrentPage(); + return new Object[] { m_printer.endCurrentPage() }; + } + case 6: + { + // getInkLevel + return new Object[] { m_printer.getInkLevel() }; + } + case 7: + { + // setPageTitle + String title = ""; + if( args.length > 0 && args[0] != null ) + { + if( !(args[0] instanceof String) ) + { + throw new LuaException( "Expected string" ); + } + title = (String)args[0]; + } + + getCurrentPage(); + m_printer.setPageTitle( title ); + return null; + } + case 8: + { + // getPaperLevel + return new Object[] { m_printer.getPaperLevel() }; + } + default: + { + return null; + } + } + } + + @Override + public void attach( IComputerAccess computer ) + { + } + + @Override + public void detach( IComputerAccess computer ) + { + } + + @Override + public boolean equals( IPeripheral other ) + { + if( other instanceof PrinterPeripheral ) + { + PrinterPeripheral otherPrinter = (PrinterPeripheral)other; + if( otherPrinter.m_printer == this.m_printer ) + { + return true; + } + } + return false; + } + + private Terminal getCurrentPage() throws LuaException + { + Terminal currentPage = m_printer.getCurrentPage(); + if( currentPage == null ) + { + throw new LuaException( "Page not started" ); + } + return currentPage; + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java b/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java new file mode 100644 index 0000000000..1901eefe0b --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java @@ -0,0 +1,597 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.peripheral.printer; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.core.terminal.Terminal; +import dan200.computercraft.shared.media.items.ItemPrintout; +import dan200.computercraft.shared.peripheral.PeripheralType; +import dan200.computercraft.shared.peripheral.common.TilePeripheralBase; +import dan200.computercraft.shared.util.InventoryUtil; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.ISidedInventory; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.*; +import net.minecraft.world.World; +import net.minecraftforge.common.util.Constants; + +public class TilePrinter extends TilePeripheralBase + implements IInventory, ISidedInventory +{ + // Statics + + private static final int[] bottomSlots = { 7, 8, 9, 10, 11, 12 }; + private static final int[] topSlots = { 1, 2, 3, 4, 5, 6 }; + private static final int[] sideSlots = { 0 }; + + // Members + + private final ItemStack[] m_inventory; + private final Terminal m_page; + private String m_pageTitle; + private boolean m_printing; + + public TilePrinter() + { + m_inventory = new ItemStack[13]; + m_page = new Terminal( ItemPrintout.LINE_MAX_LENGTH, ItemPrintout.LINES_PER_PAGE ); + m_pageTitle = ""; + m_printing = false; + } + + @Override + public void destroy() + { + ejectContents(); + } + + @Override + public boolean onActivate( EntityPlayer player, EnumFacing side, float hitX, float hitY, float hitZ ) + { + if( !player.isSneaking() ) + { + if( !worldObj.isRemote ) + { + ComputerCraft.openPrinterGUI( player, this ); + } + return true; + } + return false; + } + + @Override + public void readFromNBT(NBTTagCompound nbttagcompound) + { + super.readFromNBT(nbttagcompound); + + // Read page + synchronized( m_page ) + { + m_printing = nbttagcompound.getBoolean( "printing" ); + m_pageTitle = nbttagcompound.getString( "pageTitle" ); + m_page.readFromNBT( nbttagcompound ); + } + + // Read inventory + synchronized( m_inventory ) + { + NBTTagList nbttaglist = nbttagcompound.getTagList( "Items", Constants.NBT.TAG_COMPOUND ); + for( int i=0; i= 0 && j < m_inventory.length) + { + m_inventory[j] = ItemStack.loadItemStackFromNBT(itemTag); + } + } + } + } + + @Override + public void writeToNBT(NBTTagCompound nbttagcompound) + { + super.writeToNBT(nbttagcompound); + + // Write page + synchronized( m_page ) + { + nbttagcompound.setBoolean( "printing", m_printing ); + nbttagcompound.setString( "pageTitle", m_pageTitle ); + m_page.writeToNBT( nbttagcompound ); + } + + // Write inventory + synchronized( m_inventory ) + { + NBTTagList nbttaglist = new NBTTagList(); + for(int i=0; i 0 ) + { + return true; + } + return false; + } + } + + private boolean inputPage() + { + synchronized( m_inventory ) + { + ItemStack inkStack = m_inventory[0]; + if( inkStack == null || !isInk(inkStack) ) + { + return false; + } + + for( int i=1; i<7; ++i ) + { + ItemStack paperStack = m_inventory[i]; + if( paperStack != null && isPaper(paperStack) ) + { + // Decrement ink + inkStack.stackSize--; + if( inkStack.stackSize <= 0 ) + { + m_inventory[0] = null; + } + + // Decrement paper + paperStack.stackSize--; + if( paperStack.stackSize <= 0 ) + { + m_inventory[i] = null; + updateAnim(); + } + + // Setup the new page + int colour = inkStack.getItemDamage(); + if( colour >= 0 && colour < 16 ) { + m_page.setTextColour( 15 - colour ); + } else { + m_page.setTextColour( 15 ); + } + + m_page.clear(); + if( paperStack.getItem() instanceof ItemPrintout ) + { + m_pageTitle = ItemPrintout.getTitle( paperStack ); + String[] text = ItemPrintout.getText( paperStack ); + String[] textColour = ItemPrintout.getColours( paperStack ); + for( int y=0; y= 0 || modem ) + { + NBTTagCompound compound = new NBTTagCompound(); + if( id >= 0 ) + { + compound.setInteger( "computerID", id ); + } + if( modem ) + { + compound.setInteger( "upgrade", 1 ); + } + result.setTagCompound( compound ); + } + if( label != null ) + { + result.setStackDisplayName( label ); + } + return result; + } + + @Override + public void getSubItems( Item itemID, CreativeTabs tabs, List list ) + { + list.add( PocketComputerItemFactory.create( -1, null, ComputerFamily.Normal, false ) ); + list.add( PocketComputerItemFactory.create( -1, null, ComputerFamily.Normal, true ) ); + list.add( PocketComputerItemFactory.create( -1, null, ComputerFamily.Advanced, false ) ); + list.add( PocketComputerItemFactory.create( -1, null, ComputerFamily.Advanced, true ) ); + } + + @Override + public void onUpdate( ItemStack stack, World world, Entity entity, int slotNum, boolean selected ) + { + if( !world.isRemote ) + { + // Server side + IInventory inventory = (entity instanceof EntityPlayer) ? ((EntityPlayer)entity).inventory : null; + ServerComputer computer = createServerComputer( world, inventory, stack ); + if( computer != null ) + { + // Ping computer + computer.keepAlive(); + computer.setWorld( world ); + + // Sync ID + int id = computer.getID(); + if( id != getComputerID( stack ) ) + { + setComputerID( stack, id ); + if( inventory != null ) + { + inventory.markDirty(); + } + } + + // Sync label + String label = computer.getLabel(); + if( !Objects.equal( label, getLabel( stack ) ) ) + { + setLabel( stack, label ); + if( inventory != null ) + { + inventory.markDirty(); + } + } + + // Update modem + IPeripheral peripheral = computer.getPeripheral( 2 ); + if( peripheral != null && peripheral instanceof PocketModemPeripheral ) + { + // Location + PocketModemPeripheral modem = (PocketModemPeripheral)peripheral; + if( entity instanceof EntityLivingBase ) + { + EntityLivingBase player = (EntityLivingBase)entity; + modem.setLocation( world, player.posX, player.posY + player.getEyeHeight(), player.posZ ); + } + else + { + modem.setLocation( world, entity.posX, entity.posY, entity.posZ ); + } + + // Light + boolean modemLight = modem.isActive(); + NBTTagCompound modemNBT = computer.getUserData(); + if( modemNBT.getBoolean( "modemLight" ) != modemLight ) + { + modemNBT.setBoolean( "modemLight", modemLight ); + computer.updateUserData(); + } + } + } + } + else + { + // Client side + ClientComputer computer = createClientComputer( stack ); + if( computer != null ) + { + // Todo: things here? + } + } + } + + @Override + public ItemStack onItemRightClick( ItemStack stack, World world, EntityPlayer player ) + { + if( !world.isRemote ) + { + ServerComputer computer = createServerComputer( world, player.inventory, stack ); + if( computer != null ) + { + computer.turnOn(); + } + ComputerCraft.openPocketComputerGUI( player ); + } + return stack; + } + + @Override + public String getUnlocalizedName( ItemStack stack ) + { + switch( getFamily( stack ) ) + { + case Normal: + default: + { + return "item.computercraft:pocket_computer"; + } + case Advanced: + { + return "item.computercraft:advanced_pocket_computer"; + } + } + } + + @Override + public String getItemStackDisplayName( ItemStack stack ) + { + String baseString = getUnlocalizedName( stack ); + boolean modem = getHasModem( stack ); + if( modem ) + { + return StatCollector.translateToLocalFormatted( + baseString + ".upgraded.name", + StatCollector.translateToLocal( "upgrade.computercraft:wireless_modem.adjective" ) + ); + } + else + { + return StatCollector.translateToLocal( baseString + ".name" ); + } + } + + @Override + public void addInformation( ItemStack stack, EntityPlayer player, List list, boolean debug ) + { + if( debug ) + { + int id = getComputerID( stack ); + if( id >= 0 ) + { + list.add( "(Computer ID: " + id + ")" ); + } + } + } + + private ServerComputer createServerComputer( final World world, IInventory inventory, ItemStack stack ) + { + if( world.isRemote ) + { + return null; + } + + ServerComputer computer; + int instanceID = getInstanceID( stack ); + int sessionID = getSessionID( stack ); + int correctSessionID = ComputerCraft.serverComputerRegistry.getSessionID(); + + if( instanceID >= 0 && sessionID == correctSessionID && + ComputerCraft.serverComputerRegistry.contains( instanceID ) ) + { + computer = ComputerCraft.serverComputerRegistry.get( instanceID ); + } + else + { + if( instanceID < 0 || sessionID != correctSessionID ) + { + instanceID = ComputerCraft.serverComputerRegistry.getUnusedInstanceID(); + setInstanceID( stack, instanceID ); + setSessionID( stack, correctSessionID ); + } + int computerID = getComputerID( stack ); + if( computerID < 0 ) + { + computerID = ComputerCraft.createUniqueNumberedSaveDir( world, "computer" ); + setComputerID( stack, computerID ); + } + computer = new ServerComputer( + world, + computerID, + getLabel( stack ), + instanceID, + getFamily( stack ), + ComputerCraft.terminalWidth_pocketComputer, + ComputerCraft.terminalHeight_pocketComputer + ); + computer.addAPI( new PocketAPI() ); + if( getHasModem( stack ) ) + { + computer.setPeripheral( 2, new PocketModemPeripheral( false ) ); + } + ComputerCraft.serverComputerRegistry.add( instanceID, computer ); + if( inventory != null ) + { + inventory.markDirty(); + } + } + computer.setWorld( world ); + return computer; + } + + public ClientComputer createClientComputer( ItemStack stack ) + { + int instanceID = getInstanceID( stack ); + if( instanceID >= 0 ) + { + if( !ComputerCraft.clientComputerRegistry.contains( instanceID ) ) + { + ComputerCraft.clientComputerRegistry.add( instanceID, new ClientComputer( instanceID ) ); + } + return ComputerCraft.clientComputerRegistry.get( instanceID ); + } + return null; + } + + private ClientComputer getClientComputer( ItemStack stack ) + { + int instanceID = getInstanceID( stack ); + if( instanceID >= 0 ) + { + return ComputerCraft.clientComputerRegistry.get( instanceID ); + } + return null; + } + + // IComputerItem implementation + + @Override + public int getComputerID( ItemStack stack ) + { + NBTTagCompound compound = stack.getTagCompound(); + if( compound != null && compound.hasKey( "computerID" ) ) + { + return compound.getInteger( "computerID" ); + } + return -1; + } + + private void setComputerID( ItemStack stack, int computerID ) + { + if( !stack.hasTagCompound() ) + { + stack.setTagCompound( new NBTTagCompound() ); + } + stack.getTagCompound().setInteger( "computerID", computerID ); + } + + @Override + public String getLabel( ItemStack stack ) + { + if( stack.hasDisplayName() ) + { + return stack.getDisplayName(); + } + return null; + } + + @Override + public ComputerFamily getFamily( ItemStack stack ) + { + int damage = stack.getItemDamage(); + switch( damage ) + { + case 0: + default: + { + return ComputerFamily.Normal; + } + case 1: + { + return ComputerFamily.Advanced; + } + } + } + + // IMedia + + @Override + public boolean setLabel( ItemStack stack, String label ) + { + if( label != null ) + { + stack.setStackDisplayName( label ); + } + else + { + stack.clearCustomName(); + } + return true; + } + + @Override + public String getAudioTitle( ItemStack stack ) + { + return null; + } + + @Override + public String getAudioRecordName( ItemStack stack ) + { + return null; + } + + @Override + public IMount createDataMount( ItemStack stack, World world ) + { + ServerComputer computer = createServerComputer( world, null, stack ); + if( computer != null ) + { + return computer.getRootMount(); + } + return null; + } + + private int getInstanceID( ItemStack stack ) + { + NBTTagCompound compound = stack.getTagCompound(); + if( compound != null && compound.hasKey( "instanceID" ) ) + { + return compound.getInteger( "instanceID" ); + } + return -1; + } + + private void setInstanceID( ItemStack stack, int instanceID ) + { + if( !stack.hasTagCompound() ) + { + stack.setTagCompound( new NBTTagCompound() ); + } + stack.getTagCompound().setInteger( "instanceID", instanceID ); + } + + private int getSessionID( ItemStack stack ) + { + NBTTagCompound compound = stack.getTagCompound(); + if( compound != null && compound.hasKey( "sessionID" ) ) + { + return compound.getInteger( "sessionID" ); + } + return -1; + } + + private void setSessionID( ItemStack stack, int sessionID ) + { + if( !stack.hasTagCompound() ) + { + stack.setTagCompound( new NBTTagCompound() ); + } + stack.getTagCompound().setInteger( "sessionID", sessionID ); + } + + public ComputerState getState( ItemStack stack ) + { + ClientComputer computer = getClientComputer( stack ); + if( computer != null && computer.isOn() ) + { + return computer.isCursorDisplayed() ? ComputerState.Blinking : ComputerState.On; + } + return ComputerState.Off; + } + + public boolean getModemState( ItemStack stack ) + { + ClientComputer computer = getClientComputer( stack ); + if( computer != null && computer.isOn() ) + { + NBTTagCompound computerNBT = computer.getUserData(); + if( computerNBT != null && computerNBT.getBoolean( "modemLight" ) ) + { + return true; + } + } + return false; + } + + public boolean getHasModem( ItemStack stack ) + { + NBTTagCompound compound = stack.getTagCompound(); + if( compound != null && compound.hasKey( "upgrade" ) ) + { + return (compound.getInteger( "upgrade" ) == 1); + } + return false; + } +} diff --git a/src/main/java/dan200/computercraft/shared/pocket/items/PocketComputerItemFactory.java b/src/main/java/dan200/computercraft/shared/pocket/items/PocketComputerItemFactory.java new file mode 100644 index 0000000000..2b17d65555 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/pocket/items/PocketComputerItemFactory.java @@ -0,0 +1,28 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.pocket.items; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import net.minecraft.item.ItemStack; + +public class PocketComputerItemFactory +{ + public static ItemStack create( int id, String label, ComputerFamily family, boolean modem ) + { + ItemPocketComputer computer = ComputerCraft.Items.pocketComputer; + switch( family ) + { + case Normal: + case Advanced: + { + return computer.create( id, label, family, modem ); + } + } + return null; + } +} diff --git a/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketModemPeripheral.java b/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketModemPeripheral.java new file mode 100644 index 0000000000..9f1bfcff25 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketModemPeripheral.java @@ -0,0 +1,61 @@ +package dan200.computercraft.shared.pocket.peripherals; + +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.shared.peripheral.modem.WirelessModemPeripheral; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +public class PocketModemPeripheral extends WirelessModemPeripheral +{ + private World m_world; + private Vec3 m_position; + + public PocketModemPeripheral( boolean advanced ) + { + super( advanced ); + m_world = null; + m_position = new Vec3( 0.0, 0.0, 0.0 ); + } + + public void setLocation( World world, double x, double y, double z ) + { + m_position = new Vec3( x, y, z ); + if( m_world != world ) + { + m_world = world; + switchNetwork(); + } + } + + @Override + protected World getWorld() + { + return m_world; + } + + @Override + protected Vec3 getPosition() + { + if( m_world != null ) + { + return m_position; + } + return null; + } + + @Override + public boolean equals( IPeripheral other ) + { + if( other instanceof PocketModemPeripheral ) + { + return true; + } + return false; + } +} diff --git a/src/main/java/dan200/computercraft/shared/pocket/recipes/PocketComputerUpgradeRecipe.java b/src/main/java/dan200/computercraft/shared/pocket/recipes/PocketComputerUpgradeRecipe.java new file mode 100644 index 0000000000..a786235388 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/pocket/recipes/PocketComputerUpgradeRecipe.java @@ -0,0 +1,137 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.pocket.recipes; + +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.peripheral.PeripheralType; +import dan200.computercraft.shared.peripheral.common.IPeripheralItem; +import dan200.computercraft.shared.pocket.items.ItemPocketComputer; +import dan200.computercraft.shared.pocket.items.PocketComputerItemFactory; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.world.World; + +public class PocketComputerUpgradeRecipe implements IRecipe +{ + public PocketComputerUpgradeRecipe() + { + } + + @Override + public int getRecipeSize() + { + return 2; + } + + @Override + public ItemStack getRecipeOutput() + { + return PocketComputerItemFactory.create( -1, null, ComputerFamily.Normal, true ); + } + + @Override + public boolean matches( InventoryCrafting inventory, World world ) + { + return (getCraftingResult( inventory ) != null); + } + + @Override + public ItemStack getCraftingResult( InventoryCrafting inventory ) + { + // Scan the grid for a pocket computer + ItemStack computer = null; + int computerX = -1; + int computerY = -1; + for( int y=0; y m_legacyTurtleUpgrades; + private Map m_turtleUpgrades; + private Map m_dropConsumers; + + public CCTurtleProxyCommon() + { + m_legacyTurtleUpgrades = new HashMap(); + m_turtleUpgrades = new HashMap(); + m_dropConsumers = new WeakHashMap(); + } + + // ICCTurtleProxy implementation + + @Override + public void preInit() + { + registerItems(); + } + + @Override + public void init() + { + registerForgeHandlers(); + registerTileEntities(); + } + + @Override + public void registerTurtleUpgrade( ITurtleUpgrade upgrade ) + { + // Check conditions + int id = upgrade.getLegacyUpgradeID(); + if( id >= 0 && id < 64 ) + { + throw new RuntimeException( "Error registering '"+upgrade.getUnlocalisedAdjective()+" Turtle'. Legacy UpgradeID '"+id+"' is reserved by ComputerCraft" ); + } + + // Register + registerTurtleUpgradeInternal( upgrade ); + } + + @Override + public ITurtleUpgrade getTurtleUpgrade( String id ) + { + return m_turtleUpgrades.get( id ); + } + + @Override + public ITurtleUpgrade getTurtleUpgrade( int legacyId ) + { + return m_legacyTurtleUpgrades.get( legacyId ); + } + + @Override + public ITurtleUpgrade getTurtleUpgrade( ItemStack stack ) + { + for( ITurtleUpgrade upgrade : m_turtleUpgrades.values() ) + { + try + { + ItemStack upgradeStack = upgrade.getCraftingItem(); + if( InventoryUtil.areItemsStackable( upgradeStack, stack ) ) + { + return upgrade; + } + } + catch( Exception e ) + { + continue; + } + } + return null; + } + + public static boolean isUpgradeVanilla( ITurtleUpgrade upgrade ) + { + return upgrade instanceof TurtleTool || upgrade instanceof TurtleModem || upgrade instanceof TurtleCraftingTable; + } + + public static boolean isUpgradeSuitableForFamily( ComputerFamily family, ITurtleUpgrade upgrade ) + { + if( family == ComputerFamily.Beginners ) + { + return upgrade.getType() == TurtleUpgradeType.Tool; + } + else + { + return true; + } + } + + private void addAllUpgradedTurtles( ComputerFamily family, List list ) + { + ItemStack basicStack = TurtleItemFactory.create( -1, null, null, family, null, null, 0, null ); + if( basicStack != null ) + { + list.add( basicStack ); + } + addUpgradedTurtle( family, ComputerCraft.Upgrades.diamondPickaxe, list ); + addUpgradedTurtle( family, ComputerCraft.Upgrades.diamondAxe, list ); + addUpgradedTurtle( family, ComputerCraft.Upgrades.diamondSword, list ); + addUpgradedTurtle( family, ComputerCraft.Upgrades.diamondShovel, list ); + addUpgradedTurtle( family, ComputerCraft.Upgrades.diamondHoe, list ); + addUpgradedTurtle( family, ComputerCraft.Upgrades.craftingTable, list ); + addUpgradedTurtle( family, ComputerCraft.Upgrades.wirelessModem, list ); + addUpgradedTurtle( family, ComputerCraft.Upgrades.advancedModem, list ); + } + + private void addUpgradedTurtle( ComputerFamily family, ITurtleUpgrade upgrade, List list ) + { + if ( isUpgradeSuitableForFamily( family, upgrade ) ) + { + ItemStack stack = TurtleItemFactory.create( -1, null, null, family, upgrade, null, 0, null ); + if( stack != null ) + { + list.add( stack ); + } + } + } + + @Override + public void addAllUpgradedTurtles( List list ) + { + addAllUpgradedTurtles( ComputerFamily.Normal, list ); + addAllUpgradedTurtles( ComputerFamily.Advanced, list ); + } + + @Override + public void setEntityDropConsumer( Entity entity, IEntityDropConsumer consumer ) + { + if( !m_dropConsumers.containsKey( entity ) ) + { + boolean captured = ObfuscationReflectionHelper.getPrivateValue( + Entity.class, + entity, + "captureDrops" + ).booleanValue(); + + if( !captured ) + { + ObfuscationReflectionHelper.setPrivateValue( + Entity.class, + entity, + new Boolean( true ), + "captureDrops" + ); + + ArrayList items = ObfuscationReflectionHelper.getPrivateValue( + Entity.class, + entity, + "capturedDrops" + ); + + if( items == null || items.size() == 0 ) + { + m_dropConsumers.put( entity, consumer ); + } + } + } + } + + @Override + public void clearEntityDropConsumer( Entity entity ) + { + if( m_dropConsumers.containsKey( entity ) ) + { + boolean captured = ObfuscationReflectionHelper.getPrivateValue( + Entity.class, + entity, + "captureDrops" + ); + + if( captured ) + { + ObfuscationReflectionHelper.setPrivateValue( + Entity.class, + entity, + new Boolean( false ), + "captureDrops" + ); + + ArrayList items = ObfuscationReflectionHelper.getPrivateValue( + Entity.class, + entity, + "capturedDrops" + ); + + if( items != null ) + { + dispatchEntityDrops( entity, items ); + items.clear(); + } + } + m_dropConsumers.remove( entity ); + } + } + + private void registerTurtleUpgradeInternal( ITurtleUpgrade upgrade ) + { + // Check conditions + int legacyID = upgrade.getLegacyUpgradeID(); + if( legacyID >= 0 ) + { + if( legacyID >= Short.MAX_VALUE ) + { + throw new RuntimeException( "Error registering '"+upgrade.getUnlocalisedAdjective()+" Turtle'. UpgradeID '"+legacyID+"' is out of range" ); + } + + ITurtleUpgrade existing = m_legacyTurtleUpgrades.get( legacyID ); + if( existing != null ) + { + throw new RuntimeException( "Error registering '" + upgrade.getUnlocalisedAdjective() + " Turtle'. UpgradeID '" + legacyID + "' is already registered by '" + existing.getUnlocalisedAdjective() + " Turtle'" ); + } + } + + String id = upgrade.getUpgradeID().toString(); + ITurtleUpgrade existing = m_turtleUpgrades.get( id ); + if( existing != null ) + { + throw new RuntimeException( "Error registering '" + upgrade.getUnlocalisedAdjective() + " Turtle'. UpgradeID '" + id + "' is already registered by '" + existing.getUnlocalisedAdjective() + " Turtle'" ); + } + + // Register + if( legacyID >= 0 ) + { + m_legacyTurtleUpgrades.put( legacyID, upgrade ); + } + m_turtleUpgrades.put( id, upgrade ); + + // Add a bunch of impostor recipes + if( isUpgradeVanilla( upgrade ) ) + { + // Add fake recipes to fool NEI + List recipeList = CraftingManager.getInstance().getRecipeList(); + ItemStack craftingItem = upgrade.getCraftingItem(); + + // A turtle just containing this upgrade + for( ComputerFamily family : ComputerFamily.values() ) + { + if( !isUpgradeSuitableForFamily( family, upgrade ) ) + { + continue; + } + + ItemStack baseTurtle = TurtleItemFactory.create( -1, null, null, family, null, null, 0, null ); + if( baseTurtle != null ) + { + ItemStack craftedTurtle = TurtleItemFactory.create( -1, null, null, family, upgrade, null, 0, null ); + ItemStack craftedTurtleFlipped = TurtleItemFactory.create( -1, null, null, family, null, upgrade, 0, null ); + recipeList.add( new ImpostorRecipe( 2, 1, new ItemStack[] { baseTurtle, craftingItem }, craftedTurtle ) ); + recipeList.add( new ImpostorRecipe( 2, 1, new ItemStack[] { craftingItem, baseTurtle }, craftedTurtleFlipped ) ); + + // A turtle containing this upgrade and another upgrade + for( ITurtleUpgrade otherUpgrade : m_turtleUpgrades.values() ) + { + if( isUpgradeVanilla( otherUpgrade ) && isUpgradeSuitableForFamily( family, otherUpgrade ) ) + { + ItemStack otherCraftingItem = otherUpgrade.getCraftingItem(); + + ItemStack otherCraftedTurtle = TurtleItemFactory.create( -1, null, null, family, null, otherUpgrade, 0, null ); + ItemStack comboCraftedTurtle = TurtleItemFactory.create( -1, null, null, family, upgrade, otherUpgrade, 0, null ); + + ItemStack otherCraftedTurtleFlipped = TurtleItemFactory.create( -1, null, null, family, otherUpgrade, null, 0, null ); + ItemStack comboCraftedTurtleFlipped = TurtleItemFactory.create( -1, null, null, family, otherUpgrade, upgrade, 0, null ); + + recipeList.add( new ImpostorRecipe( 2, 1, new ItemStack[] { otherCraftingItem, craftedTurtle }, comboCraftedTurtle ) ); + recipeList.add( new ImpostorRecipe( 2, 1, new ItemStack[] { otherCraftedTurtle, craftingItem }, comboCraftedTurtle ) ); + recipeList.add( new ImpostorRecipe( 2, 1, new ItemStack[] { craftedTurtleFlipped, otherCraftingItem }, comboCraftedTurtleFlipped ) ); + recipeList.add( new ImpostorRecipe( 2, 1, new ItemStack[] { craftingItem, otherCraftedTurtleFlipped }, comboCraftedTurtleFlipped ) ); + recipeList.add( new ImpostorRecipe( 3, 1, new ItemStack[] { otherCraftingItem, baseTurtle, craftingItem, }, comboCraftedTurtle ) ); + recipeList.add( new ImpostorRecipe( 3, 1, new ItemStack[] { craftingItem, baseTurtle, otherCraftingItem }, comboCraftedTurtleFlipped ) ); + } + } + } + } + } + } + + private void registerItems() + { + // Blocks + // Turtle + ComputerCraft.Blocks.turtle = BlockTurtle.createTurtleBlock(); + GameRegistry.registerBlock( ComputerCraft.Blocks.turtle, ItemTurtleLegacy.class, "CC-Turtle" ); + + ComputerCraft.Blocks.turtleExpanded = BlockTurtle.createTurtleBlock(); + GameRegistry.registerBlock( ComputerCraft.Blocks.turtleExpanded, ItemTurtleNormal.class, "CC-TurtleExpanded" ); + + // Advanced Turtle + ComputerCraft.Blocks.turtleAdvanced = BlockTurtle.createTurtleBlock(); + GameRegistry.registerBlock( ComputerCraft.Blocks.turtleAdvanced, ItemTurtleAdvanced.class, "CC-TurtleAdvanced" ); + + // Recipe types + RecipeSorter.register( "computercraft:turtle", TurtleRecipe.class, RecipeSorter.Category.SHAPED, "after:minecraft:shapeless" ); + RecipeSorter.register( "computercraft:turtle_upgrade", TurtleUpgradeRecipe.class, RecipeSorter.Category.SHAPED, "after:minecraft:shapeless" ); + + // Recipes + // Turtle + GameRegistry.addRecipe( new TurtleRecipe( new Item[] { + Items.iron_ingot, Items.iron_ingot, Items.iron_ingot, + Items.iron_ingot, Item.getItemFromBlock( ComputerCraft.Blocks.computer ), Items.iron_ingot, + Items.iron_ingot, Item.getItemFromBlock( Blocks.chest ), Items.iron_ingot, + }, ComputerFamily.Normal ) ); + GameRegistry.addRecipe( new TurtleUpgradeRecipe() ); + + // Impostor Turtle recipe (to fool NEI) + ItemStack iron = new ItemStack( Items.iron_ingot, 1 ); + GameRegistry.addRecipe( new ImpostorRecipe( 3, 3, + new ItemStack[] { + iron, iron, iron, + iron, ComputerItemFactory.create( -1, null, ComputerFamily.Normal ), iron, + iron, new ItemStack( Blocks.chest, 1 ), iron, + }, + TurtleItemFactory.create( -1, null, null, ComputerFamily.Normal, null, null, 0, null ) + ) ); + + // Advanced Turtle + GameRegistry.addRecipe( new TurtleRecipe( new Item[] { + Items.gold_ingot, Items.gold_ingot, Items.gold_ingot, + Items.gold_ingot, Item.getItemFromBlock( ComputerCraft.Blocks.computer ), Items.gold_ingot, + Items.gold_ingot, Item.getItemFromBlock( Blocks.chest ), Items.gold_ingot, + }, ComputerFamily.Advanced ) ); + + // Impostor Advanced Turtle recipe (to fool NEI) + ItemStack gold = new ItemStack( Items.gold_ingot, 1 ); + GameRegistry.addRecipe( new ImpostorRecipe( 3, 3, + new ItemStack[] { + gold, gold, gold, + gold, ComputerItemFactory.create( -1, null, ComputerFamily.Advanced ), gold, + gold, new ItemStack( Blocks.chest, 1 ), gold, + }, + TurtleItemFactory.create( -1, null, null, ComputerFamily.Advanced, null, null, 0, null ) + ) ); + + // Upgrades + ComputerCraft.Upgrades.wirelessModem = new TurtleModem( false, new ResourceLocation( "computercraft", "wireless_modem" ), 1 ); + registerTurtleUpgradeInternal( ComputerCraft.Upgrades.wirelessModem ); + + ComputerCraft.Upgrades.craftingTable = new TurtleCraftingTable( 2 ); + registerTurtleUpgradeInternal( ComputerCraft.Upgrades.craftingTable ); + + ComputerCraft.Upgrades.diamondSword = new TurtleSword( new ResourceLocation( "minecraft", "diamond_sword" ), 3, "upgrade.minecraft:diamond_sword.adjective", Items.diamond_sword ); + registerTurtleUpgradeInternal( ComputerCraft.Upgrades.diamondSword ); + + ComputerCraft.Upgrades.diamondShovel = new TurtleShovel( new ResourceLocation( "minecraft", "diamond_shovel" ), 4, "upgrade.minecraft:diamond_shovel.adjective", Items.diamond_shovel ); + registerTurtleUpgradeInternal( ComputerCraft.Upgrades.diamondShovel ); + + ComputerCraft.Upgrades.diamondPickaxe = new TurtleTool( new ResourceLocation( "minecraft", "diamond_pickaxe" ), 5, "upgrade.minecraft:diamond_pickaxe.adjective", Items.diamond_pickaxe ); + registerTurtleUpgradeInternal( ComputerCraft.Upgrades.diamondPickaxe ); + + ComputerCraft.Upgrades.diamondAxe = new TurtleAxe( new ResourceLocation( "minecraft", "diamond_axe" ), 6, "upgrade.minecraft:diamond_axe.adjective", Items.diamond_axe ); + registerTurtleUpgradeInternal( ComputerCraft.Upgrades.diamondAxe ); + + ComputerCraft.Upgrades.diamondHoe = new TurtleHoe( new ResourceLocation( "minecraft", "diamond_hoe" ), 7, "upgrade.minecraft:diamond_hoe.adjective", Items.diamond_hoe ); + registerTurtleUpgradeInternal( ComputerCraft.Upgrades.diamondHoe ); + + ComputerCraft.Upgrades.advancedModem = new TurtleModem( true, new ResourceLocation( "computercraft", "advanced_modem" ), -1 ); + registerTurtleUpgradeInternal( ComputerCraft.Upgrades.advancedModem ); + } + + private void registerTileEntities() + { + // TileEntities + GameRegistry.registerTileEntity( TileTurtle.class, "turtle" ); + GameRegistry.registerTileEntity( TileTurtleExpanded.class, "turtleex" ); + GameRegistry.registerTileEntity( TileTurtleAdvanced.class, "turtleadv" ); + } + + private void registerForgeHandlers() + { + ForgeHandlers handlers = new ForgeHandlers(); + MinecraftForge.EVENT_BUS.register( handlers ); + } + + public class ForgeHandlers + { + private ForgeHandlers() + { + } + + // Forge event responses + @SubscribeEvent + public void onEntityLivingDrops( LivingDropsEvent event ) + { + dispatchEntityDrops( event.entity, event.drops ); + } + } + + private void dispatchEntityDrops( Entity entity, java.util.List drops ) + { + IEntityDropConsumer consumer = m_dropConsumers.get( entity ); + if( consumer != null ) + { + // All checks have passed, lets dispatch the drops + Iterator it = drops.iterator(); + while( it.hasNext() ) + { + EntityItem entityItem = (EntityItem)it.next(); + consumer.consumeDrop( entity, entityItem.getEntityItem() ); + } + drops.clear(); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java b/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java new file mode 100644 index 0000000000..1292a8b66b --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java @@ -0,0 +1,665 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.proxy; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.ComputerCraftAPI; +import dan200.computercraft.core.computer.MainThread; +import dan200.computercraft.shared.common.DefaultBundledRedstoneProvider; +import dan200.computercraft.shared.common.TileGeneric; +import dan200.computercraft.shared.computer.blocks.BlockCommandComputer; +import dan200.computercraft.shared.computer.blocks.BlockComputer; +import dan200.computercraft.shared.computer.blocks.TileCommandComputer; +import dan200.computercraft.shared.computer.blocks.TileComputer; +import dan200.computercraft.shared.computer.core.ClientComputer; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.core.ServerComputer; +import dan200.computercraft.shared.computer.inventory.ContainerComputer; +import dan200.computercraft.shared.computer.items.ComputerItemFactory; +import dan200.computercraft.shared.computer.items.ItemCommandComputer; +import dan200.computercraft.shared.computer.items.ItemComputer; +import dan200.computercraft.shared.media.common.DefaultMediaProvider; +import dan200.computercraft.shared.media.inventory.ContainerHeldItem; +import dan200.computercraft.shared.media.items.ItemDiskExpanded; +import dan200.computercraft.shared.media.items.ItemDiskLegacy; +import dan200.computercraft.shared.media.items.ItemPrintout; +import dan200.computercraft.shared.media.items.ItemTreasureDisk; +import dan200.computercraft.shared.media.recipes.DiskRecipe; +import dan200.computercraft.shared.media.recipes.PrintoutRecipe; +import dan200.computercraft.shared.network.ComputerCraftPacket; +import dan200.computercraft.shared.peripheral.PeripheralType; +import dan200.computercraft.shared.peripheral.commandblock.CommandBlockPeripheralProvider; +import dan200.computercraft.shared.peripheral.common.*; +import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive; +import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive; +import dan200.computercraft.shared.peripheral.modem.BlockAdvancedModem; +import dan200.computercraft.shared.peripheral.modem.TileAdvancedModem; +import dan200.computercraft.shared.peripheral.modem.TileCable; +import dan200.computercraft.shared.peripheral.modem.TileWirelessModem; +import dan200.computercraft.shared.peripheral.monitor.TileMonitor; +import dan200.computercraft.shared.peripheral.printer.ContainerPrinter; +import dan200.computercraft.shared.peripheral.printer.TilePrinter; +import dan200.computercraft.shared.pocket.items.ItemPocketComputer; +import dan200.computercraft.shared.pocket.items.PocketComputerItemFactory; +import dan200.computercraft.shared.pocket.recipes.PocketComputerUpgradeRecipe; +import dan200.computercraft.shared.turtle.blocks.TileTurtle; +import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; +import dan200.computercraft.shared.util.Colour; +import dan200.computercraft.shared.util.CreativeTabMain; +import dan200.computercraft.shared.util.ImpostorRecipe; +import dan200.computercraft.shared.util.ImpostorShapelessRecipe; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.init.Items; +import net.minecraft.item.Item; +import net.minecraft.item.ItemRecord; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.Packet; +import net.minecraft.server.MinecraftServer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.IThreadListener; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import net.minecraftforge.fml.common.network.FMLNetworkEvent; +import net.minecraftforge.fml.common.network.IGuiHandler; +import net.minecraftforge.fml.common.network.NetworkRegistry; +import net.minecraftforge.fml.common.registry.GameRegistry; +import net.minecraftforge.oredict.RecipeSorter; + +import java.io.File; + +public abstract class ComputerCraftProxyCommon implements IComputerCraftProxy +{ + public ComputerCraftProxyCommon() + { + } + + // IComputerCraftProxy implementation + + @Override + public void preInit() + { + registerItems(); + } + + @Override + public void init() + { + registerTileEntities(); + registerForgeHandlers(); + } + + @Override + public abstract boolean isClient(); + + @Override + public abstract boolean getGlobalCursorBlink(); + + @Override + public abstract long getRenderFrame(); + + @Override + public void deleteDisplayLists( int list, int range ) + { + } + + @Override + public abstract Object getFixedWidthFontRenderer(); + + @Override + public String getRecordInfo( ItemStack recordStack ) + { + Item item = recordStack.getItem(); + if( item instanceof ItemRecord ) + { + ItemRecord record = (ItemRecord)item; + if( (( ResourceLocation)Item.itemRegistry.getNameForObject( record )).getResourceDomain().equals( "minecraft" ) ) + { + return "C418 - " + record.recordName; + } + // TODO: determine descriptions for mod items (ie: Portal gun mod) + return record.recordName; + } + return null; + } + + @Override + public abstract void playRecord( String record, String recordInfo, World world, BlockPos pos ); + + @Override + public abstract Object getDiskDriveGUI( InventoryPlayer inventory, TileDiskDrive drive ); + + @Override + public abstract Object getComputerGUI( TileComputer computer ); + + @Override + public abstract Object getPrinterGUI( InventoryPlayer inventory, TilePrinter printer ); + + @Override + public abstract Object getTurtleGUI( InventoryPlayer inventory, TileTurtle turtle ); + + @Override + public abstract Object getPrintoutGUI( InventoryPlayer inventory ); + + @Override + public abstract Object getPocketComputerGUI( InventoryPlayer inventory ); + + public abstract File getWorldDir( World world ); + + @Override + public void handlePacket( final ComputerCraftPacket packet, final EntityPlayer player ) + { + IThreadListener listener = MinecraftServer.getServer(); + if( listener != null ) + { + if( listener.isCallingFromMinecraftThread() ) + { + processPacket( packet, player ); + } + else + { + listener.addScheduledTask( new Runnable() + { + @Override + public void run() + { + processPacket( packet, player ); + } + } ); + } + } + } + + private void processPacket( ComputerCraftPacket packet, EntityPlayer player ) + { + switch( packet.m_packetType ) + { + /////////////////////////////////// + // Packets from Client to Server // + /////////////////////////////////// + case ComputerCraftPacket.TurnOn: + case ComputerCraftPacket.Shutdown: + case ComputerCraftPacket.Reboot: + case ComputerCraftPacket.QueueEvent: + case ComputerCraftPacket.RequestComputerUpdate: + case ComputerCraftPacket.SetLabel: + { + int instance = packet.m_dataInt[0]; + ServerComputer computer = ComputerCraft.serverComputerRegistry.get( instance ); + if( computer != null ) + { + computer.handlePacket( packet, player ); + } + break; + } + case ComputerCraftPacket.RequestTileEntityUpdate: + { + int x = packet.m_dataInt[0]; + int y = packet.m_dataInt[1]; + int z = packet.m_dataInt[2]; + BlockPos pos = new BlockPos( x, y, z ); + World world = player.getEntityWorld(); + TileEntity tileEntity = world.getTileEntity( pos ); + if( tileEntity != null && tileEntity instanceof TileGeneric ) + { + TileGeneric generic = (TileGeneric)tileEntity; + Packet description = generic.getDescriptionPacket(); + if( description != null ) + { + ((EntityPlayerMP)player).playerNetServerHandler.sendPacket( description ); + } + } + break; + } + } + } + + private void registerItems() + { + // Creative tab + ComputerCraft.mainCreativeTab = new CreativeTabMain( CreativeTabs.getNextID() ); + + // Blocks + // Computer + ComputerCraft.Blocks.computer = new BlockComputer(); + GameRegistry.registerBlock( ComputerCraft.Blocks.computer, ItemComputer.class, "CC-Computer" ); + + // Peripheral + ComputerCraft.Blocks.peripheral = new BlockPeripheral(); + GameRegistry.registerBlock( ComputerCraft.Blocks.peripheral, ItemPeripheral.class, "CC-Peripheral" ); + + // Cable + ComputerCraft.Blocks.cable = new BlockCable(); + GameRegistry.registerBlock( ComputerCraft.Blocks.cable, ItemCable.class, "CC-Cable" ); + + // Command Computer + ComputerCraft.Blocks.commandComputer = new BlockCommandComputer(); + GameRegistry.registerBlock( ComputerCraft.Blocks.commandComputer, ItemCommandComputer.class, "command_computer" ); + + // Command Computer + ComputerCraft.Blocks.advancedModem = new BlockAdvancedModem(); + GameRegistry.registerBlock( ComputerCraft.Blocks.advancedModem, ItemAdvancedModem.class, "advanced_modem" ); + + // Items + // Floppy Disk + ComputerCraft.Items.disk = new ItemDiskLegacy(); + GameRegistry.registerItem( ComputerCraft.Items.disk, "disk" ); + + ComputerCraft.Items.diskExpanded = new ItemDiskExpanded(); + GameRegistry.registerItem( ComputerCraft.Items.diskExpanded, "diskExpanded" ); + + // Treasure Disk + ComputerCraft.Items.treasureDisk = new ItemTreasureDisk(); + GameRegistry.registerItem( ComputerCraft.Items.treasureDisk, "treasureDisk" ); + + // Printout + ComputerCraft.Items.printout = new ItemPrintout(); + GameRegistry.registerItem( ComputerCraft.Items.printout, "printout" ); + + // Pocket computer + ComputerCraft.Items.pocketComputer = new ItemPocketComputer(); + GameRegistry.registerItem( ComputerCraft.Items.pocketComputer, "pocketComputer" ); + + // Recipe types + RecipeSorter.register( "computercraft:impostor", ImpostorRecipe.class, RecipeSorter.Category.SHAPED, "after:minecraft:shapeless" ); + RecipeSorter.register( "computercraft:impostor_shapeless", ImpostorShapelessRecipe.class, RecipeSorter.Category.SHAPELESS, "after:minecraft:shapeless" ); + RecipeSorter.register( "computercraft:disk", DiskRecipe.class, RecipeSorter.Category.SHAPELESS, "after:minecraft:shapeless" ); + RecipeSorter.register( "computercraft:printout", PrintoutRecipe.class, RecipeSorter.Category.SHAPELESS, "after:minecraft:shapeless" ); + RecipeSorter.register( "computercraft:pocket_computer_upgrade", PocketComputerUpgradeRecipe.class, RecipeSorter.Category.SHAPELESS, "after:minecraft:shapeless" ); + + // Recipes + // Computer + ItemStack computer = ComputerItemFactory.create( -1, null, ComputerFamily.Normal ); + GameRegistry.addRecipe( computer, + "XXX", "XYX", "XZX", + 'X', Blocks.stone, + 'Y', Items.redstone, + 'Z', Blocks.glass_pane + ); + + // Advanced Computer + ItemStack advancedComputer = ComputerItemFactory.create( -1, null, ComputerFamily.Advanced ); + GameRegistry.addRecipe( advancedComputer, + "XXX", "XYX", "XZX", + 'X', Items.gold_ingot, + 'Y', Items.redstone, + 'Z', Blocks.glass_pane + ); + + // Disk Drive + ItemStack diskDrive = PeripheralItemFactory.create( PeripheralType.DiskDrive, null, 1 ); + GameRegistry.addRecipe( diskDrive, + "XXX", "XYX", "XYX", + 'X', Blocks.stone, + 'Y', Items.redstone + ); + + // Wireless Modem + ItemStack wirelessModem = PeripheralItemFactory.create( PeripheralType.WirelessModem, null, 1 ); + GameRegistry.addRecipe( wirelessModem, + "XXX", "XYX", "XXX", + 'X', Blocks.stone, + 'Y', Items.ender_pearl + ); + + // Monitor + ItemStack monitor = PeripheralItemFactory.create( PeripheralType.Monitor, null, 1 ); + GameRegistry.addRecipe( monitor, + "XXX", "XYX", "XXX", + 'X', Blocks.stone, + 'Y', Blocks.glass_pane + ); + + // PrinterEmpty + ItemStack printer = PeripheralItemFactory.create( PeripheralType.Printer, null, 1 ); + GameRegistry.addRecipe( printer, + "XXX", "XYX", "XZX", + 'X', Blocks.stone, + 'Y', Items.redstone, + 'Z', new ItemStack( Items.dye, 1, 0 ) // 0 = Black + ); + + // Advanced Monitor + ItemStack advancedMonitors = PeripheralItemFactory.create( PeripheralType.AdvancedMonitor, null, 4 ); + GameRegistry.addRecipe( advancedMonitors, + "XXX", "XYX", "XXX", + 'X', Items.gold_ingot, + 'Y', Blocks.glass_pane + ); + + // Networking Cable + ItemStack cable = PeripheralItemFactory.create( PeripheralType.Cable, null, 6 ); + GameRegistry.addRecipe( cable, + " X ", "XYX", " X ", + 'X', Blocks.stone, + 'Y', Items.redstone + ); + + // Wired Modem + ItemStack wiredModem = PeripheralItemFactory.create( PeripheralType.WiredModem, null, 1 ); + GameRegistry.addRecipe( wiredModem, + "XXX", "XYX", "XXX", + 'X', Blocks.stone, + 'Y', Items.redstone + ); + + // Computer + ItemStack commandComputer = ComputerItemFactory.create( -1, null, ComputerFamily.Command ); + GameRegistry.addRecipe( commandComputer, + "XXX", "XYX", "XZX", + 'X', Blocks.stone, + 'Y', Blocks.command_block, + 'Z', Blocks.glass_pane + ); + + // Advanced Modem + ItemStack advancedModem = PeripheralItemFactory.create( PeripheralType.AdvancedModem, null, 1 ); + GameRegistry.addRecipe( advancedModem, + "XXX", "XYX", "XXX", + 'X', Items.gold_ingot, + 'Y', Items.ender_eye + ); + + // Disk + GameRegistry.addRecipe( new DiskRecipe() ); + + // Impostor Disk recipes (to fool NEI) + ItemStack paper = new ItemStack( Items.paper, 1 ); + ItemStack redstone = new ItemStack( Items.redstone, 1 ); + ItemStack basicDisk = ItemDiskLegacy.createFromIDAndColour( -1, null, Colour.Blue.getHex() ); + GameRegistry.addRecipe( new ImpostorShapelessRecipe( basicDisk, new Object[] { redstone, paper } ) ); + + for( int colour=0; colour<16; ++colour ) + { + ItemStack disk = ItemDiskLegacy.createFromIDAndColour( -1, null, Colour.values()[ colour ].getHex() ); + ItemStack dye = new ItemStack( Items.dye, 1, colour ); + for( int otherColour=0; otherColour<16; ++otherColour ) + { + if( colour != otherColour ) + { + ItemStack otherDisk = ItemDiskLegacy.createFromIDAndColour( -1, null, Colour.values()[ colour ].getHex() ); + GameRegistry.addRecipe( new ImpostorShapelessRecipe( disk, new Object[] { + otherDisk, dye + } ) ); + } + } + GameRegistry.addRecipe( new ImpostorShapelessRecipe( disk, new Object[] { + redstone, paper, dye + } ) ); + } + + // Printout + GameRegistry.addRecipe( new PrintoutRecipe() ); + + ItemStack singlePrintout = ItemPrintout.createSingleFromTitleAndText( null, null, null ); + ItemStack multiplePrintout = ItemPrintout.createMultipleFromTitleAndText( null, null, null ); + ItemStack bookPrintout = ItemPrintout.createBookFromTitleAndText( null, null, null ); + + // Impostor Printout recipes (to fool NEI) + ItemStack string = new ItemStack( Items.string, 1, 0 ); + GameRegistry.addRecipe( new ImpostorShapelessRecipe( multiplePrintout, new Object[] { singlePrintout, singlePrintout, string } ) ); + + ItemStack leather = new ItemStack( Items.leather, 1, 0 ); + GameRegistry.addRecipe( new ImpostorShapelessRecipe( bookPrintout, new Object[] { leather, singlePrintout, string } ) ); + + // Pocket Computer + ItemStack pocketComputer = PocketComputerItemFactory.create( -1, null, ComputerFamily.Normal, false ); + GameRegistry.addRecipe( pocketComputer, + "XXX", "XYX", "XZX", + 'X', Blocks.stone, + 'Y', Items.golden_apple, + 'Z', Blocks.glass_pane + ); + + // Advanced Pocket Computer + ItemStack advancedPocketComputer = PocketComputerItemFactory.create( -1, null, ComputerFamily.Advanced, false ); + GameRegistry.addRecipe( advancedPocketComputer, + "XXX", "XYX", "XZX", + 'X', Items.gold_ingot, + 'Y', Items.golden_apple, + 'Z', Blocks.glass_pane + ); + + // Wireless Pocket Computer + ItemStack wirelessPocketComputer = PocketComputerItemFactory.create( -1, null, ComputerFamily.Normal, true ); + GameRegistry.addRecipe( new PocketComputerUpgradeRecipe() ); + + // Advanced Wireless Pocket Computer + ItemStack advancedWirelessPocketComputer = PocketComputerItemFactory.create( -1, null, ComputerFamily.Advanced, true ); + + // Impostor Pocket Computer recipes (to fool NEI) + GameRegistry.addRecipe( new ImpostorRecipe( 1, 2, new ItemStack[] { wirelessModem, pocketComputer }, wirelessPocketComputer ) ); + GameRegistry.addRecipe( new ImpostorRecipe( 1, 2, new ItemStack[] { wirelessModem, advancedPocketComputer }, advancedWirelessPocketComputer ) ); + + // Skulls (Easter Egg) + // Dan + NBTTagCompound tag = new NBTTagCompound(); + tag.setString( "SkullOwner", "dan200" ); + ItemStack danHead = new ItemStack( Items.skull, 1, 3 ); + danHead.setTagCompound( tag ); + GameRegistry.addShapelessRecipe( danHead, computer, new ItemStack( Items.skull, 1, 1 ) ); + + // Cloudy + tag = new NBTTagCompound(); + tag.setString( "SkullOwner", "Cloudhunter" ); + ItemStack cloudyHead = new ItemStack( Items.skull, 1, 3 ); + cloudyHead.setTagCompound( tag ); + GameRegistry.addShapelessRecipe( cloudyHead, monitor, new ItemStack( Items.skull, 1, 1 ) ); + } + + private void registerTileEntities() + { + // Tile Entities + GameRegistry.registerTileEntity( TileComputer.class, "computer" ); + GameRegistry.registerTileEntity( TileDiskDrive.class, "diskdrive" ); + GameRegistry.registerTileEntity( TileWirelessModem.class, "wirelessmodem" ); + GameRegistry.registerTileEntity( TileMonitor.class, "monitor" ); + GameRegistry.registerTileEntity( TilePrinter.class, "ccprinter" ); + GameRegistry.registerTileEntity( TileCable.class, "wiredmodem" ); + GameRegistry.registerTileEntity( TileCommandComputer.class, "command_computer" ); + GameRegistry.registerTileEntity( TileAdvancedModem.class, "advanced_modem" ); + + // Register peripheral providers + ComputerCraftAPI.registerPeripheralProvider( new DefaultPeripheralProvider() ); + if( ComputerCraft.enableCommandBlock ) + { + ComputerCraftAPI.registerPeripheralProvider( new CommandBlockPeripheralProvider() ); + } + + // Register bundled power providers + ComputerCraftAPI.registerBundledRedstoneProvider( new DefaultBundledRedstoneProvider() ); + + // Register media providers + ComputerCraftAPI.registerMediaProvider( new DefaultMediaProvider() ); + } + + private void registerForgeHandlers() + { + ForgeHandlers handlers = new ForgeHandlers(); + MinecraftForge.EVENT_BUS.register( handlers ); + NetworkRegistry.INSTANCE.registerGuiHandler( ComputerCraft.instance, handlers ); + } + + public class ForgeHandlers implements + IGuiHandler + { + private ForgeHandlers() + { + } + + // IGuiHandler implementation + + @Override + public Object getServerGuiElement( int id, EntityPlayer player, World world, int x, int y, int z ) + { + BlockPos pos = new BlockPos( x, y, z ); + switch( id ) + { + case ComputerCraft.diskDriveGUIID: + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileDiskDrive ) + { + TileDiskDrive drive = (TileDiskDrive)tile; + return new ContainerDiskDrive( player.inventory, drive ); + } + break; + } + case ComputerCraft.computerGUIID: + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileComputer ) + { + TileComputer computer = (TileComputer)tile; + return new ContainerComputer( computer ); + } + break; + } + case ComputerCraft.printerGUIID: + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TilePrinter ) + { + TilePrinter printer = (TilePrinter)tile; + return new ContainerPrinter( player.inventory, printer ); + } + break; + } + case ComputerCraft.turtleGUIID: + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileTurtle ) + { + TileTurtle turtle = (TileTurtle)tile; + return new ContainerTurtle( player.inventory, turtle.getAccess() ); + } + break; + } + case ComputerCraft.printoutGUIID: + { + return new ContainerHeldItem( player.inventory ); + } + case ComputerCraft.pocketComputerGUIID: + { + return new ContainerHeldItem( player.inventory ); + } + } + return null; + } + + @Override + public Object getClientGuiElement( int id, EntityPlayer player, World world, int x, int y, int z ) + { + BlockPos pos = new BlockPos( x, y, z ); + switch( id ) + { + case ComputerCraft.diskDriveGUIID: + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileDiskDrive ) + { + TileDiskDrive drive = (TileDiskDrive)tile; + return getDiskDriveGUI( player.inventory, drive ); + } + break; + } + case ComputerCraft.computerGUIID: + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileComputer ) + { + TileComputer computer = (TileComputer)tile; + return getComputerGUI( computer ); + } + break; + } + case ComputerCraft.printerGUIID: + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TilePrinter ) + { + TilePrinter printer = (TilePrinter)tile; + return getPrinterGUI( player.inventory, printer ); + } + break; + } + case ComputerCraft.turtleGUIID: + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileTurtle ) + { + TileTurtle turtle = (TileTurtle)tile; + return getTurtleGUI( player.inventory, turtle ); + } + break; + } + case ComputerCraft.printoutGUIID: + { + return getPrintoutGUI( player.inventory ); + } + case ComputerCraft.pocketComputerGUIID: + { + return getPocketComputerGUI( player.inventory ); + } + } + return null; + } + + // Event handlers + + @SubscribeEvent + public void onConnectionOpened( FMLNetworkEvent.ClientConnectedToServerEvent event ) + { + ComputerCraft.clientComputerRegistry.reset(); + } + + @SubscribeEvent + public void onConnectionClosed( FMLNetworkEvent.ClientDisconnectionFromServerEvent event ) + { + ComputerCraft.clientComputerRegistry.reset(); + } + + @SubscribeEvent + public void onClientTick( TickEvent.ClientTickEvent event ) + { + if( event.phase == TickEvent.Phase.START ) + { + ComputerCraft.clientComputerRegistry.update(); + } + } + + @SubscribeEvent + public void onServerTick( TickEvent.ServerTickEvent event ) + { + if( event.phase == TickEvent.Phase.START ) + { + MainThread.executePendingTasks(); + ComputerCraft.serverComputerRegistry.update(); + } + } + + @SubscribeEvent + public void onWorldLoad( WorldEvent.Load event ) + { + } + + @SubscribeEvent + public void onWorldUnload( WorldEvent.Unload event ) + { + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/proxy/ICCTurtleProxy.java b/src/main/java/dan200/computercraft/shared/proxy/ICCTurtleProxy.java new file mode 100644 index 0000000000..9edd30f66f --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/proxy/ICCTurtleProxy.java @@ -0,0 +1,29 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.proxy; + +import dan200.computercraft.api.turtle.ITurtleUpgrade; +import dan200.computercraft.shared.util.IEntityDropConsumer; +import net.minecraft.entity.Entity; +import net.minecraft.item.ItemStack; + +import java.util.List; + +public interface ICCTurtleProxy +{ + public void preInit(); + public void init(); + + public void registerTurtleUpgrade( ITurtleUpgrade upgrade ); + public ITurtleUpgrade getTurtleUpgrade( String id ); + public ITurtleUpgrade getTurtleUpgrade( int legacyId ); + public ITurtleUpgrade getTurtleUpgrade( ItemStack item ); + public void addAllUpgradedTurtles( List list ); + + public void setEntityDropConsumer( Entity entity, IEntityDropConsumer consumer ); + public void clearEntityDropConsumer( Entity entity ); +} diff --git a/src/main/java/dan200/computercraft/shared/proxy/IComputerCraftProxy.java b/src/main/java/dan200/computercraft/shared/proxy/IComputerCraftProxy.java new file mode 100644 index 0000000000..52d935c221 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/proxy/IComputerCraftProxy.java @@ -0,0 +1,45 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.proxy; + +import dan200.computercraft.shared.computer.blocks.TileComputer; +import dan200.computercraft.shared.network.ComputerCraftPacket; +import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive; +import dan200.computercraft.shared.peripheral.printer.TilePrinter; +import dan200.computercraft.shared.turtle.blocks.TileTurtle; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +import java.io.File; + +public interface IComputerCraftProxy +{ + public void preInit(); + public void init(); + public boolean isClient(); + + public boolean getGlobalCursorBlink(); + public long getRenderFrame(); + public void deleteDisplayLists( int list, int range ); + public Object getFixedWidthFontRenderer(); + + public String getRecordInfo( ItemStack item ); + public void playRecord( String record, String recordInfo, World world, BlockPos pos ); + + public Object getDiskDriveGUI( InventoryPlayer inventory, TileDiskDrive drive ); + public Object getComputerGUI( TileComputer computer ); + public Object getPrinterGUI( InventoryPlayer inventory, TilePrinter printer ); + public Object getTurtleGUI( InventoryPlayer inventory, TileTurtle turtle ); + public abstract Object getPrintoutGUI( InventoryPlayer inventory ); + public abstract Object getPocketComputerGUI( InventoryPlayer inventory ); + + public File getWorldDir( World world ); + public void handlePacket( ComputerCraftPacket packet, EntityPlayer player ); +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java b/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java new file mode 100644 index 0000000000..84f9985ca8 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java @@ -0,0 +1,502 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.apis; + +import com.google.common.base.Optional; +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.api.turtle.ITurtleCommand; +import dan200.computercraft.api.turtle.TurtleSide; +import dan200.computercraft.core.apis.IAPIEnvironment; +import dan200.computercraft.core.apis.ILuaAPI; +import dan200.computercraft.shared.turtle.core.*; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; + +import java.util.HashMap; +import java.util.Map; + +public class TurtleAPI implements ILuaAPI +{ + private IAPIEnvironment m_environment; + private ITurtleAccess m_turtle; + + public TurtleAPI( IAPIEnvironment environment, ITurtleAccess turtle ) + { + m_environment = environment; + m_turtle = turtle; + } + + // ILuaAPI implementation + + @Override + public String[] getNames() + { + return new String[] { + "turtle" + }; + } + + @Override + public void startup( ) + { + } + + @Override + public void advance( double _dt ) + { + } + + @Override + public void shutdown( ) + { + } + + @Override + public String[] getMethodNames() + { + return new String[] { + "forward", + "back", + "up", + "down", + "turnLeft", + "turnRight", + "dig", + "digUp", + "digDown", + "place", + "placeUp", + "placeDown", + "drop", + "select", + "getItemCount", + "getItemSpace", + "detect", + "detectUp", + "detectDown", + "compare", + "compareUp", + "compareDown", + "attack", + "attackUp", + "attackDown", + "dropUp", + "dropDown", + "suck", + "suckUp", + "suckDown", + "getFuelLevel", + "refuel", + "compareTo", + "transferTo", + "getSelectedSlot", + "getFuelLimit", + "equipLeft", + "equipRight", + "inspect", + "inspectUp", + "inspectDown", + "getItemDetail", + }; + } + + private Object[] tryCommand( ILuaContext context, ITurtleCommand command ) throws LuaException, InterruptedException + { + return m_turtle.executeCommand( context, command ); + } + + private int parseSlotNumber( Object[] arguments, int index ) throws LuaException + { + int slot = parseOptionalSlotNumber( arguments, index, 99 ); + if( slot == 99 ) + { + throw new LuaException( "Expected number" ); + } + return slot; + } + + private int parseOptionalSlotNumber( Object[] arguments, int index, int fallback ) throws LuaException + { + if( arguments.length <= index || !(arguments[index] instanceof Number) ) + { + return fallback; + } + int slot = ((Number)arguments[index]).intValue(); + if( slot >= 1 && slot <= 16 ) + { + return slot - 1; + } + else + { + throw new LuaException( "Slot number " + slot + " out of range" ); + } + } + + private int parseCount( Object[] arguments, int index ) throws LuaException + { + if( arguments.length <= index || !(arguments[index] instanceof Number) ) + { + throw new LuaException( "Expected number" ); + } + int count = ((Number)arguments[index]).intValue(); + if( count >= 0 && count <= 64 ) + { + return count; + } + else + { + throw new LuaException( "Item count " + count + " out of range" ); + } + } + + private Optional parseSide( Object[] arguments, int index ) throws LuaException + { + if( arguments.length <= index || arguments[index] == null ) + { + return Optional.absent(); + } + if( !(arguments[ index ] instanceof String) ) + { + throw new LuaException( "Expected string" ); + } + if( arguments[ index ].equals( "left" ) ) + { + return Optional.of( TurtleSide.Left ); + } + else if( arguments[ index ].equals( "right" ) ) + { + return Optional.of( TurtleSide.Right ); + } + else + { + throw new LuaException( "Invalid side" ); + } + } + + @Override + public Object[] callMethod( ILuaContext context, int method, Object[] args ) throws LuaException, InterruptedException + { + switch( method ) + { + case 0: + { + // forward + return tryCommand( context, new TurtleMoveCommand( MoveDirection.Forward ) ); + } + case 1: + { + // back + return tryCommand( context, new TurtleMoveCommand( MoveDirection.Back ) ); + } + case 2: + { + // up + return tryCommand( context, new TurtleMoveCommand( MoveDirection.Up ) ); + } + case 3: + { + // down + return tryCommand( context, new TurtleMoveCommand( MoveDirection.Down ) ); + } + case 4: + { + // turnLeft + return tryCommand( context, new TurtleTurnCommand( TurnDirection.Left ) ); + } + case 5: + { + // turnRight + return tryCommand( context, new TurtleTurnCommand( TurnDirection.Right ) ); + } + case 6: + { + // dig + Optional side = parseSide( args, 0 ); + return tryCommand( context, new TurtleDigCommand( InteractDirection.Forward, side ) ); + } + case 7: + { + // digUp + Optional side = parseSide( args, 0 ); + return tryCommand( context, new TurtleDigCommand( InteractDirection.Up, side ) ); + } + case 8: + { + // digDown + Optional side = parseSide( args, 0 ); + return tryCommand( context, new TurtleDigCommand( InteractDirection.Down, side ) ); + } + case 9: + { + // place + return tryCommand( context, new TurtlePlaceCommand( InteractDirection.Forward, args ) ); + } + case 10: + { + // placeUp + return tryCommand( context, new TurtlePlaceCommand( InteractDirection.Up, args ) ); + } + case 11: + { + // placeDown + return tryCommand( context, new TurtlePlaceCommand( InteractDirection.Down, args ) ); + } + case 12: + { + // drop + int count = 64; + if( args.length > 0 ) + { + count = parseCount( args, 0 ); + } + return tryCommand( context, new TurtleDropCommand( InteractDirection.Forward, count ) ); + } + case 13: + { + // select + int slot = parseSlotNumber( args, 0 ); + return tryCommand( context, new TurtleSelectCommand( slot ) ); + } + case 14: + { + // getItemCount + int slot = parseOptionalSlotNumber( args, 0, m_turtle.getSelectedSlot() ); + ItemStack stack = m_turtle.getInventory().getStackInSlot( slot ); + if( stack != null ) + { + return new Object[] { stack.stackSize }; + } + else + { + return new Object[] { 0 }; + } + } + case 15: + { + // getItemSpace + int slot = parseOptionalSlotNumber( args, 0, m_turtle.getSelectedSlot() ); + ItemStack stack = m_turtle.getInventory().getStackInSlot( slot ); + if( stack != null ) + { + return new Object[] { + Math.min( stack.getMaxStackSize(), 64 ) - stack.stackSize + }; + } + return new Object[] { 64 }; + } + case 16: + { + // detect + return tryCommand( context, new TurtleDetectCommand( InteractDirection.Forward ) ); + } + case 17: + { + // detectUp + return tryCommand( context, new TurtleDetectCommand( InteractDirection.Up ) ); + } + case 18: + { + // detectDown + return tryCommand( context, new TurtleDetectCommand( InteractDirection.Down ) ); + } + case 19: + { + // compare + return tryCommand( context, new TurtleCompareCommand( InteractDirection.Forward ) ); + } + case 20: + { + // compareUp + return tryCommand( context, new TurtleCompareCommand( InteractDirection.Up ) ); + } + case 21: + { + // compareDown + return tryCommand( context, new TurtleCompareCommand( InteractDirection.Down ) ); + } + case 22: + { + // attack + Optional side = parseSide( args, 0 ); + return tryCommand( context, new TurtleAttackCommand( InteractDirection.Forward, side ) ); + } + case 23: + { + // attackUp + Optional side = parseSide( args, 0 ); + return tryCommand( context, new TurtleAttackCommand( InteractDirection.Up, side ) ); + } + case 24: + { + // attackDown + Optional side = parseSide( args, 0 ); + return tryCommand( context, new TurtleAttackCommand( InteractDirection.Down, side ) ); + } + case 25: + { + // dropUp + int count = 64; + if( args.length > 0 ) + { + count = parseCount( args, 0 ); + } + return tryCommand( context, new TurtleDropCommand( InteractDirection.Up, count ) ); + } + case 26: + { + // dropDown + int count = 64; + if( args.length > 0 ) + { + count = parseCount( args, 0 ); + } + return tryCommand( context, new TurtleDropCommand( InteractDirection.Down, count ) ); + } + case 27: + { + // suck + int count = 64; + if( args.length > 0 ) + { + count = parseCount( args, 0 ); + } + return tryCommand( context, new TurtleSuckCommand( InteractDirection.Forward, count ) ); + } + case 28: + { + // suckUp + int count = 64; + if( args.length > 0 ) + { + count = parseCount( args, 0 ); + } + return tryCommand( context, new TurtleSuckCommand( InteractDirection.Up, count ) ); + } + case 29: + { + // suckDown + int count = 64; + if( args.length > 0 ) + { + count = parseCount( args, 0 ); + } + return tryCommand( context, new TurtleSuckCommand( InteractDirection.Down, count ) ); + } + case 30: + { + // getFuelLevel + if( m_turtle.isFuelNeeded() ) + { + return new Object[] { m_turtle.getFuelLevel() }; + } + else + { + return new Object[] { "unlimited" }; + } + } + case 31: + { + // refuel + int count = 64; + if( args.length > 0 ) + { + count = parseCount( args, 0 ); + } + return tryCommand( context, new TurtleRefuelCommand( count ) ); + } + case 32: + { + // compareTo + int slot = parseSlotNumber( args, 0 ); + return tryCommand( context, new TurtleCompareToCommand( slot ) ); + } + case 33: + { + // transferTo + int slot = parseSlotNumber( args, 0 ); + int count = 64; + if( args.length > 1 ) + { + count = parseCount( args, 1 ); + } + return tryCommand( context, new TurtleTransferToCommand( slot, count ) ); + } + case 34: + { + // getSelectedSlot + return new Object[] { m_turtle.getSelectedSlot() + 1 }; + } + case 35: + { + // getFuelLimit + if( m_turtle.isFuelNeeded() ) + { + return new Object[] { m_turtle.getFuelLimit() }; + } + else + { + return new Object[] { "unlimited" }; + } + } + case 36: + { + // equipLeft + return tryCommand( context, new TurtleEquipCommand( TurtleSide.Left ) ); + } + case 37: + { + // equipRight + return tryCommand( context, new TurtleEquipCommand( TurtleSide.Right ) ); + } + case 38: + { + // inspect + return tryCommand( context, new TurtleInspectCommand( InteractDirection.Forward ) ); + } + case 39: + { + // inspectUp + return tryCommand( context, new TurtleInspectCommand( InteractDirection.Up ) ); + } + case 40: + { + // inspectDown + return tryCommand( context, new TurtleInspectCommand( InteractDirection.Down ) ); + } + case 41: + { + // getItemDetail + int slot = parseOptionalSlotNumber( args, 0, m_turtle.getSelectedSlot() ); + ItemStack stack = m_turtle.getInventory().getStackInSlot( slot ); + if( stack != null && stack.stackSize > 0 ) + { + Item item = stack.getItem(); + String name = ((ResourceLocation)Item.itemRegistry.getNameForObject( item )).toString(); + int damage = stack.getItemDamage(); + int count = stack.stackSize; + + Map table = new HashMap(); + table.put( "name", name ); + table.put( "damage", damage ); + table.put( "count", count ); + return new Object[] { table }; + } + else + { + return new Object[] { null }; + } + } + default: + { + return null; + } + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/blocks/BlockTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/blocks/BlockTurtle.java new file mode 100644 index 0000000000..009b61a59a --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/blocks/BlockTurtle.java @@ -0,0 +1,176 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.blocks; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.computer.blocks.BlockComputerBase; +import dan200.computercraft.shared.computer.blocks.TileCommandComputer; +import dan200.computercraft.shared.computer.blocks.TileComputerBase; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.util.DirectionUtil; +import net.minecraft.block.material.Material; +import net.minecraft.block.properties.IProperty; +import net.minecraft.block.properties.PropertyDirection; +import net.minecraft.block.properties.PropertyEnum; +import net.minecraft.block.state.BlockState; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +public class BlockTurtle extends BlockComputerBase +{ + // Statics + + public static class Properties + { + public static final PropertyDirection FACING = PropertyDirection.create( "facing", EnumFacing.Plane.HORIZONTAL ); + public static final PropertyEnum DYE = PropertyEnum.create( "dye", BlockTurtleDyeVariant.class ); + } + + public static BlockTurtle createTurtleBlock() + { + return new BlockTurtle(); + } + + // Members + + public BlockTurtle() + { + super( Material.iron ); + setHardness( 2.5f ); + setUnlocalizedName( "computercraft:turtle" ); + setCreativeTab( ComputerCraft.mainCreativeTab ); + setDefaultState( this.blockState.getBaseState() + .withProperty( Properties.FACING, EnumFacing.NORTH ) + .withProperty( Properties.DYE, BlockTurtleDyeVariant.None ) + ); + } + + @Override + public int getRenderType() + { + return -1; + } + + @Override + public boolean isOpaqueCube() + { + return false; + } + + @Override + public boolean isFullCube() + { + return false; + } + + @Override + protected BlockState createBlockState() + { + return new BlockState(this, new IProperty[] { + Properties.FACING, + Properties.DYE + }); + } + + @Override + public IBlockState getStateFromMeta( int meta ) + { + return getDefaultState(); + } + + @Override + public int getMetaFromState( IBlockState state ) + { + return 0; + } + + @Override + public IBlockState getActualState( IBlockState state, IBlockAccess world, BlockPos pos ) + { + state = state.withProperty( Properties.FACING, getDirection( world, pos ) ); + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof ITurtleTile ) + { + ITurtleTile turtle = (ITurtleTile)tile; + state = state.withProperty( Properties.DYE, BlockTurtleDyeVariant.fromColour( turtle.getColour() ) ); + } + else + { + state = state.withProperty( Properties.DYE, BlockTurtleDyeVariant.None ); + } + return state; + } + + @Override + protected IBlockState getDefaultBlockState( ComputerFamily family, EnumFacing placedSide ) + { + return getDefaultState(); + } + + private ComputerFamily getFamily() + { + if( this == ComputerCraft.Blocks.turtleAdvanced ) + { + return ComputerFamily.Advanced; + } + else + { + return ComputerFamily.Normal; + } + } + + @Override + public ComputerFamily getFamily( int damage ) + { + return getFamily(); + } + + @Override + public ComputerFamily getFamily( IBlockState state ) + { + return getFamily(); + } + + @Override + protected TileComputerBase createTile( ComputerFamily family ) + { + if( this == ComputerCraft.Blocks.turtleAdvanced ) + { + return new TileTurtleAdvanced(); + } + else if( this == ComputerCraft.Blocks.turtleExpanded ) + { + return new TileTurtleExpanded(); + } + else + { + return new TileTurtle(); + } + } + + @Override + public void onBlockPlacedBy( World world, BlockPos pos, IBlockState state, EntityLivingBase player, ItemStack itemstack ) + { + // Not sure why this is necessary + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileTurtle ) + { + tile.setWorldObj( world ); // Not sure why this is necessary + tile.setPos( pos ); // Not sure why this is necessary + } + + // Set direction + EnumFacing dir = DirectionUtil.fromEntityRot( player ); + setDirection( world, pos, dir.getOpposite() ); + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/blocks/BlockTurtleDyeVariant.java b/src/main/java/dan200/computercraft/shared/turtle/blocks/BlockTurtleDyeVariant.java new file mode 100644 index 0000000000..f6c96d01dd --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/blocks/BlockTurtleDyeVariant.java @@ -0,0 +1,84 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.blocks; + +import dan200.computercraft.shared.util.Colour; +import net.minecraft.util.IStringSerializable; + +public enum BlockTurtleDyeVariant implements IStringSerializable +{ + None( "none", null ), + Black( "black", Colour.Black ), + Red( "red", Colour.Red ), + Green( "green", Colour.Green ), + Brown( "brown", Colour.Brown ), + Blue( "blue", Colour.Blue ), + Purple( "purple", Colour.Purple ), + Cyan( "cyan", Colour.Cyan ), + LightGrey( "light_grey", Colour.LightGrey ), + Grey( "grey", Colour.Grey ), + Pink( "pink", Colour.Pink ), + Lime( "lime", Colour.Lime ), + Yellow( "yellow", Colour.Yellow ), + LightBlue( "light_blue", Colour.LightBlue ), + Magenta( "magenta", Colour.Magenta ), + Orange( "orange", Colour.Orange ), + White( "white", Colour.Orange ); + + public static BlockTurtleDyeVariant fromColour( Colour colour ) + { + if( colour != null ) + { + switch( colour ) + { + case Black: return Black; + case Red: return Red; + case Green: return Green; + case Brown: return Brown; + case Blue: return Blue; + case Purple: return Purple; + case Cyan: return Cyan; + case LightGrey: return LightGrey; + case Grey: return Grey; + case Pink: return Pink; + case Lime: return Lime; + case Yellow: return Yellow; + case LightBlue: return LightBlue; + case Magenta: return Magenta; + case Orange: return Orange; + case White: return White; + } + } + return None; + } + + private String m_name; + private Colour m_colour; + + private BlockTurtleDyeVariant( String name, Colour colour ) + { + m_name = name; + m_colour = colour; + } + + @Override + public String getName() + { + return m_name; + } + + public Colour getColour() + { + return m_colour; + } + + @Override + public String toString() + { + return getName(); + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/blocks/ITurtleTile.java b/src/main/java/dan200/computercraft/shared/turtle/blocks/ITurtleTile.java new file mode 100644 index 0000000000..1956861d2a --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/blocks/ITurtleTile.java @@ -0,0 +1,28 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.blocks; + +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.api.turtle.ITurtleUpgrade; +import dan200.computercraft.api.turtle.TurtleSide; +import dan200.computercraft.shared.common.IDirectionalTile; +import dan200.computercraft.shared.computer.blocks.IComputerTile; +import dan200.computercraft.shared.util.Colour; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.Vec3; + +public interface ITurtleTile extends IComputerTile, IDirectionalTile +{ + public Colour getColour(); + public ResourceLocation getOverlay(); + public ITurtleUpgrade getUpgrade( TurtleSide side ); + public ITurtleAccess getAccess(); + + public Vec3 getRenderOffset( float f ); + public float getRenderYaw( float f ); + public float getToolRenderAngle( TurtleSide side, float f ); +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java new file mode 100644 index 0000000000..06f4d2861f --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java @@ -0,0 +1,665 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.blocks; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.api.turtle.ITurtleUpgrade; +import dan200.computercraft.api.turtle.TurtleSide; +import dan200.computercraft.api.turtle.TurtleUpgradeType; +import dan200.computercraft.shared.computer.blocks.TileComputerBase; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.core.IComputer; +import dan200.computercraft.shared.computer.core.ServerComputer; +import dan200.computercraft.shared.turtle.apis.TurtleAPI; +import dan200.computercraft.shared.turtle.core.TurtleBrain; +import dan200.computercraft.shared.turtle.items.TurtleItemFactory; +import dan200.computercraft.shared.util.*; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.projectile.EntityFireball; +import net.minecraft.init.Items; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.ITickable; +import net.minecraft.util.*; +import net.minecraftforge.common.util.Constants; + +import java.util.List; + +public class TileTurtle extends TileComputerBase + implements ITurtleTile, IInventory, ITickable +{ + // Statics + + public static final int INVENTORY_SIZE = 16; + public static final int INVENTORY_WIDTH = 4; + public static final int INVENTORY_HEIGHT = 4; + + // Members + + private ItemStack[] m_inventory; + private ItemStack[] m_previousInventory; + private boolean m_inventoryChanged; + private TurtleBrain m_brain; + private boolean m_moved; + + public TileTurtle() + { + m_inventory = new ItemStack[ INVENTORY_SIZE ]; + m_previousInventory = new ItemStack[ getSizeInventory() ]; + m_inventoryChanged = false; + m_brain = createBrain(); + m_moved = false; + } + + public boolean hasMoved() + { + return m_moved; + } + + protected TurtleBrain createBrain() + { + return new TurtleBrain( this ); + } + + protected final ServerComputer createComputer( int instanceID, int id, int termWidth, int termHeight ) + { + ServerComputer computer = new ServerComputer( + worldObj, + id, + m_label, + instanceID, + getFamily(), + termWidth, + termHeight + ); + computer.setPosition( getPos() ); + computer.addAPI( new TurtleAPI( computer.getAPIEnvironment(), getAccess() ) ); + m_brain.setupComputer( computer ); + return computer; + } + + @Override + protected ServerComputer createComputer( int instanceID, int id ) + { + return createComputer( instanceID, id, ComputerCraft.terminalWidth_turtle, ComputerCraft.terminalHeight_turtle ); + } + + @Override + public void destroy() + { + if( !hasMoved() ) + { + // Stop computer + super.destroy(); + + // Drop contents + if( !worldObj.isRemote ) + { + int size = getSizeInventory(); + for( int i=0; i drops, int fortune, boolean creative, boolean silkTouch ) + { + IComputer computer = getComputer(); + if( !creative || (computer != null && computer.getLabel() != null) ) + { + drops.add( TurtleItemFactory.create( this ) ); + } + } + + @Override + public ItemStack getPickedItem() + { + return TurtleItemFactory.create( this ); + } + + @Override + public boolean onActivate( EntityPlayer player, EnumFacing side, float hitX, float hitY, float hitZ ) + { + // Request description from server + requestTileEntityUpdate(); + + // Apply dye + ItemStack currentItem = player.getCurrentEquippedItem(); + if( currentItem != null ) + { + if( currentItem.getItem() == Items.dye ) + { + // Dye to change turtle colour + if( !worldObj.isRemote ) + { + int dye = (currentItem.getItemDamage() & 0xf); + if( m_brain.getDyeColour() != dye ) + { + m_brain.setDyeColour( dye ); + if( !player.capabilities.isCreativeMode ) + { + currentItem.stackSize--; + } + } + } + return true; + } + else if( currentItem.getItem() == Items.water_bucket && m_brain.getDyeColour() != -1 ) + { + // Water to remove turtle colour + if( !worldObj.isRemote ) + { + if( m_brain.getDyeColour() != -1 ) + { + m_brain.setDyeColour( -1 ); + if( !player.capabilities.isCreativeMode ) + { + currentItem.setItem( Items.bucket ); + } + } + } + return true; + } + } + + // Open GUI or whatever + return super.onActivate( player, side, hitX, hitY, hitZ ); + } + + @Override + protected boolean canNameWithTag( EntityPlayer player ) + { + return true; + } + + @Override + public void openGUI( EntityPlayer player ) + { + ComputerCraft.openTurtleGUI( player, this ); + } + + @Override + public boolean isSolidOnSide( int side ) + { + return false; + } + + @Override + public boolean isImmuneToExplosion( Entity exploder ) + { + if( getFamily() == ComputerFamily.Advanced ) + { + return true; + } + else + { + if( exploder != null && ( exploder instanceof EntityLivingBase || exploder instanceof EntityFireball ) ) + { + return true; + } + return false; + } + } + + @Override + public AxisAlignedBB getBounds() + { + Vec3 offset = getRenderOffset( 1.0f ); + return new AxisAlignedBB( + offset.xCoord + 0.125, offset.yCoord + 0.125, offset.zCoord + 0.125, + offset.xCoord + 0.875, offset.yCoord + 0.875, offset.zCoord + 0.875 + ); + } + + @Override + protected double getInteractRange( EntityPlayer player ) + { + return 12.0; + } + + @Override + public void update() + { + super.update(); + m_brain.update(); + synchronized( m_inventory ) + { + if( !worldObj.isRemote && m_inventoryChanged ) + { + IComputer computer = getComputer(); + if( computer != null ) + { + computer.queueEvent( "turtle_inventory" ); + } + + m_inventoryChanged = false; + for( int n=0; n= 0 && slot < getSizeInventory() ) + { + m_inventory[slot] = ItemStack.loadItemStackFromNBT( itemtag ); + m_previousInventory[slot] = InventoryUtil.copyItem( m_inventory[slot] ); + } + } + + // Read state + m_brain.readFromNBT( nbttagcompound ); + } + + @Override + public void writeToNBT( NBTTagCompound nbttagcompound ) + { + super.writeToNBT( nbttagcompound ); + + // Write inventory + NBTTagList nbttaglist = new NBTTagList(); + for( int i=0; i= 0 ) + { + return Colour.values()[ dye ]; + } + return null; + } + + @Override + public ResourceLocation getOverlay() + { + return m_brain.getOverlay(); + } + + @Override + public ITurtleAccess getAccess() + { + return m_brain; + } + + @Override + public Vec3 getRenderOffset( float f ) + { + return m_brain.getRenderOffset( f ); + } + + @Override + public float getRenderYaw( float f ) + { + return m_brain.getVisualYaw( f ); + } + + @Override + public float getToolRenderAngle( TurtleSide side, float f ) + { + return m_brain.getToolRenderAngle( side, f ); + } + + // IInventory + + @Override + public int getSizeInventory() + { + return INVENTORY_SIZE; + } + + @Override + public ItemStack getStackInSlot( int slot ) + { + if( slot >= 0 && slot < INVENTORY_SIZE ) + { + synchronized( m_inventory ) + { + return m_inventory[ slot ]; + } + } + return null; + } + + @Override + public ItemStack removeStackFromSlot( int slot ) + { + synchronized( m_inventory ) + { + ItemStack result = getStackInSlot( slot ); + setInventorySlotContents( slot, null ); + return result; + } + } + + @Override + public ItemStack decrStackSize( int slot, int count ) + { + if( count == 0 ) + { + return null; + } + + synchronized( m_inventory ) + { + ItemStack stack = getStackInSlot( slot ); + if( stack == null ) + { + return null; + } + + if( stack.stackSize <= count ) + { + setInventorySlotContents( slot, null ); + return stack; + } + + ItemStack part = stack.splitStack( count ); + onInventoryDefinitelyChanged(); + return part; + } + } + + @Override + public void setInventorySlotContents( int i, ItemStack stack ) + { + if( i >= 0 && i < INVENTORY_SIZE ) + { + synchronized( m_inventory ) + { + if( !InventoryUtil.areItemsEqual( stack, m_inventory[ i ] ) ) + { + m_inventory[ i ] = stack; + onInventoryDefinitelyChanged(); + } + } + } + } + + @Override + public void clear() + { + synchronized( m_inventory ) + { + boolean changed = false; + for( int i = 0; i < INVENTORY_SIZE; ++i ) + { + if( m_inventory[i] != null ) + { + m_inventory[i] = null; + changed = true; + } + } + if( changed ) + { + onInventoryDefinitelyChanged(); + } + } + } + + @Override + public String getName() + { + IComputer computer = getComputer(); + if( computer != null ) + { + String label = computer.getLabel(); + if( label != null && label.length() > 0 ) + { + return label; + } + } + return "tile.computercraft:turtle.name"; + } + + @Override + public boolean hasCustomName() + { + IComputer computer = getComputer(); + if( computer != null ) + { + String label = computer.getLabel(); + if( label != null && label.length() > 0 ) + { + return true; + } + } + return false; + } + + @Override + public IChatComponent getDisplayName() + { + if( hasCustomName() ) + { + return new ChatComponentText( getName() ); + } + else + { + return new ChatComponentTranslation( getName() ); + } + } + + @Override + public int getInventoryStackLimit() + { + return 64; + } + + @Override + public void openInventory( EntityPlayer player ) + { + } + + @Override + public void closeInventory( EntityPlayer player ) + { + } + + @Override + public boolean isItemValidForSlot( int slot, ItemStack stack ) + { + return true; + } + + @Override + public void markDirty() + { + super.markDirty(); + synchronized( m_inventory ) + { + if( !m_inventoryChanged ) + { + for( int n=0; n side ) + { + super( TurtleVerb.Attack, direction, side ); + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java new file mode 100644 index 0000000000..2a61f145dd --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java @@ -0,0 +1,1176 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.core; + +import com.google.common.base.Objects; +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.api.turtle.*; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.core.IComputer; +import dan200.computercraft.shared.computer.core.ServerComputer; +import dan200.computercraft.shared.turtle.blocks.TileTurtle; +import dan200.computercraft.shared.util.Colour; +import dan200.computercraft.shared.util.DirectionUtil; +import dan200.computercraft.shared.util.Holiday; +import dan200.computercraft.shared.util.HolidayUtil; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.inventory.IInventory; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.*; +import net.minecraft.world.World; +import net.minecraftforge.common.util.Constants; + +import java.lang.ref.WeakReference; +import java.util.*; + +public class TurtleBrain implements ITurtleAccess +{ + private static int s_nextInstanceID = 0; + private static Map> s_allClientBrains = new HashMap>(); + + public static int assignInstanceID() + { + return s_nextInstanceID++; + } + + public static TurtleBrain getClientBrain( int instanceID ) + { + if( instanceID >= 0 ) + { + WeakReference ref = s_allClientBrains.get( instanceID ); + if( ref != null ) + { + TurtleBrain brain = ref.get(); + if( brain != null ) + { + return brain; + } + else + { + s_allClientBrains.remove( instanceID ); + } + } + } + return null; + } + + public static void setClientBrain( int instanceID, TurtleBrain brain ) + { + if( instanceID >= 0 ) + { + if( getClientBrain( instanceID ) != brain ) + { + s_allClientBrains.put( instanceID, new WeakReference( brain ) ); + } + } + } + + public static void cleanupBrains() + { + if( s_allClientBrains.size() > 0 ) + { + Iterator>> it = s_allClientBrains.entrySet().iterator(); + while( it.hasNext() ) + { + Map.Entry> entry = it.next(); + WeakReference ref = entry.getValue(); + if( ref != null ) + { + TurtleBrain brain = ref.get(); + if( brain == null ) + { + it.remove(); + } + } + } + } + } + + private static final int ANIM_DURATION = 8; + + private TileTurtle m_owner; + + private LinkedList m_commandQueue; + private int m_commandsIssued; + + private Map m_upgrades; + private Map m_peripherals; + private Map m_upgradeNBTData; + + private int m_selectedSlot; + private int m_fuelLevel; + private Colour m_colour; + private ResourceLocation m_overlay; + + private int m_instanceID; + private EnumFacing m_direction; + private TurtleAnimation m_animation; + private int m_animationProgress; + private int m_lastAnimationProgress; + + public TurtleBrain( TileTurtle turtle ) + { + m_owner = turtle; + + m_commandQueue = new LinkedList(); + m_commandsIssued = 0; + + m_upgrades = new HashMap(); + m_peripherals = new HashMap(); + m_upgradeNBTData = new HashMap(); + + m_selectedSlot = 0; + m_fuelLevel = 0; + m_colour = null; + m_overlay = null; + + m_instanceID = -1; + m_direction = EnumFacing.NORTH; + m_animation = TurtleAnimation.None; + m_animationProgress = 0; + m_lastAnimationProgress = 0; + } + + public TurtleBrain getFutureSelf() + { + if( getOwner().getWorld().isRemote ) + { + TurtleBrain futureSelf = getClientBrain( m_instanceID ); + if( futureSelf != null ) + { + return futureSelf; + } + } + return this; + } + + public void setOwner( TileTurtle owner ) + { + m_owner = owner; + } + + public TileTurtle getOwner() + { + return m_owner; + } + + public ComputerFamily getFamily() + { + return m_owner.getFamily(); + } + + public void setupComputer( ServerComputer computer ) + { + updatePeripherals( computer ); + } + + public void update() + { + World world = getWorld(); + if( !world.isRemote ) + { + // Advance movement + updateCommands(); + } + + // Advance animation + updateAnimation(); + + // Advance upgrades + if( !m_upgrades.isEmpty() ) + { + for( Map.Entry entry : m_upgrades.entrySet() ) + { + entry.getValue().update( this, entry.getKey() ); + } + } + } + + public void readFromNBT( NBTTagCompound nbttagcompound ) + { + // Read state + m_direction = EnumFacing.getFront( nbttagcompound.getInteger( "dir" ) ); + m_selectedSlot = nbttagcompound.getInteger( "selectedSlot" ); + if( nbttagcompound.hasKey( "fuelLevel" ) ) + { + m_fuelLevel = nbttagcompound.getInteger( "fuelLevel" ); + } + else + { + m_fuelLevel = 0; + } + + // Read colour + if( nbttagcompound.hasKey( "colourIndex" ) ) + { + m_colour = Colour.values()[ nbttagcompound.getInteger( "colourIndex" ) ]; + } + else + { + m_colour = null; + } + + // Read overlay + if( nbttagcompound.hasKey( "overlay_mod" ) ) + { + String overlay_mod = nbttagcompound.getString( "overlay_mod" ); + if( nbttagcompound.hasKey( "overlay_path" ) ) + { + String overlay_path = nbttagcompound.getString( "overlay_path" ); + m_overlay = new ResourceLocation( overlay_mod, overlay_path ); + } + else + { + m_overlay = null; + } + } + else + { + m_overlay = null; + } + + // Read upgrades + // (pre-1.4 turtles will have a "subType" variable, newer things will have "leftUpgrade" and "rightUpgrade") + ITurtleUpgrade leftUpgrade = null; + ITurtleUpgrade rightUpgrade = null; + if( nbttagcompound.hasKey( "subType" ) ) + { + // Loading a pre-1.4 world + int subType = nbttagcompound.getInteger( "subType" ); + if( (subType & 0x1) > 0 ) + { + leftUpgrade = ComputerCraft.Upgrades.diamondPickaxe; + } + if( (subType & 0x2) > 0 ) + { + rightUpgrade = ComputerCraft.Upgrades.wirelessModem; + } + } + else + { + // Loading a post-1.4 world + if( nbttagcompound.hasKey( "leftUpgrade" ) ) + { + if( nbttagcompound.getTagId( "leftUpgrade" ) == Constants.NBT.TAG_STRING ) + { + leftUpgrade = ComputerCraft.getTurtleUpgrade( nbttagcompound.getString( "leftUpgrade" ) ); + } + else + { + leftUpgrade = ComputerCraft.getTurtleUpgrade( nbttagcompound.getShort( "leftUpgrade" ) ); + } + } + if( nbttagcompound.hasKey( "rightUpgrade" ) ) + { + if( nbttagcompound.getTagId( "rightUpgrade" ) == Constants.NBT.TAG_STRING ) + { + rightUpgrade = ComputerCraft.getTurtleUpgrade( nbttagcompound.getString( "rightUpgrade" ) ); + } + else + { + rightUpgrade = ComputerCraft.getTurtleUpgrade( nbttagcompound.getShort( "rightUpgrade" ) ); + } + } + } + setUpgrade( TurtleSide.Left, leftUpgrade ); + setUpgrade( TurtleSide.Right, rightUpgrade ); + + // NBT + m_upgradeNBTData.clear(); + if( nbttagcompound.hasKey( "leftUpgradeNBT" ) ) + { + m_upgradeNBTData.put( TurtleSide.Left, (NBTTagCompound) nbttagcompound.getCompoundTag( "leftUpgradeNBT" ).copy() ); + } + if( nbttagcompound.hasKey( "rightUpgradeNBT" ) ) + { + m_upgradeNBTData.put( TurtleSide.Right, (NBTTagCompound) nbttagcompound.getCompoundTag( "rightUpgradeNBT" ).copy() ); + } + } + + public void writeToNBT( NBTTagCompound nbttagcompound ) + { + // Write state + nbttagcompound.setInteger( "dir", m_direction.getIndex() ); + nbttagcompound.setInteger( "selectedSlot", m_selectedSlot ); + nbttagcompound.setInteger( "fuelLevel", m_fuelLevel ); + + // Write upgrades + String leftUpgradeID = getUpgradeID( getUpgrade( TurtleSide.Left ) ); + if( leftUpgradeID != null ) + { + nbttagcompound.setString( "leftUpgrade", leftUpgradeID ); + } + String rightUpgradeID = getUpgradeID( getUpgrade( TurtleSide.Right ) ); + if( rightUpgradeID != null ) + { + nbttagcompound.setString( "rightUpgrade", rightUpgradeID ); + } + + // Write colour + if( m_colour != null ) + { + nbttagcompound.setInteger( "colourIndex", m_colour.ordinal() ); + } + + // Write overlay + if( m_overlay != null ) + { + nbttagcompound.setString( "overlay_mod", m_overlay.getResourceDomain() ); + nbttagcompound.setString( "overlay_path", m_overlay.getResourcePath() ); + } + + // Write NBT + if( m_upgradeNBTData.containsKey( TurtleSide.Left ) ) + { + nbttagcompound.setTag( "leftUpgradeNBT", (NBTTagCompound) getUpgradeNBTData( TurtleSide.Left ).copy() ); + } + if( m_upgradeNBTData.containsKey( TurtleSide.Right ) ) + { + nbttagcompound.setTag( "rightUpgradeNBT", (NBTTagCompound) getUpgradeNBTData( TurtleSide.Right ).copy() ); + } + } + + private String getUpgradeID( ITurtleUpgrade upgrade ) + { + if( upgrade != null ) + { + return upgrade.getUpgradeID().toString(); + } + return null; + } + + public void writeDescription( NBTTagCompound nbttagcompound ) + { + // Upgrades + String leftUpgradeID = getUpgradeID( getUpgrade( TurtleSide.Left ) ); + if( leftUpgradeID != null ) + { + nbttagcompound.setString( "leftUpgrade", leftUpgradeID ); + } + String rightUpgradeID = getUpgradeID( getUpgrade( TurtleSide.Right ) ); + if( rightUpgradeID != null ) + { + nbttagcompound.setString( "rightUpgrade", rightUpgradeID ); + } + + // NBT + if( m_upgradeNBTData.containsKey( TurtleSide.Left ) ) + { + nbttagcompound.setTag( "leftUpgradeNBT", (NBTTagCompound) getUpgradeNBTData( TurtleSide.Left ).copy() ); + } + if( m_upgradeNBTData.containsKey( TurtleSide.Right ) ) + { + nbttagcompound.setTag( "rightUpgradeNBT", (NBTTagCompound) getUpgradeNBTData( TurtleSide.Right ).copy() ); + } + + // Colour + if( m_colour != null ) + { + nbttagcompound.setInteger( "colourIndex", m_colour.ordinal() ); + } + + // Overlay + if( m_overlay != null ) + { + nbttagcompound.setString( "overlay_mod", m_overlay.getResourceDomain() ); + nbttagcompound.setString( "overlay_path", m_overlay.getResourcePath() ); + } + + // Animation + if( m_instanceID < 0 ) + { + m_instanceID = assignInstanceID(); + } + nbttagcompound.setInteger( "brainInstanceID", m_instanceID ); + nbttagcompound.setInteger( "animation", m_animation.ordinal() ); + nbttagcompound.setInteger( "direction", m_direction.getIndex() ); + nbttagcompound.setInteger( "fuelLevel", m_fuelLevel ); + } + + public void readDescription( NBTTagCompound nbttagcompound ) + { + // Upgrades + if( nbttagcompound.hasKey( "leftUpgrade" ) ) + { + setUpgrade( TurtleSide.Left, ComputerCraft.getTurtleUpgrade( nbttagcompound.getString( "leftUpgrade" ) ) ); + } + else + { + setUpgrade( TurtleSide.Left, null ); + } + if( nbttagcompound.hasKey( "rightUpgrade" ) ) + { + setUpgrade( TurtleSide.Right, ComputerCraft.getTurtleUpgrade( nbttagcompound.getString( "rightUpgrade" ) ) ); + } + else + { + setUpgrade( TurtleSide.Right, null ); + } + + // NBT + m_upgradeNBTData.clear(); + if( nbttagcompound.hasKey( "leftUpgradeNBT" ) ) + { + m_upgradeNBTData.put( TurtleSide.Left, (NBTTagCompound) nbttagcompound.getCompoundTag( "leftUpgradeNBT" ).copy() ); + } + if( nbttagcompound.hasKey( "rightUpgradeNBT" ) ) + { + m_upgradeNBTData.put( TurtleSide.Right, (NBTTagCompound)nbttagcompound.getCompoundTag( "rightUpgradeNBT" ).copy() ); + } + + // Colour + if( nbttagcompound.hasKey( "colourIndex" ) ) + { + m_colour = Colour.values()[ nbttagcompound.getInteger( "colourIndex" ) ]; + } + else + { + m_colour = null; + } + + // Overlay + if( nbttagcompound.hasKey( "overlay_mod" ) && nbttagcompound.hasKey( "overlay_path" ) ) + { + String overlay_mod = nbttagcompound.getString( "overlay_mod" ); + String overlay_path = nbttagcompound.getString( "overlay_path" ); + m_overlay = new ResourceLocation( overlay_mod, overlay_path ); + } + else + { + m_overlay = null; + } + + // Animation + m_instanceID = nbttagcompound.getInteger( "brainInstanceID" ); + setClientBrain( m_instanceID, this ); + + TurtleAnimation anim = TurtleAnimation.values()[ nbttagcompound.getInteger( "animation" ) ]; + if( anim != m_animation && + anim != TurtleAnimation.Wait && + anim != TurtleAnimation.ShortWait && + anim != TurtleAnimation.None ) + { + m_animation = TurtleAnimation.values()[ nbttagcompound.getInteger( "animation" ) ]; + m_animationProgress = 0; + m_lastAnimationProgress = 0; + } + + m_direction = EnumFacing.getFront( nbttagcompound.getInteger( "direction" ) ); + m_fuelLevel = nbttagcompound.getInteger( "fuelLevel" ); + } + + @Override + public World getWorld() + { + return m_owner.getWorld(); + } + + @Override + public BlockPos getPosition() + { + return m_owner.getPos(); + } + + @Override + public boolean teleportTo( World world, BlockPos pos ) + { + if( world.isRemote || getWorld().isRemote ) + { + throw new UnsupportedOperationException(); + } + + // Cache info about the old turtle (so we don't access this after we delete ourselves) + World oldWorld = getWorld(); + BlockPos oldPos = m_owner.getPos(); + Block oldBlock = m_owner.getBlock(); + + if( oldWorld == world && oldPos.equals( pos ) ) + { + // Teleporting to the current position is a no-op + return true; + } + + // Create a new turtle + if( world.isBlockLoaded( pos ) && world.setBlockState( pos, oldBlock.getDefaultState(), 3 ) ) + { + Block block = world.getBlockState( pos ).getBlock(); + if( block == oldBlock ) + { + TileEntity newTile = world.getTileEntity( pos ); + if( newTile != null && newTile instanceof TileTurtle ) + { + // Copy the old turtle state into the new turtle + TileTurtle newTurtle = (TileTurtle)newTile; + newTurtle.setWorldObj( world ); + newTurtle.setPos( pos ); + newTurtle.transferStateFrom( m_owner ); + newTurtle.createServerComputer().setWorld( world ); + newTurtle.createServerComputer().setPosition( pos ); + + // Remove the old turtle + oldWorld.setBlockToAir( oldPos ); + + // Make sure everybody knows about it + newTurtle.updateInput(); + newTurtle.updateOutput(); + return true; + } + } + + // Something went wrong, remove the newly created turtle + world.setBlockToAir( pos ); + } + + return false; + } + + @Override + public Vec3 getVisualPosition( float f ) + { + Vec3 offset = getRenderOffset( f ); + BlockPos pos = m_owner.getPos(); + return new Vec3( + pos.getX() + 0.5 + offset.xCoord, + pos.getY() + 0.5 + offset.yCoord, + pos.getZ() + 0.5 + offset.zCoord + ); + } + + @Override + public float getVisualYaw( float f ) + { + float forward = DirectionUtil.toYawAngle( getDirection() ); + float yaw = forward; + switch( m_animation ) + { + case TurnLeft: + { + yaw += 90.0f * (1.0f - getAnimationFraction( f )); + if( yaw >= 360.0f ) + { + yaw -= 360.0f; + } + break; + } + case TurnRight: + { + yaw += -90.0f * (1.0f - getAnimationFraction( f )); + if( yaw < 0.0f ) + { + yaw += 360.0f; + } + break; + } + } + return yaw; + } + + @Override + public EnumFacing getDirection() + { + return m_direction; + } + + @Override + public void setDirection( EnumFacing dir ) + { + if( dir.getAxis() == EnumFacing.Axis.Y ) + { + dir = EnumFacing.NORTH; + } + m_direction = dir; + m_owner.updateOutput(); + m_owner.updateInput(); + m_owner.onTileEntityChange(); + } + + @Override + public int getSelectedSlot() + { + return m_selectedSlot; + } + + @Override + public void setSelectedSlot( int slot ) + { + if( getWorld().isRemote ) + { + throw new UnsupportedOperationException(); + } + if( slot >= 0 && slot < m_owner.getSizeInventory() ) + { + m_selectedSlot = slot; + m_owner.onTileEntityChange(); + } + } + + @Override + public IInventory getInventory() + { + return m_owner; + } + + @Override + public boolean isFuelNeeded() + { + return ComputerCraft.turtlesNeedFuel; + } + + @Override + public int getFuelLevel() + { + return Math.min( m_fuelLevel, getFuelLimit() ); + } + + @Override + public void setFuelLevel( int level ) + { + m_fuelLevel = Math.min( level, getFuelLimit() ); + m_owner.onTileEntityChange(); + } + + @Override + public int getFuelLimit() + { + if( m_owner.getFamily() == ComputerFamily.Advanced ) + { + return ComputerCraft.advancedTurtleFuelLimit; + } + else + { + return ComputerCraft.turtleFuelLimit; + } + } + + @Override + public boolean consumeFuel( int fuel ) + { + if( getWorld().isRemote ) + { + throw new UnsupportedOperationException(); + } + if( !isFuelNeeded() ) + { + return true; + } + + int consumption = Math.max( fuel, 0 ); + if( getFuelLevel() >= consumption ) + { + setFuelLevel( getFuelLevel() - consumption ); + return true; + } + return false; + } + + @Override + public void addFuel( int fuel ) + { + if( getWorld().isRemote ) + { + throw new UnsupportedOperationException(); + } + int addition = Math.max( fuel, 0 ); + setFuelLevel( getFuelLevel() + addition ); + } + + private int issueCommand( ITurtleCommand command ) + { + m_commandQueue.offer( new TurtleCommandQueueEntry( ++m_commandsIssued, command ) ); + return m_commandsIssued; + } + + @Override + public Object[] executeCommand( ILuaContext context, ITurtleCommand command ) throws LuaException, InterruptedException + { + if( getWorld().isRemote ) + { + throw new UnsupportedOperationException(); + } + + // Issue command + int commandID = issueCommand( command ); + + // Wait for response + while( true ) + { + Object[] response = context.pullEvent( "turtle_response" ); + if( response.length >= 3 && response[ 1 ] instanceof Number && response[ 2 ] instanceof Boolean ) + { + if( ( (Number) response[ 1 ] ).intValue() == commandID ) + { + Object[] returnValues = new Object[ response.length - 2 ]; + for( int i = 0; i < returnValues.length; ++i ) + { + returnValues[ i ] = response[ i + 2 ]; + } + return returnValues; + } + } + } + } + + @Override + public void playAnimation( TurtleAnimation animation ) + { + if( getWorld().isRemote ) + { + throw new UnsupportedOperationException(); + } + m_animation = animation; + if( m_animation == TurtleAnimation.ShortWait ) + { + m_animationProgress = ANIM_DURATION / 2; + m_lastAnimationProgress = ANIM_DURATION / 2; + } + else + { + m_animationProgress = 0; + m_lastAnimationProgress = 0; + } + m_owner.updateBlock(); + } + + @Override + public int getDyeColour() + { + return (m_colour != null) ? m_colour.ordinal() : -1; + } + + public ResourceLocation getOverlay() + { + return m_overlay; + } + + public void setOverlay( ResourceLocation overlay ) + { + if( !Objects.equal(m_overlay, overlay) ) + { + m_overlay = overlay; + m_owner.updateBlock(); + } + } + + @Override + public void setDyeColour( int dyeColour ) + { + Colour newColour = null; + if( dyeColour >= 0 && dyeColour < 16 ) + { + newColour = Colour.values()[ dyeColour ]; + } + if( m_colour != newColour ) + { + m_colour = newColour; + m_owner.updateBlock(); + } + } + + @Override + public ITurtleUpgrade getUpgrade( TurtleSide side ) + { + if( m_upgrades.containsKey( side ) ) + { + return m_upgrades.get( side ); + } + return null; + } + + @Override + public void setUpgrade( TurtleSide side, ITurtleUpgrade upgrade ) + { + // Remove old upgrade + if( m_upgrades.containsKey( side ) ) + { + if( m_upgrades.get( side ) == upgrade ) + { + return; + } + m_upgrades.remove( side ); + } + else + { + if( upgrade == null ) + { + return; + } + } + if( m_upgradeNBTData.containsKey( side ) ) + { + m_upgradeNBTData.remove( side ); + } + + // Set new upgrade + if( upgrade != null ) + { + m_upgrades.put( side, upgrade ); + } + + // Notify clients and create peripherals + if( m_owner.getWorld() != null ) + { + updatePeripherals( m_owner.createServerComputer() ); + m_owner.updateBlock(); + } + } + + @Override + public IPeripheral getPeripheral( TurtleSide side ) + { + if( m_peripherals.containsKey( side ) ) + { + return m_peripherals.get( side ); + } + return null; + } + + @Override + public NBTTagCompound getUpgradeNBTData( TurtleSide side ) + { + if( !m_upgradeNBTData.containsKey( side ) ) + { + m_upgradeNBTData.put( side, new NBTTagCompound() ); + } + return m_upgradeNBTData.get( side ); + } + + @Override + public void updateUpgradeNBTData( TurtleSide side ) + { + m_owner.updateBlock(); + } + + public boolean saveBlockChange( BlockPos coordinates, IBlockState previousState ) + { + // Overriden by CCEdu + return false; + } + + public Vec3 getRenderOffset( float f ) + { + switch( m_animation ) + { + case MoveForward: + case MoveBack: + case MoveUp: + case MoveDown: + { + // Get direction + EnumFacing dir; + switch( m_animation ) + { + case MoveForward: + default: + { + dir = getDirection(); + break; + } + case MoveBack: + { + dir = getDirection().getOpposite(); + break; + } + case MoveUp: + { + dir = EnumFacing.UP; + break; + } + case MoveDown: + { + dir = EnumFacing.DOWN; + break; + } + } + + double distance = -1.0 + (double)getAnimationFraction( f ); + return new Vec3( + distance * (double)dir.getFrontOffsetX(), + distance * (double)dir.getFrontOffsetY(), + distance * (double)dir.getFrontOffsetZ() + ); + } + default: + { + return new Vec3( 0.0, 0.0, 0.0 ); + } + } + } + + public float getToolRenderAngle( TurtleSide side, float f ) + { + if( (side == TurtleSide.Left && m_animation == TurtleAnimation.SwingLeftTool) || + (side == TurtleSide.Right && m_animation == TurtleAnimation.SwingRightTool) ) + { + return 45.0f * (float)Math.sin( (double) getAnimationFraction( f ) * Math.PI ); + } + return 0.0f; + } + + private int toDirection( TurtleSide side ) + { + switch( side ) + { + case Left: + { + return 5; + } + case Right: + default: + { + return 4; + } + } + } + + public void updatePeripherals( ServerComputer serverComputer ) + { + if( serverComputer == null ) + { + // Nothing to do + return; + } + + // Update peripherals + for( TurtleSide side : TurtleSide.values() ) + { + ITurtleUpgrade upgrade = getUpgrade( side ); + IPeripheral peripheral = null; + if( upgrade != null && upgrade.getType() == TurtleUpgradeType.Peripheral ) + { + peripheral = upgrade.createPeripheral( this, side ); + } + + int dir = toDirection( side ); + if( peripheral != null ) + { + if( !m_peripherals.containsKey( side ) ) + { + serverComputer.setPeripheral( dir, peripheral ); + serverComputer.setRedstoneInput( dir, 0 ); + serverComputer.setBundledRedstoneInput( dir, 0 ); + m_peripherals.put( side, peripheral ); + } + else if( !m_peripherals.get( side ).equals( peripheral ) ) + { + serverComputer.setPeripheral( dir, peripheral ); + serverComputer.setRedstoneInput( dir, 0 ); + serverComputer.setBundledRedstoneInput( dir, 0 ); + m_peripherals.remove( side ); + m_peripherals.put( side, peripheral ); + } + } + else if( m_peripherals.containsKey( side ) ) + { + serverComputer.setPeripheral( dir, null ); + m_peripherals.remove( side ); + } + } + } + + private void updateCommands() + { + if( m_animation == TurtleAnimation.None ) + { + // Pull a new command + TurtleCommandQueueEntry nextCommand = null; + if( m_commandQueue.peek() != null ) + { + nextCommand = m_commandQueue.remove(); + } + + if( nextCommand != null ) + { + // Execute the command + TurtleCommandResult result = nextCommand.command.execute( this ); + + // Dispatch the callback + int callbackID = nextCommand.callbackID; + if( callbackID >= 0 ) + { + if( result != null && result.isSuccess() ) + { + IComputer computer = m_owner.getComputer(); + if( computer != null ) + { + Object[] results = result.getResults(); + if( results != null ) + { + Object[] arguments = new Object[ results.length + 2 ]; + arguments[0] = callbackID; + arguments[1] = true; + for( int i=0; i= ANIM_DURATION ) + { + m_animation = TurtleAnimation.None; + m_animationProgress = 0; + m_lastAnimationProgress = 0; + } + } + } + + private float getAnimationFraction( float f ) + { + float next = (float)m_animationProgress / ANIM_DURATION; + float previous = (float)m_lastAnimationProgress / ANIM_DURATION; + return previous + (next - previous) * f; + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCheckRedstoneCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCheckRedstoneCommand.java new file mode 100644 index 0000000000..94e5f9e1b9 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCheckRedstoneCommand.java @@ -0,0 +1,59 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.core; + +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.api.turtle.ITurtleCommand; +import dan200.computercraft.api.turtle.TurtleCommandResult; +import dan200.computercraft.core.apis.IAPIEnvironment; + +public class TurtleCheckRedstoneCommand implements ITurtleCommand +{ + private final IAPIEnvironment m_environment; + private final InteractDirection m_direction; + + public TurtleCheckRedstoneCommand( IAPIEnvironment environment, InteractDirection direction ) + { + m_environment = environment; + m_direction = direction; + } + + @Override + public TurtleCommandResult execute( ITurtleAccess turtle ) + { + // Do the checking + int redstoneSide; + switch( m_direction ) + { + case Forward: + default: + { + redstoneSide = 3; + break; + } + case Up: + { + redstoneSide = 1; + break; + } + case Down: + { + redstoneSide = 2; + break; + } + } + int power = m_environment.getInput( redstoneSide ); + if( power > 0 ) + { + return TurtleCommandResult.success(); + } + else + { + return TurtleCommandResult.failure(); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCommandQueueEntry.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCommandQueueEntry.java new file mode 100644 index 0000000000..a250813081 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCommandQueueEntry.java @@ -0,0 +1,21 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.core; + +import dan200.computercraft.api.turtle.ITurtleCommand; + +public class TurtleCommandQueueEntry +{ + public final int callbackID; + public final ITurtleCommand command; + + public TurtleCommandQueueEntry( int callbackID, ITurtleCommand command ) + { + this.callbackID = callbackID; + this.command = command; + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareCommand.java new file mode 100644 index 0000000000..0c00a6a643 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareCommand.java @@ -0,0 +1,141 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.core; + +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.api.turtle.ITurtleCommand; +import dan200.computercraft.api.turtle.TurtleCommandResult; +import dan200.computercraft.shared.util.WorldUtil; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.ReflectionHelper; + +import java.lang.reflect.Method; +import java.util.Iterator; + +public class TurtleCompareCommand implements ITurtleCommand +{ + private final InteractDirection m_direction; + + public TurtleCompareCommand( InteractDirection direction ) + { + m_direction = direction; + } + + @Override + public TurtleCommandResult execute( ITurtleAccess turtle ) + { + // Get world direction from direction + EnumFacing direction = m_direction.toWorldDir( turtle ); + + // Get currently selected stack + ItemStack selectedStack = turtle.getInventory().getStackInSlot( turtle.getSelectedSlot() ); + + // Get stack representing thing in front + World world = turtle.getWorld(); + BlockPos oldPosition = turtle.getPosition(); + BlockPos newPosition = oldPosition.offset( direction ); + + ItemStack lookAtStack = null; + if( WorldUtil.isBlockInWorld( world, newPosition ) ) + { + if( !world.isAirBlock( newPosition ) ) + { + Block lookAtBlock = world.getBlockState( newPosition ).getBlock(); + if( lookAtBlock != null && !lookAtBlock.isAir( world, newPosition ) ) + { + // Try createStackedBlock first + IBlockState lookAtState = world.getBlockState( newPosition ); + if( !lookAtBlock.hasTileEntity( lookAtState ) ) + { + try + { + Method method = ReflectionHelper.findMethod( + Block.class, lookAtBlock, + new String[]{ "func_149644_j", "j", "createStackedBlock" }, + IBlockState.class + ); + if( method != null ) + { + lookAtStack = (ItemStack)method.invoke( lookAtBlock, lookAtState ); + } + } + catch( Exception e ) + { + // ??? + } + } + + // See if the block drops anything with the same ID as itself + // (try 5 times to try and beat random number generators) + for( int i=0; (i<5) && (lookAtStack == null); ++i ) + { + java.util.List drops = lookAtBlock.getDrops( world, newPosition, lookAtState, 0 ); + if( drops != null && drops.size() > 0 ) + { + Iterator it = drops.iterator(); + while( it.hasNext() ) + { + ItemStack drop = it.next(); + if( drop.getItem() == Item.getItemFromBlock( lookAtBlock ) ) + { + lookAtStack = drop; + break; + } + } + } + } + + // Last resort: roll our own (which will probably be wrong) + if( lookAtStack == null ) + { + Item item = Item.getItemFromBlock( lookAtBlock ); + if( item != null && item.getHasSubtypes() ) + { + lookAtStack = new ItemStack( item, 1, lookAtBlock.getMetaFromState( lookAtState ) ); + } + else + { + lookAtStack = new ItemStack( item, 1, 0 ); + } + } + } + } + } + + // Compare them + if( selectedStack == null && lookAtStack == null ) + { + return TurtleCommandResult.success(); + } + else if( selectedStack != null && lookAtStack != null ) + { + if( selectedStack.getItem() == lookAtStack.getItem() ) + { + if( !selectedStack.getHasSubtypes() ) + { + return TurtleCommandResult.success(); + } + else if( selectedStack.getItemDamage() == lookAtStack.getItemDamage() ) + { + return TurtleCommandResult.success(); + } + else if( selectedStack.getUnlocalizedName().equals( lookAtStack.getUnlocalizedName() ) ) + { + return TurtleCommandResult.success(); + } + } + } + + return TurtleCommandResult.failure(); + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareToCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareToCommand.java new file mode 100644 index 0000000000..3c85c3607c --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareToCommand.java @@ -0,0 +1,38 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.core; + +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.api.turtle.ITurtleCommand; +import dan200.computercraft.api.turtle.TurtleCommandResult; +import dan200.computercraft.shared.util.InventoryUtil; +import net.minecraft.item.ItemStack; + +public class TurtleCompareToCommand implements ITurtleCommand +{ + private final int m_slot; + + public TurtleCompareToCommand( int slot ) + { + m_slot = slot; + } + + @Override + public TurtleCommandResult execute( ITurtleAccess turtle ) + { + ItemStack selectedStack = turtle.getInventory().getStackInSlot( turtle.getSelectedSlot() ); + ItemStack stack = turtle.getInventory().getStackInSlot( m_slot ); + if( InventoryUtil.areItemsStackable( selectedStack, stack ) ) + { + return TurtleCommandResult.success(); + } + else + { + return TurtleCommandResult.failure(); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCraftCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCraftCommand.java new file mode 100644 index 0000000000..aa3cd8c521 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCraftCommand.java @@ -0,0 +1,64 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.core; + +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.api.turtle.ITurtleCommand; +import dan200.computercraft.api.turtle.TurtleAnimation; +import dan200.computercraft.api.turtle.TurtleCommandResult; +import dan200.computercraft.shared.turtle.upgrades.TurtleInventoryCrafting; +import dan200.computercraft.shared.util.InventoryUtil; +import dan200.computercraft.shared.util.WorldUtil; +import net.minecraft.item.ItemStack; +import net.minecraft.util.BlockPos; + +import java.util.ArrayList; + +public class TurtleCraftCommand implements ITurtleCommand +{ + private final int m_limit; + + public TurtleCraftCommand( int limit ) + { + m_limit = limit; + } + + @Override + public TurtleCommandResult execute( ITurtleAccess turtle ) + { + // Craft the item + TurtleInventoryCrafting crafting = new TurtleInventoryCrafting( turtle ); + ArrayList results = crafting.doCrafting( turtle.getWorld(), m_limit ); + if( results != null ) + { + // Store the results + for( int i=0; i 0 ) + { + // Animate + turtle.playAnimation( TurtleAnimation.Wait ); + } + + // Succeed + return TurtleCommandResult.success(); + } + + // Fail + return TurtleCommandResult.failure( "No matching recipes" ); + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDetectCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDetectCommand.java new file mode 100644 index 0000000000..2ac7d260da --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDetectCommand.java @@ -0,0 +1,48 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.core; + +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.api.turtle.ITurtleCommand; +import dan200.computercraft.api.turtle.TurtleCommandResult; +import dan200.computercraft.shared.util.WorldUtil; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +public class TurtleDetectCommand implements ITurtleCommand +{ + private final InteractDirection m_direction; + + public TurtleDetectCommand( InteractDirection direction ) + { + m_direction = direction; + } + + @Override + public TurtleCommandResult execute( ITurtleAccess turtle ) + { + // Get world direction from direction + EnumFacing direction = m_direction.toWorldDir( turtle ); + + // Check if thing in front is air or not + World world = turtle.getWorld(); + BlockPos oldPosition = turtle.getPosition(); + BlockPos newPosition = oldPosition.offset( direction ); + + if( WorldUtil.isBlockInWorld( world, newPosition ) ) + { + if( !WorldUtil.isLiquidBlock( world, newPosition ) && + !world.isAirBlock( newPosition ) ) + { + return TurtleCommandResult.success(); + } + } + + return TurtleCommandResult.failure(); + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDigCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDigCommand.java new file mode 100644 index 0000000000..d781ad77c7 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDigCommand.java @@ -0,0 +1,19 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.core; + +import com.google.common.base.Optional; +import dan200.computercraft.api.turtle.TurtleSide; +import dan200.computercraft.api.turtle.TurtleVerb; + +public class TurtleDigCommand extends TurtleToolCommand +{ + public TurtleDigCommand( InteractDirection direction, Optional side ) + { + super( TurtleVerb.Dig, direction, side ); + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java new file mode 100644 index 0000000000..e240baa6c1 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java @@ -0,0 +1,89 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.core; + +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.api.turtle.ITurtleCommand; +import dan200.computercraft.api.turtle.TurtleAnimation; +import dan200.computercraft.api.turtle.TurtleCommandResult; +import dan200.computercraft.shared.util.InventoryUtil; +import dan200.computercraft.shared.util.WorldUtil; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +public class TurtleDropCommand implements ITurtleCommand +{ + private final InteractDirection m_direction; + private final int m_quantity; + + public TurtleDropCommand( InteractDirection direction, int quantity ) + { + m_direction = direction; + m_quantity = quantity; + } + + @Override + public TurtleCommandResult execute( ITurtleAccess turtle ) + { + // Dropping nothing is easy + if( m_quantity == 0 ) + { + turtle.playAnimation( TurtleAnimation.Wait ); + return TurtleCommandResult.success(); + } + + // Get world direction from direction + EnumFacing direction = m_direction.toWorldDir( turtle ); + + // Get things to drop + ItemStack stack = InventoryUtil.takeItems( m_quantity, turtle.getInventory(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); + if( stack == null ) + { + return TurtleCommandResult.failure( "No items to drop" ); + } + + // Get inventory for thing in front + World world = turtle.getWorld(); + BlockPos oldPosition = turtle.getPosition(); + BlockPos newPosition = oldPosition.offset( direction ); + EnumFacing side = direction.getOpposite(); + + IInventory inventory = InventoryUtil.getInventory( world, newPosition, side ); + if( inventory != null ) + { + // Drop the item into the inventory + ItemStack remainder = InventoryUtil.storeItems( stack, inventory, side ); + if( remainder != null ) + { + // Put the remainder back in the turtle + InventoryUtil.storeItems( remainder, turtle.getInventory(), 0, turtle.getInventory().getSizeInventory(), turtle.getSelectedSlot() ); + } + + // Return true if we stored anything + if( remainder != stack ) + { + turtle.playAnimation( TurtleAnimation.Wait ); + return TurtleCommandResult.success(); + } + else + { + return TurtleCommandResult.failure( "No space for items" ); + } + } + else + { + // Drop the item into the world + WorldUtil.dropItemStack( stack, world, oldPosition, direction ); + world.playSoundEffect( newPosition.getX() + 0.5, newPosition.getY() + 0.5, newPosition.getZ() + 0.5, "random.pop", 0.2f, ((world.rand.nextFloat() - world.rand.nextFloat()) * 0.7f + 1.0f) * 2.0f ); + turtle.playAnimation( TurtleAnimation.Wait ); + return TurtleCommandResult.success(); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java new file mode 100644 index 0000000000..f479ea7eaa --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java @@ -0,0 +1,92 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.core; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.turtle.*; +import dan200.computercraft.shared.proxy.CCTurtleProxyCommon; +import dan200.computercraft.shared.util.InventoryUtil; +import dan200.computercraft.shared.util.WorldUtil; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.util.BlockPos; + +public class TurtleEquipCommand implements ITurtleCommand +{ + private final TurtleSide m_side; + + public TurtleEquipCommand( TurtleSide side ) + { + m_side = side; + } + + @Override + public TurtleCommandResult execute( ITurtleAccess turtle ) + { + // Determine the upgrade to equipLeft + ITurtleUpgrade newUpgrade; + ItemStack newUpgradeStack; + IInventory inventory = turtle.getInventory(); + ItemStack selectedStack = inventory.getStackInSlot( turtle.getSelectedSlot() ); + if( selectedStack != null ) + { + newUpgradeStack = selectedStack.copy(); + newUpgrade = ComputerCraft.getTurtleUpgrade( newUpgradeStack ); + if( newUpgrade == null || !CCTurtleProxyCommon.isUpgradeSuitableForFamily( ((TurtleBrain)turtle).getFamily(), newUpgrade ) ) + { + return TurtleCommandResult.failure( "Not a valid upgrade" ); + } + } + else + { + newUpgradeStack = null; + newUpgrade = null; + } + + // Determine the upgrade to replace + ItemStack oldUpgradeStack; + ITurtleUpgrade oldUpgrade = turtle.getUpgrade( m_side ); + if( oldUpgrade != null ) + { + ItemStack craftingItem = oldUpgrade.getCraftingItem(); + oldUpgradeStack = (craftingItem != null) ? craftingItem.copy() : null; + } + else + { + oldUpgradeStack = null; + } + + // Do the swapping: + if( newUpgradeStack != null ) + { + // Consume new upgrades item + InventoryUtil.takeItems( 1, inventory, turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); + inventory.markDirty(); + } + if( oldUpgradeStack != null ) + { + // Store old upgrades item + ItemStack remainder = InventoryUtil.storeItems( oldUpgradeStack, inventory, 0, inventory.getSizeInventory(), turtle.getSelectedSlot() ); + if( remainder != null ) + { + // If there's no room for the items, drop them + BlockPos position = turtle.getPosition(); + WorldUtil.dropItemStack( remainder, turtle.getWorld(), position, turtle.getDirection() ); + } + inventory.markDirty(); + } + turtle.setUpgrade( m_side, newUpgrade ); + + // Animate + if( newUpgrade != null || oldUpgrade != null ) + { + turtle.playAnimation( TurtleAnimation.Wait ); + } + + return TurtleCommandResult.success(); + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleInspectCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleInspectCommand.java new file mode 100644 index 0000000000..dc129509df --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleInspectCommand.java @@ -0,0 +1,90 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.core; + +import com.google.common.collect.ImmutableMap; +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.api.turtle.ITurtleCommand; +import dan200.computercraft.api.turtle.TurtleCommandResult; +import dan200.computercraft.shared.util.WorldUtil; +import net.minecraft.block.Block; +import net.minecraft.block.properties.IProperty; +import net.minecraft.block.state.IBlockState; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; + +import java.util.HashMap; +import java.util.Map; + +public class TurtleInspectCommand implements ITurtleCommand +{ + private static final boolean FAIL_ON_AIR = true; + private final InteractDirection m_direction; + + public TurtleInspectCommand( InteractDirection direction ) + { + m_direction = direction; + } + + @Override + public TurtleCommandResult execute( ITurtleAccess turtle ) + { + // Get world direction from direction + EnumFacing direction = m_direction.toWorldDir( turtle ); + + // Check if thing in front is air or not + World world = turtle.getWorld(); + BlockPos oldPosition = turtle.getPosition(); + BlockPos newPosition = WorldUtil.moveCoords( oldPosition, direction ); + + if( WorldUtil.isBlockInWorld( world, newPosition ) ) + { + if( !FAIL_ON_AIR || !world.isAirBlock( newPosition ) ) + { + IBlockState state = world.getBlockState( newPosition ); + Block block = state.getBlock(); + String name = ((ResourceLocation)Block.blockRegistry.getNameForObject( block )).toString(); + int metadata = block.getMetaFromState( state ); + + Map table = new HashMap(); + table.put( "name", name ); + table.put( "metadata", metadata ); + + Map stateTable = new HashMap(); + for( Object o : block.getActualState( state, world, newPosition ).getProperties().entrySet() ) + { + ImmutableMap.Entry entry = (ImmutableMap.Entry)o; + String propertyName = entry.getKey().getName(); + Object value = entry.getValue(); + if( value instanceof String || value instanceof Number || value instanceof Boolean ) + { + stateTable.put( propertyName, value ); + } + else + { + stateTable.put( propertyName, value.toString() ); + } + } + table.put( "state", stateTable ); + + return TurtleCommandResult.success( new Object[]{ table } ); + } + } + + if( !FAIL_ON_AIR ) + { + Map table = new HashMap(); + table.put( "name", "minecraft:air" ); + table.put( "metadata", 0 ); + table.put( "state", new HashMap() ); + return TurtleCommandResult.success( new Object[]{ table } ); + } + return TurtleCommandResult.failure( "No block to inspect" ); + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleMoveCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleMoveCommand.java new file mode 100644 index 0000000000..b4e1e8a0c5 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleMoveCommand.java @@ -0,0 +1,174 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.core; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.api.turtle.ITurtleCommand; +import dan200.computercraft.api.turtle.TurtleAnimation; +import dan200.computercraft.api.turtle.TurtleCommandResult; +import dan200.computercraft.shared.util.WorldUtil; +import net.minecraft.block.Block; +import net.minecraft.entity.Entity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +import java.util.List; + +public class TurtleMoveCommand implements ITurtleCommand +{ + private final MoveDirection m_direction; + + public TurtleMoveCommand( MoveDirection direction ) + { + m_direction = direction; + } + + @Override + public TurtleCommandResult execute( ITurtleAccess turtle ) + { + // Get world direction from direction + EnumFacing direction = m_direction.toWorldDir( turtle ); + + // Check if we can move + World oldWorld = turtle.getWorld(); + BlockPos oldPosition = turtle.getPosition(); + BlockPos newPosition = WorldUtil.moveCoords( oldPosition, direction ); + + TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer( turtle, oldPosition, direction ); + TurtleCommandResult canEnterResult = canEnter( turtlePlayer, oldWorld, newPosition ); + if( !canEnterResult.isSuccess() ) + { + return canEnterResult; + } + + // Check existing block is air or replaceable + Block block = oldWorld.getBlockState( newPosition ).getBlock(); + if( block != null && + !oldWorld.isAirBlock( newPosition ) && + !WorldUtil.isLiquidBlock( oldWorld, newPosition ) && + !block.isReplaceable( oldWorld, newPosition ) ) + { + return TurtleCommandResult.failure( "Movement obstructed" ); + } + + // Check there isn't anything in the way + AxisAlignedBB aabb = ((TurtleBrain)turtle).getOwner().getBounds(); + aabb = aabb.offset( + newPosition.getX(), + newPosition.getY(), + newPosition.getZ() + ); + if( !oldWorld.checkNoEntityCollision( aabb ) ) + { + if( ComputerCraft.turtlesCanPush && m_direction != MoveDirection.Up && m_direction != MoveDirection.Down ) + { + // Check there is space for all the pushable entities to be pushed + List list = oldWorld.getEntitiesWithinAABBExcludingEntity( (Entity)null, aabb ); + for( int i=0; i world.getHeight() - 1 ) + { + return TurtleCommandResult.failure( "Too high to move" ); + } + if( ComputerCraft.turtlesObeyBlockProtection ) + { + // Check spawn protection + if( !ComputerCraft.isBlockEnterable( world, position, turtlePlayer ) ) + { + return TurtleCommandResult.failure( "Cannot enter protected area" ); + } + } + if( !world.isBlockLoaded( position ) ) + { + return TurtleCommandResult.failure( "Cannot leave loaded world" ); + } + return TurtleCommandResult.success(); + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java new file mode 100644 index 0000000000..e87a8bc985 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java @@ -0,0 +1,422 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.core; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.api.turtle.ITurtleCommand; +import dan200.computercraft.api.turtle.TurtleAnimation; +import dan200.computercraft.api.turtle.TurtleCommandResult; +import dan200.computercraft.shared.util.DirectionUtil; +import dan200.computercraft.shared.util.IEntityDropConsumer; +import dan200.computercraft.shared.util.InventoryUtil; +import dan200.computercraft.shared.util.WorldUtil; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.*; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntitySign; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import org.apache.commons.lang3.tuple.Pair; + +public class TurtlePlaceCommand implements ITurtleCommand +{ + private final InteractDirection m_direction; + private final Object[] m_extraArguments; + + public TurtlePlaceCommand( InteractDirection direction, Object[] arguments ) + { + m_direction = direction; + m_extraArguments = arguments; + } + + @Override + public TurtleCommandResult execute( ITurtleAccess turtle ) + { + // Get thing to place + ItemStack stack = turtle.getInventory().getStackInSlot( turtle.getSelectedSlot() ); + if( stack == null ) + { + return TurtleCommandResult.failure( "No items to place" ); + } + + // Remember old block + EnumFacing direction = m_direction.toWorldDir( turtle ); + World world = turtle.getWorld(); + BlockPos coordinates = WorldUtil.moveCoords( turtle.getPosition(), direction ); + + IBlockState previousState; + if( WorldUtil.isBlockInWorld( world, coordinates ) ) + { + previousState = world.getBlockState( coordinates ); + } + else + { + previousState = null; + } + + // Do the deploying + String[] errorMessage = new String[1]; + ItemStack remainder = deploy( stack, turtle, direction, m_extraArguments, errorMessage ); + if( remainder != stack ) + { + // Put the remaining items back + turtle.getInventory().setInventorySlotContents( turtle.getSelectedSlot(), remainder ); + turtle.getInventory().markDirty(); + + // Remember the old block + if( turtle instanceof TurtleBrain && previousState != null ) + { + TurtleBrain brain = (TurtleBrain)turtle; + brain.saveBlockChange( coordinates, previousState ); + } + + // Animate and return success + turtle.playAnimation( TurtleAnimation.Wait ); + return TurtleCommandResult.success(); + } + else + { + if( errorMessage[0] != null ) + { + return TurtleCommandResult.failure( errorMessage[0] ); + } + else if( stack.getItem() instanceof ItemBlock ) + { + return TurtleCommandResult.failure( "Cannot place block here" ); + } + else + { + return TurtleCommandResult.failure( "Cannot place item here" ); + } + } + } + + public static ItemStack deploy( ItemStack stack, ITurtleAccess turtle, EnumFacing direction, Object[] extraArguments, String[] o_errorMessage ) + { + // Create a fake player, and orient it appropriately + BlockPos playerPosition = WorldUtil.moveCoords( turtle.getPosition(), direction ); + TurtlePlayer turtlePlayer = createPlayer( turtle, playerPosition, direction ); + + // Deploy on an entity + ItemStack remainder = deployOnEntity( stack, turtle, turtlePlayer, direction, extraArguments, o_errorMessage ); + if( remainder != stack ) + { + return remainder; + } + + // Deploy on the block immediately in front + BlockPos position = turtle.getPosition(); + BlockPos newPosition = WorldUtil.moveCoords( position, direction ); + remainder = deployOnBlock( stack, turtle, turtlePlayer, newPosition, direction.getOpposite(), extraArguments, true, o_errorMessage ); + if( remainder != stack ) + { + return remainder; + } + + // Deploy on the block one block away + remainder = deployOnBlock( stack, turtle, turtlePlayer, WorldUtil.moveCoords( newPosition, direction ), direction.getOpposite(), extraArguments, false, o_errorMessage ); + if( remainder != stack ) + { + return remainder; + } + + if( direction.getAxis() != EnumFacing.Axis.Y ) + { + // Deploy down on the block in front + remainder = deployOnBlock( stack, turtle, turtlePlayer, newPosition.down(), EnumFacing.UP, extraArguments, false, o_errorMessage ); + if( remainder != stack ) + { + return remainder; + } + } + + // Deploy back onto the turtle + remainder = deployOnBlock( stack, turtle, turtlePlayer, position, direction, extraArguments, false, o_errorMessage ); + if( remainder != stack ) + { + return remainder; + } + + // If nothing worked, return the original stack unchanged + return stack; + } + + public static TurtlePlayer createPlayer( ITurtleAccess turtle, BlockPos position, EnumFacing direction ) + { + TurtlePlayer turtlePlayer = new TurtlePlayer( (WorldServer)turtle.getWorld() ); + orientPlayer( turtle, turtlePlayer, position, direction ); + return turtlePlayer; + } + + public static void orientPlayer( ITurtleAccess turtle, TurtlePlayer turtlePlayer, BlockPos position, EnumFacing direction ) + { + turtlePlayer.posX = position.getX() + 0.5; + turtlePlayer.posY = position.getY() + 0.5; + turtlePlayer.posZ = position.getZ() + 0.5; + + // Stop intersection with the turtle itself + if( turtle.getPosition().equals( position ) ) + { + turtlePlayer.posX += 0.48 * direction.getFrontOffsetX(); + turtlePlayer.posY += 0.48 * direction.getFrontOffsetY(); + turtlePlayer.posZ += 0.48 * direction.getFrontOffsetZ(); + } + + if( direction.getAxis() != EnumFacing.Axis.Y ) + { + turtlePlayer.rotationYaw = DirectionUtil.toYawAngle( direction ); + turtlePlayer.rotationPitch = 0.0f; + } + else + { + turtlePlayer.rotationYaw = DirectionUtil.toYawAngle( turtle.getDirection() ); + turtlePlayer.rotationPitch = DirectionUtil.toPitchAngle( direction ); + } + + turtlePlayer.prevPosX = turtlePlayer.posX; + turtlePlayer.prevPosY = turtlePlayer.posY; + turtlePlayer.prevPosZ = turtlePlayer.posZ; + turtlePlayer.prevRotationPitch = turtlePlayer.rotationPitch; + turtlePlayer.prevRotationYaw = turtlePlayer.rotationYaw; + + turtlePlayer.rotationYawHead = turtlePlayer.rotationYaw; + turtlePlayer.prevRotationYawHead = turtlePlayer.rotationYawHead; + } + + private static ItemStack deployOnEntity( ItemStack stack, final ITurtleAccess turtle, TurtlePlayer turtlePlayer, EnumFacing direction, Object[] extraArguments, String[] o_errorMessage ) + { + // See if there is an entity present + final World world = turtle.getWorld(); + final BlockPos position = turtle.getPosition(); + Vec3 turtlePos = new Vec3( turtlePlayer.posX, turtlePlayer.posY, turtlePlayer.posZ ); + Vec3 rayDir = turtlePlayer.getLook( 1.0f ); + Vec3 rayStart = turtlePos; + Pair hit = WorldUtil.rayTraceEntities( world, rayStart, rayDir, 1.5 ); + if( hit == null ) + { + return stack; + } + + // Load up the turtle's inventory + Item item = stack.getItem(); + ItemStack stackCopy = stack.copy(); + turtlePlayer.loadInventory( stackCopy ); + + // Start claiming entity drops + Entity hitEntity = hit.getKey(); + Vec3 hitPos = hit.getValue(); + ComputerCraft.setEntityDropConsumer( hitEntity, new IEntityDropConsumer() + { + @Override + public void consumeDrop( Entity entity, ItemStack drop ) + { + ItemStack remainder = InventoryUtil.storeItems( drop, turtle.getInventory(), 0, turtle.getInventory().getSizeInventory(), turtle.getSelectedSlot() ); + if( remainder != null ) + { + WorldUtil.dropItemStack( remainder, world, position, turtle.getDirection().getOpposite() ); + } + } + } ); + + // Place on the entity + boolean placed = false; + if( hitEntity.interactFirst( turtlePlayer ) ) + { + placed = true; + } + else if( hitEntity instanceof EntityLivingBase ) + { + placed = item.itemInteractionForEntity( stackCopy, turtlePlayer, (EntityLivingBase)hitEntity ); + if( placed ) + { + turtlePlayer.loadInventory( stackCopy ); + } + else if( hitEntity.interactAt( turtlePlayer, hitPos ) ) // interact + { + placed = true; + } + } + + // Stop claiming drops + ComputerCraft.clearEntityDropConsumer( hitEntity ); + + // Put everything we collected into the turtles inventory, then return + ItemStack remainder = turtlePlayer.unloadInventory( turtle ); + if( !placed && (remainder != null && ItemStack.areItemStacksEqual( stack, remainder )) ) + { + return stack; + } + else if( remainder != null && remainder.stackSize > 0 ) + { + return remainder; + } + else + { + return null; + } + } + + private static boolean canDeployOnBlock( ItemStack stack, ITurtleAccess turtle, TurtlePlayer player, BlockPos position, EnumFacing side, boolean allowReplaceable, String[] o_errorMessage ) + { + World world = turtle.getWorld(); + if( WorldUtil.isBlockInWorld( world, position ) && + !world.isAirBlock( position ) && + !(stack.getItem() instanceof ItemBlock && WorldUtil.isLiquidBlock( world, position )) ) + { + Block block = world.getBlockState( position ).getBlock(); + IBlockState state = world.getBlockState( position ); + + boolean replaceable = block.isReplaceable( world, position ); + if( allowReplaceable || !replaceable ) + { + if( ComputerCraft.turtlesObeyBlockProtection ) + { + // Check spawn protection + boolean editable = true; + if( replaceable ) + { + editable = ComputerCraft.isBlockEditable( world, position, player ); + } + else + { + BlockPos shiftedPos = WorldUtil.moveCoords( position, side ); + if( WorldUtil.isBlockInWorld( world, shiftedPos ) ) + { + editable = ComputerCraft.isBlockEditable( world, shiftedPos, player ); + } + } + if( !editable ) + { + if( o_errorMessage != null ) + { + o_errorMessage[0] = "Cannot place in protected area"; + } + return false; + } + } + + // Check the block is solid or liquid + if( block.canCollideCheck( state, true ) ) + { + return true; + } + } + } + return false; + } + + private static ItemStack deployOnBlock( ItemStack stack, ITurtleAccess turtle, TurtlePlayer turtlePlayer, BlockPos position, EnumFacing side, Object[] extraArguments, boolean allowReplace, String[] o_errorMessage ) + { + // Check if there's something suitable to place onto + if( !canDeployOnBlock( stack, turtle, turtlePlayer, position, side, allowReplace, o_errorMessage ) ) + { + return stack; + } + + // Re-orient the fake player + EnumFacing playerDir = side.getOpposite(); + BlockPos playerPosition = WorldUtil.moveCoords( position, side ); + orientPlayer( turtle, turtlePlayer, playerPosition, playerDir ); + + // Calculate where the turtle would hit the block + float hitX = 0.5f + side.getFrontOffsetX() * 0.5f; + float hitY = 0.5f + side.getFrontOffsetY() * 0.5f; + float hitZ = 0.5f + side.getFrontOffsetZ() * 0.5f; + if( Math.abs( hitY - 0.5f ) < 0.01f ) + { + hitY = 0.45f; + } + + // Load up the turtle's inventory + Item item = stack.getItem(); + ItemStack stackCopy = stack.copy(); + turtlePlayer.loadInventory( stackCopy ); + + // Do the deploying (put everything in the players inventory) + boolean placed = false; + if( item.onItemUseFirst( stackCopy, turtlePlayer, turtle.getWorld(), position, side, hitX, hitY, hitZ ) || + item.onItemUse( stackCopy, turtlePlayer, turtle.getWorld(), position, side, hitX, hitY, hitZ ) ) + { + placed = true; + turtlePlayer.loadInventory( stackCopy ); + } + else if( item instanceof ItemBucket || item instanceof ItemBoat || item instanceof ItemLilyPad || item instanceof ItemGlassBottle ) + { + ItemStack result = item.onItemRightClick( stackCopy, turtle.getWorld(), turtlePlayer ); + if( !ItemStack.areItemStacksEqual( stack, result ) ) + { + placed = true; + turtlePlayer.loadInventory( result ); + } + } + + // Set text on signs + if( placed && item instanceof ItemSign ) + { + if( extraArguments != null && extraArguments.length >= 1 && extraArguments[0] instanceof String ) + { + World world = turtle.getWorld(); + TileEntity tile = world.getTileEntity( position ); + if( tile == null ) + { + BlockPos newPosition = WorldUtil.moveCoords( position, side ); + tile = world.getTileEntity( newPosition ); + } + if( tile != null && tile instanceof TileEntitySign ) + { + TileEntitySign signTile = (TileEntitySign) tile; + String s = (String)extraArguments[0]; + String[] split = s.split("\n"); + int firstLine = (split.length <= 2) ? 1 : 0; + for (int i = 0; i < signTile.signText.length; i++) + { + if( i >= firstLine && i < firstLine + split.length ) + { + if( split[ i - firstLine ].length() > 15 ) + { + signTile.signText[ i ] = new ChatComponentText( split[ i - firstLine ].substring( 0, 15 ) ); + } + else + { + signTile.signText[ i ] = new ChatComponentText( split[ i - firstLine ] ); + } + } + else + { + signTile.signText[i] = new ChatComponentText( "" ); + } + } + signTile.markDirty(); + world.markBlockForUpdate( signTile.getPos() ); + } + } + } + + // Put everything we collected into the turtles inventory, then return + ItemStack remainder = turtlePlayer.unloadInventory( turtle ); + if( !placed && (remainder != null && ItemStack.areItemStacksEqual( stack, remainder )) ) + { + return stack; + } + else if( remainder != null && remainder.stackSize > 0 ) + { + return remainder; + } + else + { + return null; + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java new file mode 100644 index 0000000000..a41534f613 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java @@ -0,0 +1,94 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.core; + +import com.mojang.authlib.GameProfile; +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.shared.util.InventoryUtil; +import dan200.computercraft.shared.util.WorldUtil; +import net.minecraft.entity.Entity; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntitySign; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.WorldServer; +import net.minecraftforge.common.util.FakePlayer; + +import java.util.UUID; + +public class TurtlePlayer extends FakePlayer +{ + private final static GameProfile s_profile = new GameProfile( + UUID.fromString( "0d0c4ca0-4ff1-11e4-916c-0800200c9a66" ), + "ComputerCraft" + ); + + public TurtlePlayer( WorldServer world ) + { + super( world, s_profile ); + } + + public void loadInventory( ItemStack currentStack ) + { + // Load up the fake inventory + inventory.currentItem = 0; + inventory.setInventorySlotContents( 0, currentStack ); + } + + public ItemStack unloadInventory( ITurtleAccess turtle ) + { + // Get the item we placed with + ItemStack results = inventory.getStackInSlot( 0 ); + inventory.setInventorySlotContents( 0, null ); + + // Store (or drop) anything else we found + BlockPos dropPosition = turtle.getPosition(); + EnumFacing dropDirection = turtle.getDirection().getOpposite(); + for( int i=0; i 0 ) + { + boolean foundItems = false; + boolean storedItems = false; + for( int i=0; i m_quantity ) + { + storeStack = stack.splitStack( m_quantity ); + leaveStack = stack; + } + else + { + storeStack = stack; + leaveStack = null; + } + ItemStack remainder = InventoryUtil.storeItems( storeStack, turtle.getInventory(), 0, turtle.getInventory().getSizeInventory(), turtle.getSelectedSlot() ); + if( remainder != storeStack ) + { + storedItems = true; + if( remainder == null && leaveStack == null ) + { + entityItem.setDead(); + } + else if( remainder == null ) + { + entityItem.setEntityItemStack( leaveStack ); + } + else if( leaveStack == null ) + { + entityItem.setEntityItemStack( remainder ); + } + else + { + leaveStack.stackSize += remainder.stackSize; + entityItem.setEntityItemStack( leaveStack ); + } + break; + } + } + } + + if( foundItems ) + { + if( storedItems ) + { + // Play fx + world.playSoundEffect( oldPosition.getX() + 0.5, oldPosition.getY() + 0.5, oldPosition.getZ() + 0.5, "random.pop", 0.2f, ((world.rand.nextFloat() - world.rand.nextFloat()) * 0.7f + 1.0f) * 2.0f ); + turtle.playAnimation( TurtleAnimation.Wait ); + return TurtleCommandResult.success(); + } + else + { + return TurtleCommandResult.failure( "No space for items" ); + } + } + } + return TurtleCommandResult.failure( "No items to take" ); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleToolCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleToolCommand.java new file mode 100644 index 0000000000..4469b39396 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleToolCommand.java @@ -0,0 +1,75 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.core; + +import com.google.common.base.Optional; +import dan200.computercraft.api.turtle.*; + +public class TurtleToolCommand implements ITurtleCommand +{ + private final TurtleVerb m_verb; + private final InteractDirection m_direction; + private final Optional m_side; + + public TurtleToolCommand( TurtleVerb verb, InteractDirection direction, Optional side ) + { + m_verb = verb; + m_direction = direction; + m_side = side; + } + + @Override + public TurtleCommandResult execute( ITurtleAccess turtle ) + { + TurtleCommandResult firstFailure = null; + for( TurtleSide side : TurtleSide.values() ) + { + if( !m_side.isPresent() || m_side.get() == side ) + { + ITurtleUpgrade upgrade = turtle.getUpgrade( side ); + if( upgrade != null && upgrade.getType() == TurtleUpgradeType.Tool ) + { + TurtleCommandResult result = upgrade.useTool( turtle, side, m_verb, m_direction.toWorldDir( turtle ) ); + if( result.isSuccess() ) + { + switch( side ) + { + case Left: + { + turtle.playAnimation( TurtleAnimation.SwingLeftTool ); + break; + } + case Right: + { + turtle.playAnimation( TurtleAnimation.SwingRightTool ); + break; + } + default: + { + turtle.playAnimation( TurtleAnimation.Wait ); + break; + } + } + return result; + } + else if( firstFailure == null ) + { + firstFailure = result; + } + } + } + } + if( firstFailure != null ) + { + return firstFailure; + } + else + { + return TurtleCommandResult.failure( "No tool to " + m_verb.toString().toLowerCase() + " with" ); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTransferToCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTransferToCommand.java new file mode 100644 index 0000000000..38b0275f72 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTransferToCommand.java @@ -0,0 +1,57 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.core; + +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.api.turtle.ITurtleCommand; +import dan200.computercraft.api.turtle.TurtleAnimation; +import dan200.computercraft.api.turtle.TurtleCommandResult; +import dan200.computercraft.shared.util.InventoryUtil; +import net.minecraft.item.ItemStack; + +public class TurtleTransferToCommand implements ITurtleCommand +{ + private final int m_slot; + private final int m_quantity; + + public TurtleTransferToCommand( int slot, int limit ) + { + m_slot = slot; + m_quantity = limit; + } + + @Override + public TurtleCommandResult execute( ITurtleAccess turtle ) + { + // Take stack + ItemStack stack = InventoryUtil.takeItems( m_quantity, turtle.getInventory(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); + if( stack == null ) + { + turtle.playAnimation( TurtleAnimation.Wait ); + return TurtleCommandResult.success(); + } + + // Store stack + ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getInventory(), m_slot, 1, m_slot ); + if( remainder != null ) + { + // Put the remainder back + InventoryUtil.storeItems( remainder, turtle.getInventory(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); + } + + // Return true if we moved anything + if( remainder != stack ) + { + turtle.playAnimation( TurtleAnimation.Wait ); + return TurtleCommandResult.success(); + } + else + { + return TurtleCommandResult.failure( "No space for items" ); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTurnCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTurnCommand.java new file mode 100644 index 0000000000..cfc2cad99d --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTurnCommand.java @@ -0,0 +1,47 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.core; + +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.api.turtle.ITurtleCommand; +import dan200.computercraft.api.turtle.TurtleAnimation; +import dan200.computercraft.api.turtle.TurtleCommandResult; +import dan200.computercraft.shared.util.DirectionUtil; + +public class TurtleTurnCommand implements ITurtleCommand +{ + private final TurnDirection m_direction; + + public TurtleTurnCommand( TurnDirection direction ) + { + m_direction = direction; + } + + @Override + public TurtleCommandResult execute( ITurtleAccess turtle ) + { + switch( m_direction ) + { + case Left: + { + turtle.setDirection( DirectionUtil.rotateLeft( turtle.getDirection() ) ); + turtle.playAnimation( TurtleAnimation.TurnLeft ); + return TurtleCommandResult.success(); + } + case Right: + { + turtle.setDirection( DirectionUtil.rotateRight( turtle.getDirection() ) ); + turtle.playAnimation( TurtleAnimation.TurnRight ); + return TurtleCommandResult.success(); + } + default: + { + return TurtleCommandResult.failure( "Unknown direction" ); + } + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/entity/TurtleVisionCamera.java b/src/main/java/dan200/computercraft/shared/turtle/entity/TurtleVisionCamera.java new file mode 100644 index 0000000000..228f155c93 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/entity/TurtleVisionCamera.java @@ -0,0 +1,106 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.entity; + +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.shared.turtle.core.TurtleBrain; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +public class TurtleVisionCamera extends EntityLivingBase +{ + private ITurtleAccess m_turtle; + private ItemStack[] m_inventory; + + public TurtleVisionCamera( World world, ITurtleAccess turtle ) + { + super( world ); + m_turtle = turtle; + m_inventory = new ItemStack[0]; + applyPos(); + } + + public ITurtleAccess getTurtle() + { + return m_turtle; + } + + @Override + public float getEyeHeight() + { + return 0.0f; + } + + @Override + public void onUpdate() + { + m_turtle = ((TurtleBrain)m_turtle).getFutureSelf(); + applyPos(); + } + + private void applyPos() + { + Vec3 prevPos = m_turtle.getVisualPosition( 0.0f ); + this.lastTickPosX = this.prevPosX = prevPos.xCoord; + this.lastTickPosY = this.prevPosY = prevPos.yCoord; + this.lastTickPosZ = this.prevPosZ = prevPos.zCoord; + this.prevRotationPitch = 0.0f; + this.prevRotationYaw = m_turtle.getVisualYaw( 0.0f ); + this.prevCameraPitch = 0.0f; + + Vec3 pos = m_turtle.getVisualPosition( 1.0f ); + this.posX = pos.xCoord; + this.posY = pos.yCoord; + this.posZ = pos.zCoord; + this.rotationPitch = 0.0f; + this.rotationYaw = m_turtle.getVisualYaw( 1.0f ); + this.cameraPitch = 0.0f; + + float yawDifference = this.rotationYaw - this.prevRotationYaw; + if( yawDifference > 180.0f ) + { + this.prevRotationYaw += 360.0f; + } + else if( yawDifference < -180.0f ) + { + this.prevRotationYaw -= 360.0f; + } + } + + // EntityLivingBase overrides: + + @Override + public ItemStack getHeldItem() + { + return null; + } + + @Override + public ItemStack getEquipmentInSlot( int slot ) + { + return null; + } + + @Override + public ItemStack getCurrentArmor( int slotIn ) + { + return null; + } + + @Override + public void setCurrentItemOrArmor( int slot, ItemStack stack ) + { + } + + @Override + public ItemStack[] getInventory() + { + return m_inventory; + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java new file mode 100644 index 0000000000..f78401b9c7 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java @@ -0,0 +1,181 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.inventory; + +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.shared.turtle.blocks.TileTurtle; +import dan200.computercraft.shared.turtle.core.TurtleBrain; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.ICrafting; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; + +public class ContainerTurtle extends Container +{ + private static final int PROGRESS_ID_SELECTED_SLOT = 0; + + public final int m_playerInvStartY; + public final int m_turtleInvStartX; + + protected ITurtleAccess m_turtle; + private int m_selectedSlot; + + protected ContainerTurtle( IInventory playerInventory, ITurtleAccess turtle, int playerInvStartY, int turtleInvStartX ) + { + m_playerInvStartY = playerInvStartY; + m_turtleInvStartX = turtleInvStartX; + + m_turtle = turtle; + if( !m_turtle.getWorld().isRemote ) + { + m_selectedSlot = m_turtle.getSelectedSlot(); + } + else + { + m_selectedSlot = 0; + } + + // Turtle inventory + for( int y = 0; y < 4; y++ ) + { + for( int x = 0; x < 4; x++ ) + { + addSlotToContainer( new Slot( m_turtle.getInventory(), x + y * 4, turtleInvStartX + 1 + x * 18, playerInvStartY + 1 + y * 18) ); + } + } + + // Player inventory + for( int y = 0; y < 3; y++) + { + for( int x = 0; x < 9; x++ ) + { + addSlotToContainer( new Slot( playerInventory, x + y * 9 + 9, 8 + x * 18, playerInvStartY + 1 + y * 18 ) ); + } + } + + // Player hotbar + for( int x = 0; x < 9; x++ ) + { + addSlotToContainer( new Slot( playerInventory, x, 8 + x * 18, playerInvStartY + 3 * 18 + 5 ) ); + } + } + + public ContainerTurtle( IInventory playerInventory, ITurtleAccess turtle ) + { + this( playerInventory, turtle, 134, 175 ); + } + + public int getSelectedSlot() + { + return m_selectedSlot; + } + + private void sendStateToPlayer( ICrafting icrafting ) + { + int selectedSlot = m_turtle.getSelectedSlot(); + icrafting.sendProgressBarUpdate( this, PROGRESS_ID_SELECTED_SLOT, selectedSlot ); + } + + @Override + public void onCraftGuiOpened( ICrafting crafting ) + { + super.onCraftGuiOpened( crafting ); + sendStateToPlayer( crafting ); + } + + @Override + public void detectAndSendChanges() + { + super.detectAndSendChanges(); + + int selectedSlot = m_turtle.getSelectedSlot(); + for( int i=0; i= 0 && slotNum < 16 ) + { + return tryItemMerge( player, slotNum, 16, 52, true ); + } + else if( slotNum >= 16 ) + { + return tryItemMerge( player, slotNum, 0, 16, false ); + } + return null; + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/items/ITurtleItem.java b/src/main/java/dan200/computercraft/shared/turtle/items/ITurtleItem.java new file mode 100644 index 0000000000..9c7e5e2e5e --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/items/ITurtleItem.java @@ -0,0 +1,22 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.items; + +import dan200.computercraft.api.turtle.ITurtleUpgrade; +import dan200.computercraft.api.turtle.TurtleSide; +import dan200.computercraft.shared.computer.items.IComputerItem; +import dan200.computercraft.shared.util.Colour; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; + +public interface ITurtleItem extends IComputerItem +{ + public ITurtleUpgrade getUpgrade( ItemStack stack, TurtleSide side ); + public int getFuelLevel( ItemStack stack ); + public Colour getColour( ItemStack stack ); + public ResourceLocation getOverlay( ItemStack stack ); +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtleAdvanced.java b/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtleAdvanced.java new file mode 100644 index 0000000000..908b12e7ce --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtleAdvanced.java @@ -0,0 +1,29 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.items; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import net.minecraft.block.Block; + +public class ItemTurtleAdvanced extends ItemTurtleNormal +{ + public ItemTurtleAdvanced( Block block ) + { + super( block ); + setUnlocalizedName( "computercraft:advanced_turtle" ); + setCreativeTab( ComputerCraft.mainCreativeTab ); + } + + // IComputerItem implementation + + @Override + public ComputerFamily getFamily( int damage ) + { + return ComputerFamily.Advanced; + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtleBase.java b/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtleBase.java new file mode 100644 index 0000000000..7f6ea71fe7 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtleBase.java @@ -0,0 +1,184 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.items; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.turtle.ITurtleUpgrade; +import dan200.computercraft.api.turtle.TurtleSide; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.items.ItemComputerBase; +import dan200.computercraft.shared.turtle.blocks.ITurtleTile; +import dan200.computercraft.shared.turtle.core.TurtleBrain; +import dan200.computercraft.shared.util.Colour; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.StatCollector; +import net.minecraft.world.World; + +import java.util.ArrayList; +import java.util.List; + +public abstract class ItemTurtleBase extends ItemComputerBase implements ITurtleItem +{ + protected ItemTurtleBase( Block block ) + { + super( block ); + setMaxStackSize( 64 ); + setHasSubtypes( true ); + } + + public abstract ItemStack create( int id, String label, Colour colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, int fuelLevel, ResourceLocation overlay ); + + @Override + public void getSubItems( Item itemID, CreativeTabs tabs, List list ) + { + List all = new ArrayList(); + ComputerCraft.addAllUpgradedTurtles( all ); + for( ItemStack stack : all ) + { + if( stack.getItem() == this ) + { + list.add( stack ); + } + } + } + + @Override + public boolean placeBlockAt( ItemStack stack, EntityPlayer player, World world, BlockPos pos, EnumFacing side, float hitX, float hitY, float hitZ, IBlockState newState ) + { + if( super.placeBlockAt( stack, player, world, pos, side, hitX, hitY, hitZ, newState ) ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof ITurtleTile ) + { + ITurtleTile turtle = (ITurtleTile)tile; + setupTurtleAfterPlacement( stack, turtle ); + } + return true; + } + return false; + } + + public void setupTurtleAfterPlacement( ItemStack stack, ITurtleTile turtle ) + { + // Set ID + int id = getComputerID( stack ); + if( id >= 0 ) + { + turtle.setComputerID( id ); + } + + // Set Label + String label = getLabel( stack ); + if( label != null ) + { + turtle.setLabel( label ); + } + + // Set Upgrades + for( TurtleSide side : TurtleSide.values() ) + { + turtle.getAccess().setUpgrade( side, getUpgrade( stack, side ) ); + } + + // Set Fuel level + int fuelLevel = getFuelLevel( stack ); + turtle.getAccess().setFuelLevel( fuelLevel ); + + // Set colour + Colour colour = getColour( stack ); + if( colour != null ) + { + turtle.getAccess().setDyeColour( colour.ordinal() ); + } + + // Set overlay + ResourceLocation overlay = getOverlay( stack ); + if( overlay != null ) + { + ((TurtleBrain)turtle.getAccess()).setOverlay( overlay ); + } + } + + @Override + public String getUnlocalizedName( ItemStack stack ) + { + ComputerFamily family = getFamily( stack ); + switch( family ) + { + case Normal: + default: + { + return "tile.computercraft:turtle"; + } + case Advanced: + { + return "tile.computercraft:advanced_turtle"; + } + case Beginners: + { + return "tile.computercraftedu:beginner_turtle"; + } + } + } + + @Override + public String getItemStackDisplayName( ItemStack stack ) + { + String baseString = getUnlocalizedName( stack ); + ITurtleUpgrade left = getUpgrade( stack, TurtleSide.Left ); + ITurtleUpgrade right = getUpgrade( stack, TurtleSide.Right ); + if( left != null && right != null ) + { + return StatCollector.translateToLocalFormatted( + baseString + ".upgraded_twice.name", + StatCollector.translateToLocal( right.getUnlocalisedAdjective() ), + StatCollector.translateToLocal( left.getUnlocalisedAdjective() ) + ); + } + else if( left != null ) + { + return StatCollector.translateToLocalFormatted( + baseString + ".upgraded.name", + StatCollector.translateToLocal( left.getUnlocalisedAdjective() ) + ); + } + else if( right != null ) + { + return StatCollector.translateToLocalFormatted( + baseString + ".upgraded.name", + StatCollector.translateToLocal( right.getUnlocalisedAdjective() ) + ); + } + else + { + return StatCollector.translateToLocal( baseString + ".name" ); + } + } + + // ITurtleItem implementation + + @Override + public abstract ITurtleUpgrade getUpgrade( ItemStack stack, TurtleSide side ); + + @Override + public abstract Colour getColour( ItemStack stack ); + + @Override + public abstract ResourceLocation getOverlay( ItemStack stack ); + + @Override + public abstract int getFuelLevel( ItemStack stack ); +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtleLegacy.java b/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtleLegacy.java new file mode 100644 index 0000000000..828d03ffca --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtleLegacy.java @@ -0,0 +1,152 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.items; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.turtle.ITurtleUpgrade; +import dan200.computercraft.api.turtle.TurtleSide; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.items.ItemComputer; +import dan200.computercraft.shared.util.Colour; +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ResourceLocation; + +public class ItemTurtleLegacy extends ItemTurtleBase +{ + public ItemTurtleLegacy( Block block ) + { + super( block ); + setUnlocalizedName( "computercraft:turtle" ); + setCreativeTab( ComputerCraft.mainCreativeTab ); + } + + @Override + public ItemStack create( int id, String label, Colour colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, int fuelLevel, ResourceLocation overlay ) + { + // Legacy turtles only support pickaxes and modems + if( (leftUpgrade != null && leftUpgrade != ComputerCraft.Upgrades.diamondPickaxe ) || + (rightUpgrade != null && rightUpgrade != ComputerCraft.Upgrades.wirelessModem) || + (colour != null) || (overlay != null) ) + { + return null; + } + + // Build the subtype + int subType = 0; + if( leftUpgrade != null ) + { + subType = subType + 1; + } + if( rightUpgrade != null ) + { + subType = subType + 2; + } + + // Build the ID + int damage = subType; + if( id >= 0 && id <= ItemComputer.HIGHEST_DAMAGE_VALUE_ID ) + { + damage += ((id + 1) << 2); + } + + // Build the stack + ItemStack stack = new ItemStack( this, 1, damage ); + if( fuelLevel > 0 || id > ItemComputer.HIGHEST_DAMAGE_VALUE_ID ) + { + NBTTagCompound nbt = new NBTTagCompound(); + if( fuelLevel > 0 ) + { + nbt.setInteger( "fuelLevel", fuelLevel ); + } + if( id > ItemComputer.HIGHEST_DAMAGE_VALUE_ID ) + { + nbt.setInteger( "computerID", id ); + } + stack.setTagCompound( nbt ); + } + if( label != null ) + { + stack.setStackDisplayName( label ); + } + + // Return the stack + return stack; + } + + // IComputerItem implementation + + @Override + public int getComputerID( ItemStack stack ) + { + if( stack.hasTagCompound() && stack.getTagCompound().hasKey( "computerID" ) ) + { + return stack.getTagCompound().getInteger( "computerID" ); + } + else + { + int damage = stack.getItemDamage(); + return ( ( damage & 0xfffc ) >> 2 ) - 1; + } + } + + @Override + public ComputerFamily getFamily( int damage ) + { + return ComputerFamily.Normal; + } + + // ITurtleItem implementation + + @Override + public ITurtleUpgrade getUpgrade( ItemStack stack, TurtleSide side ) + { + int damage = stack.getItemDamage(); + switch( side ) + { + case Left: + { + if( (damage & 0x1) > 0 ) + { + return ComputerCraft.Upgrades.diamondPickaxe; + } + break; + } + case Right: + { + if( (damage & 0x2) > 0 ) + { + return ComputerCraft.Upgrades.wirelessModem; + } + break; + } + } + return null; + } + + @Override + public Colour getColour( ItemStack stack ) + { + return null; + } + + @Override + public ResourceLocation getOverlay( ItemStack stack ) { return null; } + + @Override + public int getFuelLevel( ItemStack stack ) + { + if( stack.hasTagCompound() ) + { + NBTTagCompound nbt = stack.getTagCompound(); + return nbt.getInteger("fuelLevel"); + } + return 0; + } +} + diff --git a/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtleNormal.java b/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtleNormal.java new file mode 100644 index 0000000000..bfd4c48add --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtleNormal.java @@ -0,0 +1,197 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.items; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.turtle.ITurtleUpgrade; +import dan200.computercraft.api.turtle.TurtleSide; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.util.Colour; +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.common.util.Constants; + +public class ItemTurtleNormal extends ItemTurtleBase +{ + public ItemTurtleNormal( Block block ) + { + super( block ); + setUnlocalizedName( "computercraft:turtle" ); + setCreativeTab( ComputerCraft.mainCreativeTab ); + } + + @Override + public ItemStack create( int id, String label, Colour colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, int fuelLevel, ResourceLocation overlay ) + { + // Build the stack + ItemStack stack = new ItemStack( this, 1, 0 ); + NBTTagCompound nbt = new NBTTagCompound(); + if( leftUpgrade != null ) + { + int leftUpgradeLegacyID = leftUpgrade.getLegacyUpgradeID(); + if( leftUpgradeLegacyID >= 0 ) + { + nbt.setShort( "leftUpgrade", (short)leftUpgradeLegacyID ); + } + else + { + nbt.setString( "leftUpgrade", leftUpgrade.getUpgradeID().toString() ); + } + } + if( rightUpgrade != null ) + { + int rightUpgradeLegacyID = rightUpgrade.getLegacyUpgradeID(); + if( rightUpgradeLegacyID >= 0 ) + { + nbt.setShort( "rightUpgrade", (short)rightUpgradeLegacyID ); + } + else + { + nbt.setString( "rightUpgrade", rightUpgrade.getUpgradeID().toString() ); + } + } + if( id >= 0 ) + { + nbt.setInteger( "computerID", id ); + } + if( fuelLevel > 0 ) + { + nbt.setInteger( "fuelLevel", fuelLevel ); + } + if( colour != null ) + { + nbt.setInteger( "colourIndex", colour.ordinal() ); + } + if( overlay != null ) + { + nbt.setString( "overlay_mod", overlay.getResourceDomain() ); + nbt.setString( "overlay_path", overlay.getResourcePath() ); + } + stack.setTagCompound( nbt ); + + // Return the stack + if( label != null ) + { + stack.setStackDisplayName( label ); + } + return stack; + } + + // IComputerItem implementation + + @Override + public int getComputerID( ItemStack stack ) + { + if( stack.hasTagCompound() ) + { + NBTTagCompound nbt = stack.getTagCompound(); + if( nbt.hasKey( "computerID" ) ) + { + return nbt.getInteger( "computerID" ); + } + } + return -1; + } + + @Override + public ComputerFamily getFamily( int damage ) + { + return ComputerFamily.Normal; + } + + // ITurtleItem implementation + + @Override + public ITurtleUpgrade getUpgrade( ItemStack stack, TurtleSide side ) + { + if( stack.hasTagCompound() ) + { + NBTTagCompound nbt = stack.getTagCompound(); + switch( side ) + { + case Left: + { + if( nbt.hasKey( "leftUpgrade" ) ) + { + if( nbt.getTagId( "leftUpgrade" ) == Constants.NBT.TAG_STRING ) + { + return ComputerCraft.getTurtleUpgrade( nbt.getString( "leftUpgrade" ) ); + } + else + { + return ComputerCraft.getTurtleUpgrade( nbt.getShort( "leftUpgrade" ) ); + } + } + break; + } + case Right: + { + if( nbt.hasKey( "rightUpgrade" ) ) + { + if( nbt.getTagId( "rightUpgrade" ) == Constants.NBT.TAG_STRING ) + { + return ComputerCraft.getTurtleUpgrade( nbt.getString( "rightUpgrade" ) ); + } + else + { + return ComputerCraft.getTurtleUpgrade( nbt.getShort( "rightUpgrade" ) ); + } + } + break; + } + } + } + return null; + } + + @Override + public Colour getColour( ItemStack stack ) + { + if( stack.hasTagCompound() ) + { + NBTTagCompound nbt = stack.getTagCompound(); + if( nbt.hasKey( "colourIndex" ) ) + { + int index = nbt.getInteger( "colourIndex" ) & 0xf; + return Colour.values()[ index ]; + } + } + return null; + } + + @Override + public ResourceLocation getOverlay( ItemStack stack ) + { + if( stack.hasTagCompound() ) + { + NBTTagCompound nbt = stack.getTagCompound(); + if( nbt.hasKey( "overlay_mod" ) && nbt.hasKey( "overlay_path" ) ) + { + String overlay_mod = nbt.getString( "overlay_mod" ); + String overlay_path = nbt.getString( "overlay_path" ); + return new ResourceLocation( overlay_mod, overlay_path ); + } + } + return null; + } + + @Override + public int getFuelLevel( ItemStack stack ) + { + if( stack.hasTagCompound() ) + { + NBTTagCompound nbt = stack.getTagCompound(); + if( nbt.hasKey( "fuelLevel" ) ) + { + return nbt.getInteger( "fuelLevel" ); + } + } + return 0; + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItemFactory.java b/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItemFactory.java new file mode 100644 index 0000000000..56d195ced8 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItemFactory.java @@ -0,0 +1,89 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.items; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.turtle.ITurtleUpgrade; +import dan200.computercraft.api.turtle.TurtleSide; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.core.IComputer; +import dan200.computercraft.shared.turtle.blocks.ITurtleTile; +import dan200.computercraft.shared.util.Colour; +import dan200.computercraft.shared.util.ReflectionUtil; +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; + +public class TurtleItemFactory +{ + public static ItemStack create( ITurtleTile turtle ) + { + ITurtleUpgrade leftUpgrade = turtle.getAccess().getUpgrade( TurtleSide.Left ); + ITurtleUpgrade rightUpgrade = turtle.getAccess().getUpgrade( TurtleSide.Right ); + + IComputer computer = turtle.getComputer(); + if( computer != null ) + { + String label = computer.getLabel(); + if( label != null ) + { + if( turtle.getFamily() != ComputerFamily.Beginners ) + { + int id = computer.getID(); + int fuelLevel = turtle.getAccess().getFuelLevel(); + return create( id, label, turtle.getColour(), turtle.getFamily(), leftUpgrade, rightUpgrade, fuelLevel, turtle.getOverlay() ); + } + else + { + return create( -1, label, turtle.getColour(), turtle.getFamily(), leftUpgrade, rightUpgrade, 0, turtle.getOverlay() ); + } + } + } + return create( -1, null, turtle.getColour(), turtle.getFamily(), leftUpgrade, rightUpgrade, 0, turtle.getOverlay() ); + } + + public static ItemStack create( int id, String label, Colour colour, ComputerFamily family, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, int fuelLevel, ResourceLocation overlay ) + { + switch( family ) + { + case Normal: + { + ItemTurtleBase legacy = ((ItemTurtleBase)Item.getItemFromBlock( ComputerCraft.Blocks.turtle )); + ItemTurtleBase normal = ((ItemTurtleBase)Item.getItemFromBlock( ComputerCraft.Blocks.turtleExpanded )); + ItemStack legacyStack = legacy.create( id, label, colour, leftUpgrade, rightUpgrade, fuelLevel, overlay ); + return (legacyStack != null) ? legacyStack : normal.create( id, label, colour, leftUpgrade, rightUpgrade, fuelLevel, overlay ); + } + case Advanced: + { + ItemTurtleBase advanced = ((ItemTurtleBase)Item.getItemFromBlock( ComputerCraft.Blocks.turtleAdvanced )); + return advanced.create( id, label, colour, leftUpgrade, rightUpgrade, fuelLevel, overlay ); + } + case Beginners: + { + Block beginnersBlock = ReflectionUtil.safeGet( + ReflectionUtil.getOptionalField( + ReflectionUtil.getOptionalInnerClass( + ReflectionUtil.getOptionalClass( "dan200.computercraftedu.ComputerCraftEdu" ), + "Blocks" + ), + "turtleJunior" + ), + null, + Block.class + ); + if( beginnersBlock != null ) + { + ItemTurtleBase beginnersItem = ((ItemTurtleBase)Item.getItemFromBlock( beginnersBlock )); + return beginnersItem.create( id, label, colour, leftUpgrade, rightUpgrade, fuelLevel, overlay ); + } + return null; + } + } + return null; + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleRecipe.java b/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleRecipe.java new file mode 100644 index 0000000000..91cb97066c --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleRecipe.java @@ -0,0 +1,104 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.recipes; + +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.items.IComputerItem; +import dan200.computercraft.shared.turtle.items.TurtleItemFactory; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.world.World; + +public class TurtleRecipe implements IRecipe +{ + private final Item[] m_recipe; + private final ComputerFamily m_family; + + public TurtleRecipe( Item[] recipe, ComputerFamily family ) + { + m_recipe = recipe; + m_family = family; + } + + @Override + public int getRecipeSize() + { + return 9; + } + + @Override + public ItemStack getRecipeOutput() + { + return TurtleItemFactory.create( -1, null, null, m_family, null, null, 0, null ); + } + + @Override + public boolean matches( InventoryCrafting _inventory, World world ) + { + return (getCraftingResult( _inventory ) != null); + } + + @Override + public ItemStack getCraftingResult( InventoryCrafting inventory ) + { + // See if we match the recipe, and extract the input computercraft ID + int computerID = -1; + String label = null; + for( int y=0; y<3; ++y ) + { + for( int x=0; x<3; ++x ) + { + ItemStack item = inventory.getStackInRowAndColumn(x, y); + if( item != null && item.getItem() == m_recipe[ x + y*3 ] ) + { + if( item.getItem() instanceof IComputerItem ) + { + IComputerItem itemComputer = (IComputerItem)item.getItem(); + if( m_family == ComputerFamily.Beginners || itemComputer.getFamily( item ) == m_family ) + { + computerID = itemComputer.getComputerID( item ); + label = itemComputer.getLabel( item ); + } + else + { + return null; + } + } + } + else + { + return null; + } + } + } + + // Build a turtle with the same ID the computer had + // Construct the new stack + if( m_family != ComputerFamily.Beginners ) + { + return TurtleItemFactory.create( computerID, label, null, m_family, null, null, 0, null ); + } + else + { + return TurtleItemFactory.create( -1, label, null, m_family, null, null, 0, null ); + } + } + + @Override + public ItemStack[] getRemainingItems( InventoryCrafting inventoryCrafting ) + { + ItemStack[] results = new ItemStack[ inventoryCrafting.getSizeInventory() ]; + for (int i = 0; i < results.length; ++i) + { + ItemStack stack = inventoryCrafting.getStackInSlot(i); + results[i] = net.minecraftforge.common.ForgeHooks.getContainerItem(stack); + } + return results; + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java b/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java new file mode 100644 index 0000000000..fb7eb4271f --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java @@ -0,0 +1,171 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.recipes; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.turtle.ITurtleUpgrade; +import dan200.computercraft.api.turtle.TurtleSide; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.proxy.CCTurtleProxyCommon; +import dan200.computercraft.shared.turtle.items.ITurtleItem; +import dan200.computercraft.shared.turtle.items.TurtleItemFactory; +import dan200.computercraft.shared.util.Colour; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; + +public class TurtleUpgradeRecipe implements IRecipe +{ + public TurtleUpgradeRecipe() + { + } + + @Override + public int getRecipeSize() + { + return 3; + } + + @Override + public ItemStack getRecipeOutput() + { + return TurtleItemFactory.create( -1, null, null, ComputerFamily.Normal, null, null, 0, null ); + } + + @Override + public boolean matches( InventoryCrafting inventory, World world ) + { + return (getCraftingResult( inventory ) != null); + } + + @Override + public ItemStack getCraftingResult( InventoryCrafting inventory ) + { + // Scan the grid for a row containing a turtle and 1 or 2 items + ItemStack leftItem = null; + ItemStack turtle = null; + ItemStack rightItem = null; + + for( int y=0; y 64 ) + { + throw new LuaException( "Crafting count " + count + " out of range" ); + } + return count; + } + + @Override + public Object[] callMethod( IComputerAccess computer, ILuaContext context, int method, Object[] arguments ) throws LuaException, InterruptedException + { + switch( method ) + { + case 0: + { + // craft + final int limit = parseCount( arguments ); + return m_turtle.executeCommand( context, new TurtleCraftCommand( limit ) ); + } + default: + { + return null; + } + } + } + + @Override + public void attach( IComputerAccess computer ) + { + } + + @Override + public void detach( IComputerAccess computer ) + { + } + + @Override + public boolean equals( IPeripheral other ) + { + return (other != null && other.getClass() == this.getClass()); + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleAxe.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleAxe.java new file mode 100644 index 0000000000..b43cf48c81 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleAxe.java @@ -0,0 +1,24 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.upgrades; + +import net.minecraft.item.Item; +import net.minecraft.util.ResourceLocation; + +public class TurtleAxe extends TurtleTool +{ + public TurtleAxe( ResourceLocation id, int legacyId, String adjective, Item item ) + { + super( id, legacyId, adjective, item ); + } + + @Override + protected float getDamageMultiplier() + { + return 6.0f; + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleCraftingTable.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleCraftingTable.java new file mode 100644 index 0000000000..c459be9280 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleCraftingTable.java @@ -0,0 +1,119 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.upgrades; + +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.api.turtle.*; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.model.IBakedModel; +import net.minecraft.client.resources.model.ModelManager; +import net.minecraft.client.resources.model.ModelResourceLocation; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.apache.commons.lang3.tuple.Pair; + +import javax.vecmath.Matrix4f; + +public class TurtleCraftingTable implements ITurtleUpgrade +{ + private ResourceLocation m_id; + private int m_legacyID; + private ItemStack m_item; + + @SideOnly( Side.CLIENT ) + private ModelResourceLocation m_leftModel; + + @SideOnly( Side.CLIENT ) + private ModelResourceLocation m_rightModel; + + public TurtleCraftingTable( int legacyId ) + { + m_id = new ResourceLocation( "minecraft", "crafting_table" ); + m_legacyID = legacyId; + m_item = new ItemStack( Blocks.crafting_table, 1, 0 ); + } + + @Override + public ResourceLocation getUpgradeID() + { + return m_id; + } + + @Override + public int getLegacyUpgradeID() + { + return m_legacyID; + } + + @Override + public String getUnlocalisedAdjective() + { + return "upgrade.minecraft:crafting_table.adjective"; + } + + @Override + public TurtleUpgradeType getType() + { + return TurtleUpgradeType.Peripheral; + } + + @Override + public ItemStack getCraftingItem() + { + return m_item; + } + + @Override + public IPeripheral createPeripheral( ITurtleAccess turtle, TurtleSide side ) + { + return new CraftingTablePeripheral( turtle ); + } + + @Override + public TurtleCommandResult useTool( ITurtleAccess turtle, TurtleSide side, TurtleVerb verb, EnumFacing dir ) + { + return null; + } + + @SideOnly( Side.CLIENT ) + private void loadModelLocations() + { + if( m_leftModel == null ) + { + m_leftModel = new ModelResourceLocation( "computercraft:turtle_crafting_table_left", "inventory" ); + m_rightModel = new ModelResourceLocation( "computercraft:turtle_crafting_table_right", "inventory" ); + } + } + + @Override + @SideOnly( Side.CLIENT ) + public Pair getModel( ITurtleAccess turtle, TurtleSide side ) + { + loadModelLocations(); + + Matrix4f transform = null; + Minecraft mc = Minecraft.getMinecraft(); + ModelManager modelManager = mc.getRenderItem().getItemModelMesher().getModelManager(); + if( side == TurtleSide.Left ) + { + return Pair.of( modelManager.getModel( m_leftModel ), transform ); + } + else + { + return Pair.of( modelManager.getModel( m_rightModel ), transform ); + } + } + + @Override + public void update( ITurtleAccess turtle, TurtleSide side ) + { + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleHoe.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleHoe.java new file mode 100644 index 0000000000..b0cf9448a1 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleHoe.java @@ -0,0 +1,60 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.upgrades; + +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.api.turtle.TurtleCommandResult; +import dan200.computercraft.api.turtle.TurtleSide; +import dan200.computercraft.api.turtle.TurtleVerb; +import dan200.computercraft.shared.turtle.core.TurtlePlaceCommand; +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; + +public class TurtleHoe extends TurtleTool +{ + public TurtleHoe( ResourceLocation id, int legacyId, String adjective, Item item ) + { + super( id, legacyId, adjective, item ); + } + + @Override + protected boolean canBreakBlock( World world, BlockPos pos ) + { + if( super.canBreakBlock( world, pos ) ) + { + Block block = world.getBlockState( pos ).getBlock(); + return + block.getMaterial() == Material.plants || + block.getMaterial() == Material.cactus || + block.getMaterial() == Material.gourd || + block.getMaterial() == Material.leaves || + block.getMaterial() == Material.vine; + } + return false; + } + + @Override + public TurtleCommandResult useTool( ITurtleAccess turtle, TurtleSide side, TurtleVerb verb, EnumFacing direction ) + { + if( verb == TurtleVerb.Dig ) + { + ItemStack hoe = m_item.copy(); + ItemStack remainder = TurtlePlaceCommand.deploy( hoe, turtle, direction, null, null ); + if( remainder != hoe ) + { + return TurtleCommandResult.success(); + } + } + return super.useTool( turtle, side, verb, direction ); + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java new file mode 100644 index 0000000000..1be67984a4 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java @@ -0,0 +1,304 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.upgrades; + +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.shared.turtle.blocks.TileTurtle; +import dan200.computercraft.shared.turtle.core.TurtlePlayer; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.CraftingManager; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; + +import java.util.ArrayList; + +public class TurtleInventoryCrafting extends InventoryCrafting +{ + private ITurtleAccess m_turtle; + private int m_xStart; + private int m_yStart; + + public TurtleInventoryCrafting( ITurtleAccess turtle ) + { + super( null, 0, 0 ); + m_turtle = turtle; + m_xStart = 0; + m_yStart = 0; + } + + private ItemStack tryCrafting( int xStart, int yStart ) + { + m_xStart = xStart; + m_yStart = yStart; + + // Check the non-relevant parts of the inventory are empty + for( int x=0; x= m_xStart + 3 || + y < m_yStart || y >= m_yStart + 3 ) + { + if( m_turtle.getInventory().getStackInSlot( x + y * TileTurtle.INVENTORY_WIDTH ) != null ) + { + return null; + } + } + } + } + + // Check the actual crafting + return CraftingManager.getInstance().findMatchingRecipe( this, m_turtle.getWorld() ); + } + + public ArrayList doCrafting( World world, int maxCount ) + { + if( world.isRemote || !(world instanceof WorldServer) ) + { + return null; + } + + // Find out what we can craft + ItemStack result = tryCrafting( 0, 0 ); + if( result == null ) + { + result = tryCrafting( 0, 1 ); + } + if( result == null ) + { + result = tryCrafting( 1, 0 ); + } + if( result == null ) + { + result = tryCrafting( 1, 1 ); + } + + // Craft it + if( result != null ) + { + // Special case: craft(0) just returns an empty list if crafting was possible + ArrayList results = new ArrayList(); + if( maxCount == 0 ) + { + return results; + } + + // Find out how many we can craft + int numToCraft = 1; + int size = getSizeInventory(); + if( maxCount > 1 ) + { + int minStackSize = 0; + for( int n=0; n stack.stackSize) ) + { + minStackSize = stack.stackSize; + } + } + + if( minStackSize > 1 ) + { + numToCraft = Math.min( minStackSize, result.getMaxStackSize() / result.stackSize ); + numToCraft = Math.min( numToCraft, maxCount ); + result.stackSize = result.stackSize * numToCraft; + } + } + + // Do post-pickup stuff + TurtlePlayer turtlePlayer = new TurtlePlayer( (WorldServer)world ); + result.onCrafting( world, turtlePlayer, numToCraft ); + results.add( result ); + + // Consume resources from the inventory + ItemStack[] remainingItems = CraftingManager.getInstance().func_180303_b( this, world ); // getRemainingItems + for( int n=0; n= replacement.getMaxDamage()) ) + { + replacement.stackSize = Math.min( numToCraft, replacement.getMaxStackSize() ); + if( getStackInSlot( n ) == null ) + { + setInventorySlotContents( n, replacement ); + } + else + { + results.add( replacement ); + } + } + } + } + } + return results; + } + + return null; + } + + @Override + public ItemStack getStackInRowAndColumn(int x, int y) + { + if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight() ) + { + return getStackInSlot( x + y * getWidth() ); + } + return null; + } + + @Override + public int getWidth() + { + return 3; + } + + @Override + public int getHeight() + { + return 3; + } + + private int modifyIndex( int index ) + { + int x = m_xStart + (index % getWidth()); + int y = m_yStart + (index / getHeight()); + if( x >= 0 && x < TileTurtle.INVENTORY_WIDTH && + y >= 0 && y < TileTurtle.INVENTORY_HEIGHT ) + { + return x + y * TileTurtle.INVENTORY_WIDTH; + } + return -1; + } + + // IInventory implementation + + @Override + public int getSizeInventory() + { + return getWidth() * getHeight(); + } + + @Override + public ItemStack getStackInSlot( int i ) + { + i = modifyIndex( i ); + return m_turtle.getInventory().getStackInSlot( i ); + } + + @Override + public String getName() + { + return ""; + } + + @Override + public boolean hasCustomName() + { + return false; + } + + @Override + public IChatComponent getDisplayName() + { + return new ChatComponentText( "" ); + } + + @Override + public ItemStack removeStackFromSlot( int i ) + { + i = modifyIndex( i ); + return m_turtle.getInventory().removeStackFromSlot( i ); + } + + @Override + public ItemStack decrStackSize( int i, int size ) + { + i = modifyIndex( i ); + return m_turtle.getInventory().decrStackSize( i, size ); + } + + @Override + public void setInventorySlotContents( int i, ItemStack stack ) + { + i = modifyIndex( i ); + m_turtle.getInventory().setInventorySlotContents( i, stack ); + } + + @Override + public int getInventoryStackLimit() + { + return m_turtle.getInventory().getInventoryStackLimit(); + } + + @Override + public void markDirty() + { + m_turtle.getInventory().markDirty(); + } + + @Override + public boolean isUseableByPlayer( EntityPlayer player ) + { + return true; + } + + @Override + public void openInventory( EntityPlayer player ) + { + } + + @Override + public void closeInventory( EntityPlayer player ) + { + } + + @Override + public boolean isItemValidForSlot( int i, ItemStack stack ) + { + i = modifyIndex( i ); + return m_turtle.getInventory().isItemValidForSlot( i, stack ); + } + + @Override + public int getField( int id ) + { + return 0; + } + + @Override + public void setField( int id, int value ) + { + } + + @Override + public int getFieldCount() + { + return 0; + } + + @Override + public void clear() + { + for( int i=0; i getModel( ITurtleAccess turtle, TurtleSide side ) + { + loadModelLocations(); + + boolean active = false; + if( turtle != null ) + { + NBTTagCompound turtleNBT = turtle.getUpgradeNBTData( side ); + if( turtleNBT.hasKey( "active" ) ) + { + active = turtleNBT.getBoolean( "active" ); + } + } + + Matrix4f transform = null; + Minecraft mc = Minecraft.getMinecraft(); + ModelManager modelManager = mc.getRenderItem().getItemModelMesher().getModelManager(); + if( side == TurtleSide.Left ) + { + return Pair.of( + active ? modelManager.getModel( m_leftOnModel ) : modelManager.getModel( m_leftOffModel ), + transform + ); + } + else + { + return Pair.of( + active ? modelManager.getModel( m_rightOnModel ) : modelManager.getModel( m_rightOffModel ), + transform + ); + } + } + + @Override + public void update( ITurtleAccess turtle, TurtleSide side ) + { + // Advance the modem + if( !turtle.getWorld().isRemote ) + { + IPeripheral peripheral = turtle.getPeripheral( side ); + if( peripheral != null && peripheral instanceof Peripheral ) + { + Peripheral modemPeripheral = (Peripheral)peripheral; + if( modemPeripheral.pollChanged() ) + { + turtle.getUpgradeNBTData( side ).setBoolean( "active", modemPeripheral.isActive() ); + turtle.updateUpgradeNBTData( side ); + } + } + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleShovel.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleShovel.java new file mode 100644 index 0000000000..0141238695 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleShovel.java @@ -0,0 +1,43 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.upgrades; +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.item.Item; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; + +public class TurtleShovel extends TurtleTool +{ + public TurtleShovel( ResourceLocation id, int legacyId, String adjective, Item item ) + { + super( id, legacyId, adjective, item ); + } + + @Override + protected boolean canBreakBlock( World world, BlockPos pos ) + { + if( super.canBreakBlock( world, pos ) ) + { + Block block = world.getBlockState( pos ).getBlock(); + return + block.getMaterial() == Material.ground || + block.getMaterial() == Material.sand || + block.getMaterial() == Material.snow || + block.getMaterial() == Material.clay || + block.getMaterial() == Material.craftedSnow || + block.getMaterial() == Material.grass || + block.getMaterial() == Material.plants || + block.getMaterial() == Material.cactus || + block.getMaterial() == Material.gourd || + block.getMaterial() == Material.leaves || + block.getMaterial() == Material.vine; + } + return false; + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSword.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSword.java new file mode 100644 index 0000000000..7d67eaacbb --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSword.java @@ -0,0 +1,43 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.upgrades; +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.item.Item; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; + +public class TurtleSword extends TurtleTool +{ + public TurtleSword( ResourceLocation id, int legacyId, String adjective, Item item ) + { + super( id, legacyId, adjective, item ); + } + + @Override + protected boolean canBreakBlock( World world, BlockPos pos ) + { + if( super.canBreakBlock( world, pos ) ) + { + Block block = world.getBlockState( pos ).getBlock(); + return + block.getMaterial() == Material.plants || + block.getMaterial() == Material.leaves || + block.getMaterial() == Material.vine || + block.getMaterial() == Material.cloth || + block.getMaterial() == Material.web; + } + return false; + } + + @Override + protected float getDamageMultiplier() + { + return 9.0f; + } +} diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java new file mode 100644 index 0000000000..9c9704aa01 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java @@ -0,0 +1,306 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.turtle.upgrades; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.api.turtle.*; +import dan200.computercraft.shared.turtle.core.TurtleBrain; +import dan200.computercraft.shared.turtle.core.TurtlePlaceCommand; +import dan200.computercraft.shared.turtle.core.TurtlePlayer; +import dan200.computercraft.shared.util.IEntityDropConsumer; +import dan200.computercraft.shared.util.InventoryUtil; +import dan200.computercraft.shared.util.WorldUtil; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.model.IBakedModel; +import net.minecraft.entity.Entity; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.init.Blocks; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.*; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import net.minecraftforge.common.ForgeHooks; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.apache.commons.lang3.tuple.Pair; + +import javax.vecmath.Matrix4f; +import java.util.Iterator; + +public class TurtleTool implements ITurtleUpgrade +{ + private ResourceLocation m_id; + private int m_legacyId; + private String m_adjective; + protected ItemStack m_item; + + public TurtleTool( ResourceLocation id, int legacyID, String adjective, Item item ) + { + m_id = id; + m_legacyId = legacyID; + m_adjective = adjective; + m_item = new ItemStack( item, 1, 0 ); + } + + @Override + public ResourceLocation getUpgradeID() + { + return m_id; + } + + @Override + public int getLegacyUpgradeID() + { + return m_legacyId; + } + + @Override + public String getUnlocalisedAdjective() + { + return m_adjective; + } + + @Override + public TurtleUpgradeType getType() + { + return TurtleUpgradeType.Tool; + } + + @Override + public ItemStack getCraftingItem() + { + return m_item.copy(); + } + + @Override + public IPeripheral createPeripheral( ITurtleAccess turtle, TurtleSide side ) + { + return null; + } + + @Override + @SideOnly( Side.CLIENT ) + public Pair getModel( ITurtleAccess turtle, TurtleSide side ) + { + float xOffset = (side == TurtleSide.Left) ? -0.40625f : 0.40625f; + Matrix4f transform = new Matrix4f( + 0.0f, 0.0f, -1.0f, 1.0f + xOffset, + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + Minecraft mc = Minecraft.getMinecraft(); + return Pair.of( + mc.getRenderItem().getItemModelMesher().getItemModel( m_item ), + transform + ); + } + + @Override + public void update( ITurtleAccess turtle, TurtleSide side ) + { + } + + @Override + public TurtleCommandResult useTool( ITurtleAccess turtle, TurtleSide side, TurtleVerb verb, EnumFacing direction ) + { + switch( verb ) + { + case Attack: + { + return attack( turtle, direction ); + } + case Dig: + { + return dig( turtle, direction ); + } + default: + { + return TurtleCommandResult.failure( "Unsupported action" ); + } + } + } + + protected boolean canBreakBlock( World world, BlockPos pos ) + { + Block block = world.getBlockState( pos ).getBlock(); + if( block.isAir( world, pos ) || block == Blocks.bedrock || block.getBlockHardness( world, pos ) <= -1.0F ) + { + return false; + } + return true; + } + + protected boolean canHarvestBlock( World world, BlockPos pos ) + { + Block block = world.getBlockState( pos ).getBlock(); + TurtlePlayer turtlePlayer = new TurtlePlayer( (WorldServer)world ); + turtlePlayer.loadInventory( m_item.copy() ); + return ForgeHooks.canHarvestBlock( block, turtlePlayer, world, pos ); + } + + protected float getDamageMultiplier() + { + return 3.0f; + } + + private TurtleCommandResult attack( final ITurtleAccess turtle, EnumFacing direction ) + { + // Create a fake player, and orient it appropriately + final World world = turtle.getWorld(); + final BlockPos position = turtle.getPosition(); + final TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer( turtle, position, direction ); + + // See if there is an entity present + Vec3 turtlePos = new Vec3( turtlePlayer.posX, turtlePlayer.posY, turtlePlayer.posZ ); + Vec3 rayDir = turtlePlayer.getLook( 1.0f ); + Vec3 rayStart = turtlePos; + Pair hit = WorldUtil.rayTraceEntities( world, rayStart, rayDir, 1.5 ); + if( hit != null ) + { + // Load up the turtle's inventory + ItemStack stackCopy = m_item.copy(); + turtlePlayer.loadInventory( stackCopy ); + + // Start claiming entity drops + Entity hitEntity = hit.getKey(); + ComputerCraft.setEntityDropConsumer( hitEntity, new IEntityDropConsumer() + { + @Override + public void consumeDrop( Entity entity, ItemStack drop ) + { + ItemStack remainder = InventoryUtil.storeItems( drop, turtle.getInventory(), 0, turtle.getInventory().getSizeInventory(), turtle.getSelectedSlot() ); + if( remainder != null ) + { + WorldUtil.dropItemStack( remainder, world, position, turtle.getDirection().getOpposite() ); + } + } + } ); + + // Place on the entity + boolean placed = false; + if( hitEntity.canAttackWithItem() && !hitEntity.hitByEntity( turtlePlayer ) ) + { + float damage = (float)turtlePlayer.getEntityAttribute( SharedMonsterAttributes.attackDamage ).getAttributeValue(); + damage *= getDamageMultiplier(); + if( damage > 0.0f ) + { + DamageSource source = DamageSource.causePlayerDamage( turtlePlayer ); + if( hitEntity instanceof EntityArmorStand ) + { + // Special case for armor stands: attack twice to guarantee destroy + hitEntity.attackEntityFrom( source, damage ); + if( !hitEntity.isDead ) + { + hitEntity.attackEntityFrom( source, damage ); + } + placed = true; + } + else + { + if( hitEntity.attackEntityFrom( source, damage ) ) + { + placed = true; + } + } + } + } + + // Stop claiming drops + ComputerCraft.clearEntityDropConsumer( hitEntity ); + + // Put everything we collected into the turtles inventory, then return + if( placed ) + { + turtlePlayer.unloadInventory( turtle ); + return TurtleCommandResult.success(); + } + } + + return TurtleCommandResult.failure( "Nothing to attack here" ); + } + + private TurtleCommandResult dig( ITurtleAccess turtle, EnumFacing direction ) + { + // Get ready to dig + World world = turtle.getWorld(); + BlockPos position = turtle.getPosition(); + BlockPos newPosition = WorldUtil.moveCoords( position, direction ); + + if( WorldUtil.isBlockInWorld( world, newPosition ) && + !world.isAirBlock( newPosition ) && + !WorldUtil.isLiquidBlock( world, newPosition ) ) + { + if( ComputerCraft.turtlesObeyBlockProtection ) + { + // Check spawn protection + TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer( turtle, position, direction ); + if( !ComputerCraft.isBlockEditable( world, newPosition, turtlePlayer ) ) + { + return TurtleCommandResult.failure( "Cannot break protected block" ); + } + } + + // Check if we can break the block + if( !canBreakBlock( world, newPosition ) ) + { + return TurtleCommandResult.failure( "Unbreakable block detected" ); + } + + // Consume the items the block drops + if( canHarvestBlock( world, newPosition ) ) + { + java.util.List items = getBlockDropped( world, newPosition ); + if( items != null && items.size() > 0 ) + { + Iterator it = items.iterator(); + while( it.hasNext() ) + { + ItemStack stack = it.next(); + ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getInventory(), 0, turtle.getInventory().getSizeInventory(), turtle.getSelectedSlot() ); + if( remainder != null ) + { + // If there's no room for the items, drop them + WorldUtil.dropItemStack( remainder, world, position, direction ); + } + } + } + } + + // Destroy the block + Block previousBlock = world.getBlockState( newPosition ).getBlock(); + IBlockState previousState = world.getBlockState( newPosition ); + if( previousBlock != null ) + { + world.playSoundEffect( newPosition.getX() + 0.5, newPosition.getY() + 0.5, newPosition.getZ() + 0.5, previousBlock.stepSound.getBreakSound(), (previousBlock.stepSound.getVolume() + 1.0F) / 2.0F, previousBlock.stepSound.getFrequency() * 0.8F); + } + world.setBlockToAir( newPosition ); + + // Remember the previous block + if( turtle instanceof TurtleBrain && previousBlock != null ) + { + TurtleBrain brain = (TurtleBrain)turtle; + brain.saveBlockChange( newPosition, previousState ); + } + + return TurtleCommandResult.success(); + } + + return TurtleCommandResult.failure( "Nothing to dig here" ); + } + + private java.util.List getBlockDropped( World world, BlockPos pos ) + { + Block block = world.getBlockState( pos ).getBlock(); + return block.getDrops( world, pos, world.getBlockState( pos ), 0 ); + } +} diff --git a/src/main/java/dan200/computercraft/shared/util/Colour.java b/src/main/java/dan200/computercraft/shared/util/Colour.java new file mode 100644 index 0000000000..b154046b86 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/util/Colour.java @@ -0,0 +1,84 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.util; + +public enum Colour +{ + Black( 0x191919 ), + Red( 0xcc4c4c ), + Green( 0x57A64E ), + Brown( 0x7f664c ), + Blue( 0x3366cc ), + Purple( 0xb266e5 ), + Cyan( 0x4c99b2 ), + LightGrey( 0x999999 ), + Grey( 0x4c4c4c ), + Pink( 0xf2b2cc ), + Lime( 0x7fcc19 ), + Yellow( 0xdede6c ), + LightBlue( 0x99b2f2 ), + Magenta( 0xe57fd8 ), + Orange( 0xf2b233 ), + White( 0xf0f0f0 ); + + public static Colour fromInt( int colour ) + { + if( colour >= 0 && colour < 16 ) + { + return Colour.values()[ colour ]; + } + return null; + } + + private int m_hex; + private float[] m_rgb; + + private Colour( int hex ) + { + m_hex = hex; + m_rgb = new float[] { + (float)((hex >> 16) & 0xFF) / 255.0f, + (float)((hex >> 8 ) & 0xFF) / 255.0f, + (float)((hex ) & 0xFF) / 255.0f, + }; + } + + public Colour getNext() + { + return Colour.values()[ (ordinal() + 1) % 16 ]; + } + + public Colour getPrevious() + { + return Colour.values()[ (ordinal() + 15) % 16 ]; + } + + public int getHex() + { + return m_hex; + } + + public float[] getRGB() + { + return m_rgb; + } + + public float getR() + { + return m_rgb[0]; + } + + public float getG() + { + return m_rgb[1]; + } + + public float getB() + { + return m_rgb[2]; + } +} diff --git a/src/main/java/dan200/computercraft/shared/util/CreativeTabMain.java b/src/main/java/dan200/computercraft/shared/util/CreativeTabMain.java new file mode 100644 index 0000000000..8d990d72fb --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/util/CreativeTabMain.java @@ -0,0 +1,31 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.util; + +import dan200.computercraft.ComputerCraft; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.item.Item; + +public class CreativeTabMain extends CreativeTabs +{ + public CreativeTabMain( int i ) + { + super( i, "ComputerCraft" ); + } + + @Override + public Item getTabIconItem() + { + return Item.getItemFromBlock( ComputerCraft.Blocks.computer ); + } + + @Override + public String getTranslatedTabLabel() + { + return getTabLabel(); + } +} diff --git a/src/main/java/dan200/computercraft/shared/util/CreativeTabTreasure.java b/src/main/java/dan200/computercraft/shared/util/CreativeTabTreasure.java new file mode 100644 index 0000000000..57e06fb6c9 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/util/CreativeTabTreasure.java @@ -0,0 +1,31 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.util; + +import dan200.computercraft.ComputerCraft; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.item.Item; + +public class CreativeTabTreasure extends CreativeTabs +{ + public CreativeTabTreasure( int i ) + { + super( i, "Treasure Disks" ); + } + + @Override + public Item getTabIconItem() + { + return ComputerCraft.Items.treasureDisk; + } + + @Override + public String getTranslatedTabLabel() + { + return getTabLabel(); + } +} diff --git a/src/main/java/dan200/computercraft/shared/util/DirectionUtil.java b/src/main/java/dan200/computercraft/shared/util/DirectionUtil.java new file mode 100644 index 0000000000..7d439aeefd --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/util/DirectionUtil.java @@ -0,0 +1,122 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.util; + +import dan200.computercraft.shared.common.IDirectionalTile; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.MathHelper; + +public class DirectionUtil +{ + public static EnumFacing rotateRight( EnumFacing dir ) + { + if( dir.getAxis() != EnumFacing.Axis.Y ) + { + return dir.rotateY(); + } + else + { + return dir; + } + } + + public static EnumFacing rotateLeft( EnumFacing dir ) + { + if( dir.getAxis() != EnumFacing.Axis.Y ) + { + return dir.rotateYCCW(); + } + else + { + return dir; + } + } + + public static EnumFacing rotate180( EnumFacing dir ) + { + if( dir.getAxis() != EnumFacing.Axis.Y ) + { + return dir.getOpposite(); + } + else + { + return dir; + } + } + + public static int toLocal( IDirectionalTile directional, EnumFacing dir ) + { + EnumFacing front = directional.getDirection(); + if( front.getAxis() == EnumFacing.Axis.Y ) + { + front = EnumFacing.NORTH; + } + + EnumFacing back = rotate180( front ); + EnumFacing left = rotateLeft( front ); + EnumFacing right = rotateRight( front ); + if( dir == front ) + { + return 3; + } + else if( dir == back ) + { + return 2; + } + else if( dir == left ) + { + return 5; + } + else if( dir == right ) + { + return 4; + } + else if( dir == EnumFacing.UP ) + { + return 1; + } + else + { + return 0; + } + } + + public static EnumFacing fromEntityRot( EntityLivingBase player ) + { + int rot = MathHelper.floor_float( ( player.rotationYaw / 90.0f ) + 0.5f ) & 0x3; + switch( rot ) { + case 0: return EnumFacing.NORTH; + case 1: return EnumFacing.EAST; + case 2: return EnumFacing.SOUTH; + case 3: return EnumFacing.WEST; + } + return EnumFacing.NORTH; + } + + public static float toYawAngle( EnumFacing dir ) + { + switch( dir ) + { + case NORTH: return 180.0f; + case SOUTH: return 0.0f; + case WEST: return 90.0f; + case EAST: return 270.0f; + default: return 0.0f; + } + } + + public static float toPitchAngle( EnumFacing dir ) + { + switch( dir ) + { + case DOWN: return 90.0f; + case UP: return 270.0f; + default: return 0.0f; + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/util/Holiday.java b/src/main/java/dan200/computercraft/shared/util/Holiday.java new file mode 100644 index 0000000000..e77b365b9b --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/util/Holiday.java @@ -0,0 +1,16 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.util; + +public enum Holiday +{ + None, + Valentines, + AprilFoolsDay, + Halloween, + Christmas, +} diff --git a/src/main/java/dan200/computercraft/shared/util/HolidayUtil.java b/src/main/java/dan200/computercraft/shared/util/HolidayUtil.java new file mode 100644 index 0000000000..a31652a539 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/util/HolidayUtil.java @@ -0,0 +1,40 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.util; + +import java.util.Calendar; + +public class HolidayUtil +{ + public static Holiday getCurrentHoliday() + { + return getHoliday( Calendar.getInstance() ); + } + + private static Holiday getHoliday( Calendar calendar ) + { + int month = calendar.get( Calendar.MONTH ); + int day = calendar.get( Calendar.DAY_OF_MONTH ); + if( month == Calendar.FEBRUARY && day == 14 ) + { + return Holiday.Valentines; + } + else if( month == Calendar.APRIL && day == 1 ) + { + return Holiday.AprilFoolsDay; + } + else if( month == Calendar.OCTOBER && day == 31 ) + { + return Holiday.Halloween; + } + else if( month == Calendar.DECEMBER && day >= 24 && day <= 30 ) + { + return Holiday.Christmas; + } + return Holiday.None; + } +} diff --git a/src/main/java/dan200/computercraft/shared/util/IDAssigner.java b/src/main/java/dan200/computercraft/shared/util/IDAssigner.java new file mode 100644 index 0000000000..7812f753a9 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/util/IDAssigner.java @@ -0,0 +1,114 @@ +package dan200.computercraft.shared.util; + +import java.io.*; + +public class IDAssigner +{ + private IDAssigner() + { + } + + public static int getNextIDFromDirectory( File dir ) + { + return getNextID( dir, true ); + } + + public static int getNextIDFromFile( File file ) + { + return getNextID( file, false ); + } + + private static int getNextID( File location, boolean directory ) + { + // Determine where to locate ID file + File lastidFile = null; + if( directory ) + { + location.mkdirs(); + lastidFile = new File( location, "lastid.txt" ); + } + else + { + location.getParentFile().mkdirs(); + lastidFile = location; + } + + // Try to determine the id + int id = 0; + if( !lastidFile.exists() ) + { + // If an ID file doesn't exist, determine it from the file structure + if( directory && location.exists() && location.isDirectory() ) + { + String[] contents = location.list(); + for( int i=0; i= 0 && y < world.getHeight() ) + { + TileEntity tileEntity = world.getTileEntity( pos ); + if( tileEntity != null && tileEntity instanceof IInventory ) + { + // Special case code for double chests + Block block = world.getBlockState( pos ).getBlock(); + if( block == Blocks.chest || block == Blocks.trapped_chest ) + { + // Check if it's a double chest, and return a combined inventory if so + if( world.getBlockState( pos.west() ).getBlock() == block ) + { + return new InventoryLargeChest( "Large chest", (ILockableContainer)world.getTileEntity( pos.west() ), (ILockableContainer)tileEntity ); + } + if( world.getBlockState( pos.east() ).getBlock() == block ) + { + return new InventoryLargeChest( "Large chest", (ILockableContainer)tileEntity, (ILockableContainer)world.getTileEntity( pos.east() ) ); + } + if( world.getBlockState( pos.north() ).getBlock() == block ) + { + return new InventoryLargeChest( "Large chest", (ILockableContainer)world.getTileEntity( pos.north() ), (ILockableContainer)tileEntity ); + } + if( world.getBlockState( pos.south() ).getBlock() == block ) + { + return new InventoryLargeChest( "Large chest", (ILockableContainer)tileEntity, (ILockableContainer)world.getTileEntity( pos.south() ) ); + } + } + + // Otherwise, get tile inventory + return (IInventory)tileEntity; + } + } + + // Look for entity with inventory + Vec3 vecStart = new Vec3( + pos.getX() + 0.5 + 0.6 * side.getFrontOffsetX(), + pos.getY() + 0.5 + 0.6 * side.getFrontOffsetY(), + pos.getZ() + 0.5 + 0.6 * side.getFrontOffsetZ() + ); + EnumFacing dir = side.getOpposite(); + Vec3 vecDir = new Vec3( + dir.getFrontOffsetX(), dir.getFrontOffsetY(), dir.getFrontOffsetZ() + ); + Pair hit = WorldUtil.rayTraceEntities( world, vecStart, vecDir, 1.1 ); + if( hit != null ) + { + Entity entity = hit.getKey(); + if( entity instanceof IInventory ) + { + return (IInventory) entity; + } + } + return null; + } + + // Methods for placing into inventories: + + public static ItemStack storeItems( ItemStack itemstack, IInventory inventory, int start, int range, int begin ) + { + int[] slots = makeSlotList( start, range, begin ); + return storeItems( itemstack, inventory, slots, null ); + } + + public static ItemStack storeItems( ItemStack itemstack, IInventory inventory, EnumFacing side ) + { + // Try ISidedInventory + if( inventory instanceof ISidedInventory ) + { + // Place into ISidedInventory + ISidedInventory sidedInventory = (ISidedInventory)inventory; + int[] slots = sidedInventory.getSlotsForFace( side ); + return storeItems( itemstack, inventory, slots, side ); + } + + // No ISidedInventory, store into any slot + int[] slots = makeSlotList( 0, inventory.getSizeInventory(), 0 ); // TODO: optimise this out? + return storeItems( itemstack, inventory, slots, side ); + } + + // Methods for taking out of inventories + + public static ItemStack takeItems( int count, IInventory inventory, int start, int range, int begin ) + { + int[] slots = makeSlotList( start, range, begin ); + return takeItems( count, inventory, slots, null ); + } + + public static ItemStack takeItems( int count, IInventory inventory, EnumFacing side ) + { + // Try ISidedInventory + if( inventory instanceof ISidedInventory ) + { + // Place into ISidedInventory + ISidedInventory sidedInventory = (ISidedInventory)inventory; + int[] slots = sidedInventory.getSlotsForFace( side ); + return takeItems( count, inventory, slots, side ); + } + + // No ISidedInventory, store into any slot + int[] slots = makeSlotList( 0, inventory.getSizeInventory(), 0 ); + return takeItems( count, inventory, slots, side ); + } + + // Private methods + + private static int[] makeSlotList( int start, int range, int begin ) + { + if( start < 0 || range == 0 ) + { + return null; + } + + int[] slots = new int[range]; + for( int n=0; n= remainder.stackSize ) + { + // Items fit completely in slot + inventory.setInventorySlotContents( slot, remainder ); + inventory.markDirty(); + return null; + } + else + { + // Items fit partially in slot + remainder = remainder.copy(); + inventory.setInventorySlotContents( slot, remainder.splitStack( space ) ); + } + } + else if( areItemsStackable( slotContents, remainder ) ) + { + // Slot is occupied, but matching + int space = Math.min( slotContents.getMaxStackSize(), inventory.getInventoryStackLimit() ) - slotContents.stackSize; + if( space >= remainder.stackSize ) + { + // Items fit completely in slot + slotContents.stackSize += remainder.stackSize; + inventory.setInventorySlotContents( slot, slotContents ); + inventory.markDirty(); + return null; + } + else if( space > 0 ) + { + // Items fit partially in slot + remainder = remainder.copy(); + remainder.stackSize -= space; + slotContents.stackSize += space; + inventory.setInventorySlotContents( slot, slotContents ); + } + } + } + } + + // If the output isn't the input, inform the change + if( remainder != stack ) + { + inventory.markDirty(); + } + return remainder; + } + + private static boolean canPlaceItemThroughFace( IInventory inventory, int slot, ItemStack itemstack, EnumFacing face ) + { + if( inventory.isItemValidForSlot( slot, itemstack ) ) + { + if( face != null && inventory instanceof ISidedInventory ) + { + ISidedInventory sided = (ISidedInventory)inventory; + return sided.canInsertItem( slot, itemstack, face ); + } + return true; + } + return false; + } + + private static ItemStack takeItems( int count, IInventory inventory, int[] slots, EnumFacing face ) + { + if( slots == null ) + { + return null; + } + + // Combine multiple stacks from inventory into one if necessary + ItemStack partialStack = null; + int countRemaining = count; + for( int n=0; n 0 ) + { + ItemStack stack = inventory.getStackInSlot( slot ); + if( stack != null && canTakeItemThroughFace( inventory, slot, stack, face ) ) + { + if( partialStack == null || areItemsStackable( stack, partialStack ) ) + { + // Found a matching thing + if( countRemaining >= stack.stackSize ) + { + // Eat the thing whole + inventory.setInventorySlotContents( slot, null ); + if( partialStack == null ) + { + partialStack = stack; + countRemaining = Math.min( countRemaining, partialStack.getItem().getItemStackLimit( partialStack ) ) - stack.stackSize; + } + else + { + partialStack.stackSize += stack.stackSize; + countRemaining -= stack.stackSize; + } + } + else + { + // Eat part of the thing + ItemStack splitStack = stack.splitStack( countRemaining ); + if( partialStack == null ) + { + partialStack = splitStack; + countRemaining = Math.min( countRemaining, partialStack.getItem().getItemStackLimit( partialStack ) ) - splitStack.stackSize; + } + else + { + partialStack.stackSize += splitStack.stackSize; + countRemaining -= splitStack.stackSize; + } + } + } + } + } + } + + // Return the final stack + if( partialStack != null ) + { + inventory.markDirty(); + return partialStack; + } + return null; + } + + private static boolean canTakeItemThroughFace( IInventory inventory, int slot, ItemStack itemstack, EnumFacing face ) + { + if( face != null && inventory instanceof ISidedInventory ) + { + ISidedInventory sided = (ISidedInventory)inventory; + return sided.canExtractItem( slot, itemstack, face ); + } + return true; + } +} diff --git a/src/main/java/dan200/computercraft/shared/util/NBTUtil.java b/src/main/java/dan200/computercraft/shared/util/NBTUtil.java new file mode 100644 index 0000000000..ea4a08884a --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/util/NBTUtil.java @@ -0,0 +1,141 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.util; + +import net.minecraft.nbt.*; +import net.minecraftforge.common.util.Constants; + +import java.util.HashMap; +import java.util.Map; + +public class NBTUtil +{ + private static NBTBase toNBTTag( Object object ) + { + if( object != null ) + { + if( object instanceof Boolean ) + { + boolean b = ((Boolean)object).booleanValue(); + return new NBTTagByte( b ? (byte)1 : (byte)0 ); + } + else if( object instanceof Number ) + { + Double d = ((Number)object).doubleValue(); + return new NBTTagDouble( d ); + } + else if( object instanceof String ) + { + String s = object.toString(); + return new NBTTagString( s ); + } + else if( object instanceof Map ) + { + Map m = (Map)object; + NBTTagCompound nbt = new NBTTagCompound(); + int i=0; + for( Map.Entry entry : m.entrySet() ) + { + NBTBase key = toNBTTag( entry.getKey() ); + NBTBase value = toNBTTag( entry.getKey() ); + if( key != null && value != null ) + { + nbt.setTag( "k" + Integer.toString( i ), key ); + nbt.setTag( "v" + Integer.toString( i ), value ); + ++i; + } + } + nbt.setInteger( "len", m.size() ); + return nbt; + } + } + return null; + } + + public static NBTTagCompound encodeObjects( Object[] objects ) + { + if( objects != null && objects.length > 0 ) + { + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setInteger( "len", objects.length ); + for( int i=0; i 0); + return b; + } + case Constants.NBT.TAG_DOUBLE: // Double + { + double d = ((NBTTagDouble)tag).getDouble(); + return d; + } + case Constants.NBT.TAG_STRING: // String + { + String s = ((NBTTagString)tag).getString(); + return s; + } + case Constants.NBT.TAG_COMPOUND: // Compound + { + NBTTagCompound c = (NBTTagCompound)tag; + int len = c.getInteger( "len" ); + Map map = new HashMap( len ); + for( int i=0; i 0 ) + { + Object[] objects = new Object[len]; + for( int i=0; i= 0 && y < world.getHeight() && !world.isRemote ) + { + return ComputerCraft.getPeripheralAt( world, pos, side ); + } + return null; + } +} diff --git a/src/main/java/dan200/computercraft/shared/util/RedstoneUtil.java b/src/main/java/dan200/computercraft/shared/util/RedstoneUtil.java new file mode 100644 index 0000000000..a89e82cb56 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/util/RedstoneUtil.java @@ -0,0 +1,94 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.util; + +import dan200.computercraft.ComputerCraft; +import net.minecraft.block.Block; +import net.minecraft.block.BlockRedstoneWire; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +public class RedstoneUtil +{ + private static Block getBlock( IBlockAccess world, BlockPos pos ) + { + if( pos.getY() >= 0 ) + { + return world.getBlockState( pos ).getBlock(); + } + return null; + } + + public static int getRedstoneOutput( World world, BlockPos pos, EnumFacing side ) + { + int power = 0; + Block block = getBlock( world, pos ); + if( block != null && block != Blocks.air ) + { + if( block == Blocks.redstone_wire ) + { + if( side != EnumFacing.UP ) + { + power = ((Integer)world.getBlockState( pos ).getValue( BlockRedstoneWire.POWER )).intValue(); + } + else + { + power = 0; + } + } + else if( block.canProvidePower() ) + { + power = block.getWeakPower( world, pos, world.getBlockState( pos ), side.getOpposite() ); + } + if( block.isNormalCube( world, pos ) ) + { + for( EnumFacing testSide : EnumFacing.VALUES ) + { + if( testSide != side ) + { + BlockPos testPos = pos.offset( testSide ); + Block neighbour = getBlock( world, testPos ); + if( neighbour != null && neighbour.canProvidePower() ) + { + power = Math.max( power, neighbour.getStrongPower( world, testPos, world.getBlockState( testPos ), testSide.getOpposite() ) ); + } + } + } + } + } + return power; + } + + public static int getBundledRedstoneOutput( World world, BlockPos pos, EnumFacing side ) + { + int signal = ComputerCraft.getBundledRedstoneOutput( world, pos, side ); + if( signal >= 0 ) + { + return signal; + } + return 0; + } + + public static void propogateRedstoneOutput( World world, BlockPos pos, EnumFacing side ) + { + // Propogate ordinary output + Block block = getBlock( world, pos ); + BlockPos neighbourPos = pos.offset( side ); + Block neighbour = getBlock( world, neighbourPos ); + if( neighbour != null && neighbour != Blocks.air ) + { + world.notifyBlockOfStateChange( neighbourPos, block ); + if( neighbour.isNormalCube( world, neighbourPos ) ) + { + world.notifyNeighborsOfStateExcept( neighbourPos, neighbour, side.getOpposite() ); + } + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/util/ReflectionUtil.java b/src/main/java/dan200/computercraft/shared/util/ReflectionUtil.java new file mode 100644 index 0000000000..758898d1bf --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/util/ReflectionUtil.java @@ -0,0 +1,227 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.util; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +public class ReflectionUtil +{ + public static Class getOptionalClass( String name ) + { + try + { + return Class.forName( name ); + } + catch( Exception e ) + { + // Ignore + } + return null; + } + + public static Class getOptionalInnerClass( Class enclosingClass, String name ) + { + if( enclosingClass != null ) + { + try + { + Class[] declaredClasses = enclosingClass.getDeclaredClasses(); + if( declaredClasses != null ) + { + for( int i=0; i T safeNew( Constructor constructor, Object[] arguments, Class resultClass ) + { + if( constructor != null ) + { + try + { + Object result = constructor.newInstance( arguments ); + if( result != null && resultClass.isInstance( result ) ) + { + return (T)result; + } + } + catch( Exception e ) + { + // Ignore + } + } + return null; + } + + public static boolean safeInstanceOf( Object object, Class clazz ) + { + if( clazz != null ) + { + return clazz.isInstance( object ); + } + return false; + } + + public static void safeInvoke( Method method, Object object, Object[] arguments ) + { + if( method != null ) + { + try + { + if( object == null || method.getClass().isInstance( object ) ) + { + method.invoke( object, arguments ); + } + } + catch( Exception e ) + { + // Ignore + } + } + } + + public static T safeInvoke( Method method, Object object, Object[] arguments, Class resultClass ) + { + if( method != null ) + { + try + { + if( (object == null && Modifier.isStatic( method.getModifiers() )) || + method.getDeclaringClass().isInstance( object ) ) + { + Object result = method.invoke( object, arguments ); + if( result != null && resultClass.isInstance( result ) ) + { + return (T)result; + } + } + } + catch( Exception e ) + { + // Ignore + } + } + return null; + } + + public static T safeGet( Field field, Object object, Class resultClass ) + { + if( field != null ) + { + try + { + if( (object == null && Modifier.isStatic( field.getModifiers() )) || + field.getDeclaringClass().isInstance( object ) ) + { + Object result = field.get( object ); + if( result != null && resultClass.isInstance( result ) ) + { + return (T)result; + } + } + } + catch( Exception e ) + { + // Ignore + } + } + return null; + } + + public static T safeSet( Field field, Object object, T value ) + { + if( field != null ) + { + try + { + if( object == null || field.getClass().isInstance( object ) ) + { + field.set( object, value ); + } + } + catch( Exception e ) + { + // Ignore + } + } + return null; + } +} diff --git a/src/main/java/dan200/computercraft/shared/util/WorldUtil.java b/src/main/java/dan200/computercraft/shared/util/WorldUtil.java new file mode 100644 index 0000000000..2f9a4bd92d --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/util/WorldUtil.java @@ -0,0 +1,167 @@ +/** + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.util; + +import net.minecraft.block.Block; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.item.ItemStack; +import net.minecraft.util.*; +import net.minecraft.world.World; +import org.apache.commons.lang3.tuple.Pair; + +import java.util.List; + +public class WorldUtil +{ + public static boolean isBlockInWorld( World world, BlockPos pos ) + { + return pos.getY() >= 0 && pos.getY() < world.getHeight(); + } + + public static boolean isLiquidBlock( World world, BlockPos pos ) + { + if( isBlockInWorld( world, pos ) ) + { + Block block = world.getBlockState( pos ).getBlock(); + if( block != null ) + { + return block.getMaterial().isLiquid(); + } + } + return false; + } + + public static BlockPos moveCoords( BlockPos pos, EnumFacing dir ) + { + return pos.offset( dir ); + } + + public static Pair rayTraceEntities( World world, Vec3 vecStart, Vec3 vecDir, double distance ) + { + Vec3 vecEnd = vecStart.addVector( vecDir.xCoord * distance, vecDir.yCoord * distance, vecDir.zCoord * distance ); + + // Raycast for blocks + MovingObjectPosition result = world.rayTraceBlocks( vecStart.addVector(0.0,0.0,0.0), vecEnd.addVector(0.0,0.0,0.0) ); + if( result != null && result.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK ) + { + distance = vecStart.distanceTo( result.hitVec ); + vecEnd = vecStart.addVector( vecDir.xCoord * distance, vecDir.yCoord * distance, vecDir.zCoord * distance ); + } + + // Check for entities + float xStretch = (Math.abs(vecDir.xCoord) > 0.25f) ? 0.0f : 1.0f; + float yStretch = (Math.abs(vecDir.yCoord) > 0.25f) ? 0.0f : 1.0f; + float zStretch = (Math.abs(vecDir.zCoord) > 0.25f) ? 0.0f : 1.0f; + AxisAlignedBB bigBox = new AxisAlignedBB( + Math.min(vecStart.xCoord, vecEnd.xCoord) - 0.375f * xStretch, + Math.min(vecStart.yCoord, vecEnd.yCoord) - 0.375f * yStretch, + Math.min(vecStart.zCoord, vecEnd.zCoord) - 0.375f * zStretch, + Math.max(vecStart.xCoord, vecEnd.xCoord) + 0.375f * xStretch, + Math.max(vecStart.yCoord, vecEnd.yCoord) + 0.375f * yStretch, + Math.max(vecStart.zCoord, vecEnd.zCoord) + 0.375f * zStretch + ); + + Entity closest = null; + double closestDist = 99.0; + List list = world.getEntitiesWithinAABBExcludingEntity( null, bigBox ); + for( int i=0; i> bits + end + + function bit32.band( m, n ) + if type(m) ~= "number" or type(n) ~= "number" then + error( "Expected number, number", 2 ) + end + return m & n + end + + function bit32.bnot( n ) + if type(n) ~= "number" then + error( "Expected number", 2 ) + end + return ~n + end + + function bit32.bor( m, n ) + if type(m) ~= "number" or type(n) ~= "number" then + error( "Expected number, number", 2 ) + end + return m | n + end + + function bit32.btest( m, n ) + if type(m) ~= "number" or type(n) ~= "number" then + error( "Expected number, number", 2 ) + end + return (m & n) ~= 0 + end + + function bit32.bxor( m, n ) + if type(m) ~= "number" or type(n) ~= "number" then + error( "Expected number, number", 2 ) + end + return m ~ n + end + + function bit32.lshift( n, bits ) + if type(n) ~= "number" or type(bits) ~= "number" then + error( "Expected number, number", 2 ) + end + return n << bits + end + + function bit32.rshift( n, bits ) + if type(n) ~= "number" or type(bits) ~= "number" then + error( "Expected number, number", 2 ) + end + return n >> bits + end + ]] )() +end + +if string.find( _HOST, "ComputerCraft" ) == 1 then + -- Prevent access to metatables or environments of strings, as these are global between all computers + local nativegetmetatable = getmetatable + local nativeerror = error + local nativetype = type + local string_metatable = nativegetmetatable("") + function getmetatable( t ) + local mt = nativegetmetatable( t ) + if mt == string_metatable then + nativeerror( "Attempt to access string metatable", 2 ) + else + return mt + end + end + if _VERSION == "Lua 5.1" and not _CC_DISABLE_LUA51_FEATURES then + local string_env = nativegetfenv(("").gsub) + function getfenv( env ) + if env == nil then + env = 2 + elseif nativetype( env ) == "number" and env > 0 then + env = env + 1 + end + local fenv = nativegetfenv(env) + if fenv == string_env then + --nativeerror( "Attempt to access string metatable", 2 ) + return nativegetfenv( 0 ) + else + return fenv + end + end + end +end + +-- Install lua parts of the os api +function os.version() + return "CraftOS 1.7" +end + +function os.pullEventRaw( sFilter ) + return coroutine.yield( sFilter ) +end + +function os.pullEvent( sFilter ) + local eventData = { os.pullEventRaw( sFilter ) } + if eventData[1] == "terminate" then + error( "Terminated", 0 ) + end + return table.unpack( eventData ) +end + +-- Install globals +function sleep( nTime ) + local timer = os.startTimer( nTime or 0 ) + repeat + local sEvent, param = os.pullEvent( "timer" ) + until param == timer +end + +function write( sText ) + local w,h = term.getSize() + local x,y = term.getCursorPos() + + local nLinesPrinted = 0 + local function newLine() + if y + 1 <= h then + term.setCursorPos(1, y + 1) + else + term.setCursorPos(1, h) + term.scroll(1) + end + x, y = term.getCursorPos() + nLinesPrinted = nLinesPrinted + 1 + end + + -- Print the line with proper word wrapping + while string.len(sText) > 0 do + local whitespace = string.match( sText, "^[ \t]+" ) + if whitespace then + -- Print whitespace + term.write( whitespace ) + x,y = term.getCursorPos() + sText = string.sub( sText, string.len(whitespace) + 1 ) + end + + local newline = string.match( sText, "^\n" ) + if newline then + -- Print newlines + newLine() + sText = string.sub( sText, 2 ) + end + + local text = string.match( sText, "^[^ \t\n]+" ) + if text then + sText = string.sub( sText, string.len(text) + 1 ) + if string.len(text) > w then + -- Print a multiline word + while string.len( text ) > 0 do + if x > w then + newLine() + end + term.write( text ) + text = string.sub( text, (w-x) + 2 ) + x,y = term.getCursorPos() + end + else + -- Print a word normally + if x + string.len(text) - 1 > w then + newLine() + end + term.write( text ) + x,y = term.getCursorPos() + end + end + end + + return nLinesPrinted +end + +function print( ... ) + local nLinesPrinted = 0 + local nLimit = select("#", ... ) + for n = 1, nLimit do + local s = tostring( select( n, ... ) ) + if n < nLimit then + s = s .. "\t" + end + nLinesPrinted = nLinesPrinted + write( s ) + end + nLinesPrinted = nLinesPrinted + write( "\n" ) + return nLinesPrinted +end + +function printError( ... ) + local oldColour + if term.isColour() then + oldColour = term.getTextColour() + term.setTextColour( colors.red ) + end + print( ... ) + if term.isColour() then + term.setTextColour( oldColour ) + end +end + +function read( _sReplaceChar, _tHistory, _fnComplete ) + term.setCursorBlink( true ) + + local sLine = "" + local nHistoryPos + local nPos = 0 + if _sReplaceChar then + _sReplaceChar = string.sub( _sReplaceChar, 1, 1 ) + end + + local tCompletions + local nCompletion + local function recomplete() + if _fnComplete and nPos == string.len(sLine) then + tCompletions = _fnComplete( sLine ) + if tCompletions and #tCompletions > 0 then + nCompletion = 1 + else + nCompletion = nil + end + else + tCompletions = nil + nCompletion = nil + end + end + + local function uncomplete() + tCompletions = nil + nCompletion = nil + end + + local w = term.getSize() + local sx = term.getCursorPos() + + local function redraw( _bClear ) + local nScroll = 0 + if sx + nPos >= w then + nScroll = (sx + nPos) - w + end + + local cx,cy = term.getCursorPos() + term.setCursorPos( sx, cy ) + local sReplace = (_bClear and " ") or _sReplaceChar + if sReplace then + term.write( string.rep( sReplace, math.max( string.len(sLine) - nScroll, 0 ) ) ) + else + term.write( string.sub( sLine, nScroll + 1 ) ) + end + + if nCompletion then + local sCompletion = tCompletions[ nCompletion ] + local oldText, oldBg + if not _bClear then + oldText = term.getTextColor() + oldBg = term.getBackgroundColor() + term.setTextColor( colors.white ) + term.setBackgroundColor( colors.gray ) + end + if sReplace then + term.write( string.rep( sReplace, string.len( sCompletion ) ) ) + else + term.write( sCompletion ) + end + if not _bClear then + term.setTextColor( oldText ) + term.setBackgroundColor( oldBg ) + end + end + + term.setCursorPos( sx + nPos - nScroll, cy ) + end + + local function clear() + redraw( true ) + end + + recomplete() + redraw() + + local function acceptCompletion() + if nCompletion then + -- Clear + clear() + + -- Find the common prefix of all the other suggestions which start with the same letter as the current one + local sCompletion = tCompletions[ nCompletion ] + sLine = sLine .. sCompletion + nPos = string.len( sLine ) + + -- Redraw + recomplete() + redraw() + end + end + while true do + local sEvent, param = os.pullEvent() + if sEvent == "char" then + -- Typed key + clear() + sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 ) + nPos = nPos + 1 + recomplete() + redraw() + + elseif sEvent == "paste" then + -- Pasted text + clear() + sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 ) + nPos = nPos + string.len( param ) + recomplete() + redraw() + + elseif sEvent == "key" then + if param == keys.enter then + -- Enter + if nCompletion then + clear() + uncomplete() + redraw() + end + break + + elseif param == keys.left then + -- Left + if nPos > 0 then + clear() + nPos = nPos - 1 + recomplete() + redraw() + end + + elseif param == keys.right then + -- Right + if nPos < string.len(sLine) then + -- Move right + clear() + nPos = nPos + 1 + recomplete() + redraw() + else + -- Accept autocomplete + acceptCompletion() + end + + elseif param == keys.up or param == keys.down then + -- Up or down + if nCompletion then + -- Cycle completions + clear() + if param == keys.up then + nCompletion = nCompletion - 1 + if nCompletion < 1 then + nCompletion = #tCompletions + end + elseif param == keys.down then + nCompletion = nCompletion + 1 + if nCompletion > #tCompletions then + nCompletion = 1 + end + end + redraw() + + elseif _tHistory then + -- Cycle history + clear() + if param == keys.up then + -- Up + if nHistoryPos == nil then + if #_tHistory > 0 then + nHistoryPos = #_tHistory + end + elseif nHistoryPos > 1 then + nHistoryPos = nHistoryPos - 1 + end + else + -- Down + if nHistoryPos == #_tHistory then + nHistoryPos = nil + elseif nHistoryPos ~= nil then + nHistoryPos = nHistoryPos + 1 + end + end + if nHistoryPos then + sLine = _tHistory[nHistoryPos] + nPos = string.len( sLine ) + else + sLine = "" + nPos = 0 + end + uncomplete() + redraw() + + end + + elseif param == keys.backspace then + -- Backspace + if nPos > 0 then + clear() + sLine = string.sub( sLine, 1, nPos - 1 ) .. string.sub( sLine, nPos + 1 ) + nPos = nPos - 1 + recomplete() + redraw() + end + + elseif param == keys.home then + -- Home + if nPos > 0 then + clear() + nPos = 0 + recomplete() + redraw() + end + + elseif param == keys.delete then + -- Delete + if nPos < string.len(sLine) then + clear() + sLine = string.sub( sLine, 1, nPos ) .. string.sub( sLine, nPos + 2 ) + recomplete() + redraw() + end + + elseif param == keys["end"] then + -- End + if nPos < string.len(sLine ) then + clear() + nPos = string.len(sLine) + recomplete() + redraw() + end + + elseif param == keys.tab then + -- Tab (accept autocomplete) + acceptCompletion() + + end + + elseif sEvent == "term_resize" then + -- Terminal resized + w = term.getSize() + redraw() + + end + end + + local cx, cy = term.getCursorPos() + term.setCursorBlink( false ) + term.setCursorPos( w + 1, cy ) + print() + + return sLine +end + +loadfile = function( _sFile, _tEnv ) + local file = fs.open( _sFile, "r" ) + if file then + local func, err = load( file.readAll(), fs.getName( _sFile ), "t", _tEnv ) + file.close() + return func, err + end + return nil, "File not found" +end + +dofile = function( _sFile ) + local fnFile, e = loadfile( _sFile, _G ) + if fnFile then + return fnFile() + else + error( e, 2 ) + end +end + +-- Install the rest of the OS api +function os.run( _tEnv, _sPath, ... ) + local tArgs = { ... } + local tEnv = _tEnv + setmetatable( tEnv, { __index = _G } ) + local fnFile, err = loadfile( _sPath, tEnv ) + if fnFile then + local ok, err = pcall( function() + fnFile( table.unpack( tArgs ) ) + end ) + if not ok then + if err and err ~= "" then + printError( err ) + end + return false + end + return true + end + if err and err ~= "" then + printError( err ) + end + return false +end + +local tAPIsLoading = {} +function os.loadAPI( _sPath ) + local sName = fs.getName( _sPath ) + if tAPIsLoading[sName] == true then + printError( "API "..sName.." is already being loaded" ) + return false + end + tAPIsLoading[sName] = true + + local tEnv = {} + setmetatable( tEnv, { __index = _G } ) + local fnAPI, err = loadfile( _sPath, tEnv ) + if fnAPI then + local ok, err = pcall( fnAPI ) + if not ok then + printError( err ) + tAPIsLoading[sName] = nil + return false + end + else + printError( err ) + tAPIsLoading[sName] = nil + return false + end + + local tAPI = {} + for k,v in pairs( tEnv ) do + if k ~= "_ENV" then + tAPI[k] = v + end + end + + _G[sName] = tAPI + tAPIsLoading[sName] = nil + return true +end + +function os.unloadAPI( _sName ) + if _sName ~= "_G" and type(_G[_sName]) == "table" then + _G[_sName] = nil + end +end + +function os.sleep( nTime ) + sleep( nTime ) +end + +local nativeShutdown = os.shutdown +function os.shutdown() + nativeShutdown() + while true do + coroutine.yield() + end +end + +local nativeReboot = os.reboot +function os.reboot() + nativeReboot() + while true do + coroutine.yield() + end +end + +-- Install the lua part of the HTTP api (if enabled) +if http then + local nativeHTTPRequest = http.request + + local function wrapRequest( _url, _post, _headers ) + local ok, err = nativeHTTPRequest( _url, _post, _headers ) + if ok then + while true do + local event, param1, param2 = os.pullEvent() + if event == "http_success" and param1 == _url then + return param2 + elseif event == "http_failure" and param1 == _url then + return nil, param2 + end + end + end + return nil, err + end + + http.get = function( _url, _headers ) + return wrapRequest( _url, nil, _headers ) + end + + http.post = function( _url, _post, _headers ) + return wrapRequest( _url, _post or "", _headers ) + end + + http.request = function( _url, _post, _headers ) + local ok, err = nativeHTTPRequest( _url, _post, _headers ) + if not ok then + os.queueEvent( "http_failure", _url, err ) + end + return ok, err + end +end + +-- Install the lua part of the FS api +local tEmpty = {} +function fs.complete( sPath, sLocation, bIncludeFiles, bIncludeDirs ) + bIncludeFiles = (bIncludeFiles ~= false) + bIncludeDirs = (bIncludeDirs ~= false) + local sDir = sLocation + local nStart = 1 + local nSlash = string.find( sPath, "[/\\]", nStart ) + if nSlash == 1 then + sDir = "" + nStart = 2 + end + local sName + while not sName do + local nSlash = string.find( sPath, "[/\\]", nStart ) + if nSlash then + local sPart = string.sub( sPath, nStart, nSlash - 1 ) + sDir = fs.combine( sDir, sPart ) + nStart = nSlash + 1 + else + sName = string.sub( sPath, nStart ) + end + end + + if fs.isDir( sDir ) then + local tResults = {} + if bIncludeDirs and sPath == "" then + table.insert( tResults, "." ) + end + if sDir ~= "" then + if sPath == "" then + table.insert( tResults, (bIncludeDirs and "..") or "../" ) + elseif sPath == "." then + table.insert( tResults, (bIncludeDirs and ".") or "./" ) + end + end + local tFiles = fs.list( sDir ) + for n=1,#tFiles do + local sFile = tFiles[n] + if #sFile >= #sName and string.sub( sFile, 1, #sName ) == sName then + local bIsDir = fs.isDir( fs.combine( sDir, sFile ) ) + local sResult = string.sub( sFile, #sName + 1 ) + if bIsDir then + table.insert( tResults, sResult .. "/" ) + if bIncludeDirs and #sResult > 0 then + table.insert( tResults, sResult ) + end + else + if bIncludeFiles and #sResult > 0 then + table.insert( tResults, sResult ) + end + end + end + end + return tResults + end + return tEmpty +end + +-- Load APIs +local bAPIError = false +local tApis = fs.list( "rom/apis" ) +for n,sFile in ipairs( tApis ) do + if string.sub( sFile, 1, 1 ) ~= "." then + local sPath = fs.combine( "rom/apis", sFile ) + if not fs.isDir( sPath ) then + if not os.loadAPI( sPath ) then + bAPIError = true + end + end + end +end + +if turtle then + -- Load turtle APIs + local tApis = fs.list( "rom/apis/turtle" ) + for n,sFile in ipairs( tApis ) do + if string.sub( sFile, 1, 1 ) ~= "." then + local sPath = fs.combine( "rom/apis/turtle", sFile ) + if not fs.isDir( sPath ) then + if not os.loadAPI( sPath ) then + bAPIError = true + end + end + end + end +end + +if pocket and fs.isDir( "rom/apis/pocket" ) then + -- Load pocket APIs + local tApis = fs.list( "rom/apis/pocket" ) + for n,sFile in ipairs( tApis ) do + if string.sub( sFile, 1, 1 ) ~= "." then + local sPath = fs.combine( "rom/apis/pocket", sFile ) + if not fs.isDir( sPath ) then + if not os.loadAPI( sPath ) then + bAPIError = true + end + end + end + end +end + +if commands and fs.isDir( "rom/apis/command" ) then + -- Load command APIs + if os.loadAPI( "rom/apis/command/commands" ) then + -- Add a special case-insensitive metatable to the commands api + local tCaseInsensitiveMetatable = { + __index = function( table, key ) + local value = rawget( table, key ) + if value ~= nil then + return value + end + if type(key) == "string" then + local value = rawget( table, string.lower(key) ) + if value ~= nil then + return value + end + end + return nil + end + } + setmetatable( commands, tCaseInsensitiveMetatable ) + setmetatable( commands.async, tCaseInsensitiveMetatable ) + + -- Add global "exec" function + exec = commands.exec + else + bAPIError = true + end +end + +if bAPIError then + print( "Press any key to continue" ) + os.pullEvent( "key" ) + term.clear() + term.setCursorPos( 1,1 ) +end + +-- Set default settings +settings.set( "shell.allow_startup", true ) +settings.set( "shell.allow_disk_startup", (commands == nil) ) +settings.set( "shell.autocomplete", true ) +settings.set( "edit.autocomplete", true ) +settings.set( "lua.autocomplete", true ) +settings.set( "list.show_hidden", false ) +if term.isColour() then + settings.set( "bios.use_multishell", true ) +end +if _CC_DEFAULT_SETTINGS then + for sPair in string.gmatch( _CC_DEFAULT_SETTINGS, "[^,]+" ) do + local sName, sValue = string.match( sPair, "([^=]*)=(.*)" ) + if sName and sValue then + local value + if sValue == "true" then + value = true + elseif sValue == "false" then + value = false + elseif sValue == "nil" then + value = nil + elseif tonumber(sValue) then + value = tonumber(sValue) + else + value = sValue + end + if value ~= nil then + settings.set( sName, value ) + else + settings.unset( sName ) + end + end + end +end + +-- Load user settings +if fs.exists( ".settings" ) then + settings.load( ".settings" ) +end + +-- Run the shell +local ok, err = pcall( function() + parallel.waitForAny( + function() + local sShell + if term.isColour() and settings.get( "bios.use_multishell" ) then + sShell = "rom/programs/advanced/multishell" + else + sShell = "rom/programs/shell" + end + os.run( {}, sShell ) + os.run( {}, "rom/programs/shutdown" ) + end, + function() + rednet.run() + end ) +end ) + +-- If the shell errored, let the user read it. +term.redirect( term.native() ) +if not ok then + printError( err ) + pcall( function() + term.setCursorBlink( false ) + print( "Press any key to continue" ) + os.pullEvent( "key" ) + end ) +end + +-- End +os.shutdown() diff --git a/src/main/resources/assets/computercraft/lua/rom/apis/colors b/src/main/resources/assets/computercraft/lua/rom/apis/colors new file mode 100644 index 0000000000..94bc3c2a56 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/apis/colors @@ -0,0 +1,37 @@ +-- Colors +white = 1 +orange = 2 +magenta = 4 +lightBlue = 8 +yellow = 16 +lime = 32 +pink = 64 +gray = 128 +lightGray = 256 +cyan = 512 +purple = 1024 +blue = 2048 +brown = 4096 +green = 8192 +red = 16384 +black = 32768 + +function combine( ... ) + local r = 0 + for n,c in ipairs( { ... } ) do + r = bit32.bor(r,c) + end + return r +end + +function subtract( colors, ... ) + local r = colors + for n,c in ipairs( { ... } ) do + r = bit32.band(r, bit32.bnot(c)) + end + return r +end + +function test( colors, color ) + return ((bit32.band(colors, color)) == color) +end diff --git a/src/main/resources/assets/computercraft/lua/rom/apis/colours b/src/main/resources/assets/computercraft/lua/rom/apis/colours new file mode 100644 index 0000000000..59202ebc56 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/apis/colours @@ -0,0 +1,11 @@ +-- Colours (for lovers of british spelling) +local colours = _ENV +for k,v in pairs(colors) do + colours[k] = v +end + +colours.grey = colors.gray +colours.gray = nil + +colours.lightGrey = colors.lightGray +colours.lightGray = nil diff --git a/src/main/resources/assets/computercraft/lua/rom/apis/command/commands b/src/main/resources/assets/computercraft/lua/rom/apis/command/commands new file mode 100644 index 0000000000..7911736926 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/apis/command/commands @@ -0,0 +1,46 @@ + +if not commands then + error( "Cannot load command API on normal computer", 2 ) +end +native = commands.native or commands + +local function collapseArgs( errorDepth, bJSONIsNBT, arg1, ... ) + if arg1 ~= nil then + if type(arg1) == "boolean" or type(arg1) == "number" or type(arg1) == "string" then + return tostring(arg1) .. " " .. collapseArgs( errorDepth + 1, bJSONIsNBT, ... ) + elseif type(arg1) == "table" then + return textutils.serialiseJSON( arg1, bJSONIsNBT ) .. " " .. collapseArgs( errorDepth + 1, bJSONIsNBT, ... ) + else + error( "Expected string, number, boolean or table", errorDepth ) + end + end + return "" +end + +-- Put native functions into the environment +local env = _ENV +for k,v in pairs( native ) do + env[k] = v +end + +-- Create wrapper functions for all the commands +local tAsync = {} +local tNonNBTJSONCommands = { + [ "tellraw" ] = true, + [ "title" ] = true +} +local tCommands = native.list() +for n,sCommandName in ipairs(tCommands) do + if env[ sCommandName ] == nil then + local bJSONIsNBT = (tNonNBTJSONCommands[ sCommandName ] == nil) + env[ sCommandName ] = function( ... ) + local sCommand = sCommandName .. " " .. collapseArgs( 3, bJSONIsNBT, ... ) + return native.exec( sCommand ) + end + tAsync[ sCommandName ] = function( ... ) + local sCommand = sCommandName .. " " .. collapseArgs( 3, bJSONIsNBT, ... ) + return native.execAsync( sCommand ) + end + end +end +env.async = tAsync diff --git a/src/main/resources/assets/computercraft/lua/rom/apis/disk b/src/main/resources/assets/computercraft/lua/rom/apis/disk new file mode 100644 index 0000000000..eda13773fe --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/apis/disk @@ -0,0 +1,84 @@ + +local function isDrive( name ) + return peripheral.getType( name ) == "drive" +end + +function isPresent( name ) + if isDrive( name ) then + return peripheral.call( name, "isDiskPresent" ) + end + return false +end + +function getLabel( name ) + if isDrive( name ) then + return peripheral.call( name, "getDiskLabel" ) + end + return nil +end + +function setLabel( name, label ) + if isDrive( name ) then + peripheral.call( name, "setDiskLabel", label ) + end +end + +function hasData( name ) + if isDrive( name ) then + return peripheral.call( name, "hasData" ) + end + return false +end + +function getMountPath( name ) + if isDrive( name ) then + return peripheral.call( name, "getMountPath" ) + end + return nil +end + +function hasAudio( name ) + if isDrive( name ) then + return peripheral.call( name, "hasAudio" ) + end + return false +end + +function getAudioTitle( name ) + if isDrive( name ) then + return peripheral.call( name, "getAudioTitle" ) + end + return nil +end + +function playAudio( name ) + if isDrive( name ) then + peripheral.call( name, "playAudio" ) + end +end + +function stopAudio( name ) + if not name then + for n,sName in ipairs( peripheral.getNames() ) do + stopAudio( sName ) + end + else + if isDrive( name ) then + peripheral.call( name, "stopAudio" ) + end + end +end + +function eject( name ) + if isDrive( name ) then + peripheral.call( name, "ejectDisk" ) + end +end + +function getID( name ) + if isDrive( name ) then + return peripheral.call( name, "getDiskID" ) + end + return nil +end + diff --git a/src/main/resources/assets/computercraft/lua/rom/apis/gps b/src/main/resources/assets/computercraft/lua/rom/apis/gps new file mode 100644 index 0000000000..9f7cb5fd0f --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/apis/gps @@ -0,0 +1,162 @@ + +CHANNEL_GPS = 65534 + +local function trilaterate( A, B, C ) + local a2b = B.vPosition - A.vPosition + local a2c = C.vPosition - A.vPosition + + if math.abs( a2b:normalize():dot( a2c:normalize() ) ) > 0.999 then + return nil + end + + local d = a2b:length() + local ex = a2b:normalize( ) + local i = ex:dot( a2c ) + local ey = (a2c - (ex * i)):normalize() + local j = ey:dot( a2c ) + local ez = ex:cross( ey ) + + local r1 = A.nDistance + local r2 = B.nDistance + local r3 = C.nDistance + + local x = (r1*r1 - r2*r2 + d*d) / (2*d) + local y = (r1*r1 - r3*r3 - x*x + (x-i)*(x-i) + j*j) / (2*j) + + local result = A.vPosition + (ex * x) + (ey * y) + + local zSquared = r1*r1 - x*x - y*y + if zSquared > 0 then + local z = math.sqrt( zSquared ) + local result1 = result + (ez * z) + local result2 = result - (ez * z) + + local rounded1, rounded2 = result1:round( 0.01 ), result2:round( 0.01 ) + if rounded1.x ~= rounded2.x or rounded1.y ~= rounded2.y or rounded1.z ~= rounded2.z then + return rounded1, rounded2 + else + return rounded1 + end + end + return result:round( 0.01 ) + +end + +local function narrow( p1, p2, fix ) + local dist1 = math.abs( (p1 - fix.vPosition):length() - fix.nDistance ) + local dist2 = math.abs( (p2 - fix.vPosition):length() - fix.nDistance ) + + if math.abs(dist1 - dist2) < 0.01 then + return p1, p2 + elseif dist1 < dist2 then + return p1:round( 0.01 ) + else + return p2:round( 0.01 ) + end +end + +function locate( _nTimeout, _bDebug ) + -- Let command computers use their magic fourth-wall-breaking special abilities + if commands then + return commands.getBlockPosition() + end + + -- Find a modem + local sModemSide = nil + for n,sSide in ipairs( rs.getSides() ) do + if peripheral.getType( sSide ) == "modem" and peripheral.call( sSide, "isWireless" ) then + sModemSide = sSide + break + end + end + + if sModemSide == nil then + if _bDebug then + print( "No wireless modem attached" ) + end + return nil + end + + if _bDebug then + print( "Finding position..." ) + end + + -- Open a channel + local modem = peripheral.wrap( sModemSide ) + local bCloseChannel = false + if not modem.isOpen( os.getComputerID() ) then + modem.open( os.getComputerID() ) + bCloseChannel = true + end + + -- Send a ping to listening GPS hosts + modem.transmit( CHANNEL_GPS, os.getComputerID(), "PING" ) + + -- Wait for the responses + local tFixes = {} + local pos1, pos2 = nil, nil + local timeout = os.startTimer( _nTimeout or 2 ) + while true do + local e, p1, p2, p3, p4, p5 = os.pullEvent() + if e == "modem_message" then + -- We received a reply from a modem + local sSide, sChannel, sReplyChannel, tMessage, nDistance = p1, p2, p3, p4, p5 + if sSide == sModemSide and sChannel == os.getComputerID() and sReplyChannel == CHANNEL_GPS and nDistance then + -- Received the correct message from the correct modem: use it to determine position + if type(tMessage) == "table" and #tMessage == 3 then + local tFix = { vPosition = vector.new( tMessage[1], tMessage[2], tMessage[3] ), nDistance = nDistance } + if _bDebug then + print( tFix.nDistance.." metres from "..tostring( tFix.vPosition ) ) + end + if tFix.nDistance == 0 then + pos1, pos2 = tFix.vPosition, nil + else + table.insert( tFixes, tFix ) + if #tFixes >= 3 then + if not pos1 then + pos1, pos2 = trilaterate( tFixes[1], tFixes[2], tFixes[#tFixes] ) + else + pos1, pos2 = narrow( pos1, pos2, tFixes[#tFixes] ) + end + end + end + if pos1 and not pos2 then + break + end + end + end + + elseif e == "timer" then + -- We received a timeout + local timer = p1 + if timer == timeout then + break + end + + end + end + + -- Close the channel, if we opened one + if bCloseChannel then + modem.close( os.getComputerID() ) + end + + -- Return the response + if pos1 and pos2 then + if _bDebug then + print( "Ambiguous position" ) + print( "Could be "..pos1.x..","..pos1.y..","..pos1.z.." or "..pos2.x..","..pos2.y..","..pos2.z ) + end + return nil + elseif pos1 then + if _bDebug then + print( "Position is "..pos1.x..","..pos1.y..","..pos1.z ) + end + return pos1.x, pos1.y, pos1.z + else + if _bDebug then + print( "Could not determine position" ) + end + return nil + end +end diff --git a/src/main/resources/assets/computercraft/lua/rom/apis/help b/src/main/resources/assets/computercraft/lua/rom/apis/help new file mode 100644 index 0000000000..65fc910e0c --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/apis/help @@ -0,0 +1,66 @@ + +local sPath = "/rom/help" + +function path() + return sPath +end + +function setPath( _sPath ) + sPath = _sPath +end + +function lookup( _sTopic ) + -- Look on the path variable + for sPath in string.gmatch(sPath, "[^:]+") do + sPath = fs.combine( sPath, _sTopic ) + if fs.exists( sPath ) and not fs.isDir( sPath ) then + return sPath + end + end + + -- Not found + return nil +end + +function topics() + -- Add index + local tItems = { + [ "index" ] = true + } + + -- Add topics from the path + for sPath in string.gmatch(sPath, "[^:]+") do + if fs.isDir( sPath ) then + local tList = fs.list( sPath ) + for n,sFile in pairs( tList ) do + if string.sub( sFile, 1, 1 ) ~= "." then + if not fs.isDir( fs.combine( sPath, sFile ) ) then + tItems[ sFile ] = true + end + end + end + end + end + + -- Sort and return + local tItemList = {} + for sItem, b in pairs( tItems ) do + table.insert( tItemList, sItem ) + end + table.sort( tItemList ) + return tItemList +end + +function completeTopic( sText ) + local tTopics = topics() + local tResults = {} + for n=1,#tTopics do + local sTopic = tTopics[n] + if #sTopic > #sText and string.sub( sTopic, 1, #sText ) == sText then + table.insert( tResults, string.sub( sTopic, #sText + 1 ) ) + end + end + return tResults +end + + diff --git a/src/main/resources/assets/computercraft/lua/rom/apis/io b/src/main/resources/assets/computercraft/lua/rom/apis/io new file mode 100644 index 0000000000..2d503fbf05 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/apis/io @@ -0,0 +1,182 @@ +-- Definition for the IO API + +local g_defaultInput = { + bFileHandle = true, + bClosed = false, + close = function( self ) + end, + read = function( self, _sFormat ) + if _sFormat and _sFormat ~= "*l" then + error( "Unsupported format" ) + end + return _G.read() + end, + lines = function( self ) + return function() + return _G.read() + end + end, +} + +local g_defaultOutput = { + bFileHandle = true, + bClosed = false, + close = function( self ) + end, + write = function( self, _sText ) + _G.write( _sText ) + end, + flush = function( self ) + end, +} + +local g_currentInput = g_defaultInput +local g_currentOutput = g_defaultOutput + +function close( _file ) + (_file or g_currentOutput):close() +end + +function flush() + g_currentOutput:flush() +end + +function input( _arg ) + if _G.type( _arg ) == "string" then + g_currentInput = open( _arg, "r" ) + elseif _G.type( _arg ) == "table" then + g_currentInput = _arg + elseif _G.type( _arg ) == "nil" then + return g_currentInput + else + error( "Expected file name or file handle" ) + end +end + +function lines( _sFileName ) + if _sFileName then + return open( _sFileName, "r" ):lines() + else + return g_currentInput:lines() + end +end + +function open( _sPath, _sMode ) + local sMode = _sMode or "r" + local file = fs.open( _sPath, sMode ) + if not file then + return nil + end + + if sMode == "r"then + return { + bFileHandle = true, + bClosed = false, + close = function( self ) + file.close() + self.bClosed = true + end, + read = function( self, _sFormat ) + local sFormat = _sFormat or "*l" + if sFormat == "*l" then + return file.readLine() + elseif sFormat == "*a" then + return file.readAll() + else + error( "Unsupported format" ) + end + return nil + end, + lines = function( self ) + return function() + local sLine = file.readLine() + if sLine == nil then + file.close() + self.bClosed = true + end + return sLine + end + end, + } + elseif sMode == "w" or sMode == "a" then + return { + bFileHandle = true, + bClosed = false, + close = function( self ) + file.close() + self.bClosed = true + end, + write = function( self, _sText ) + file.write( _sText ) + end, + flush = function( self ) + file.flush() + end, + } + + elseif sMode == "rb" then + return { + bFileHandle = true, + bClosed = false, + close = function( self ) + file.close() + self.bClosed = true + end, + read = function( self ) + return file.read() + end, + } + + elseif sMode == "wb" or sMode == "ab" then + return { + bFileHandle = true, + bClosed = false, + close = function( self ) + file.close() + self.bClosed = true + end, + write = function( self, _number ) + file.write( _number ) + end, + flush = function( self ) + file.flush() + end, + } + + else + file.close() + error( "Unsupported mode" ) + + end +end + +function output( _arg ) + if _G.type( _arg ) == "string" then + g_currentOutput = open( _arg, "w" ) + elseif _G.type( _arg ) == "table" then + g_currentOutput = _arg + elseif _G.type( _arg ) == "nil" then + return g_currentOutput + else + error( "Expected file name or file handle" ) + end +end + +function read( ... ) + return input():read( ... ) +end + +function type( _handle ) + if _G.type( _handle ) == "table" and _handle.bFileHandle == true then + if _handle.bClosed then + return "closed file" + else + return "file" + end + end + return nil +end + +function write( ... ) + return output():write( ... ) +end diff --git a/src/main/resources/assets/computercraft/lua/rom/apis/keys b/src/main/resources/assets/computercraft/lua/rom/apis/keys new file mode 100644 index 0000000000..98da2a4e05 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/apis/keys @@ -0,0 +1,59 @@ + +-- Minecraft key code bindings +-- See http://www.minecraftwiki.net/wiki/Key_codes for more info + +local tKeys = { + nil, "one", "two", "three", "four", -- 1 + "five", "six", "seven", "eight", "nine", -- 6 + "zero", "minus", "equals", "backspace","tab", -- 11 + "q", "w", "e", "r", "t", -- 16 + "y", "u", "i", "o", "p", -- 21 + "leftBracket","rightBracket","enter","leftCtrl","a", -- 26 + "s", "d", "f", "g", "h", -- 31 + "j", "k", "l", "semiColon","apostrophe", -- 36 + "grave", "leftShift","backslash","z", "x", -- 41 + "c", "v", "b", "n", "m", -- 46 + "comma", "period", "slash", "rightShift","multiply", -- 51 + "leftAlt", "space", "capsLock", "f1", "f2", -- 56 + "f3", "f4", "f5", "f6", "f7", -- 61 + "f8", "f9", "f10", "numLock", "scollLock", -- 66 + "numPad7", "numPad8", "numPad9", "numPadSubtract","numPad4", -- 71 + "numPad5", "numPad6", "numPadAdd","numPad1", "numPad2", -- 76 + "numPad3", "numPad0", "numPadDecimal",nil, nil, -- 81 + nil, "f11", "f12", nil, nil, -- 86 + nil, nil, nil, nil, nil, -- 91 + nil, nil, nil, nil, "f13", -- 96 + "f14", "f15", nil, nil, nil, -- 101 + nil, nil, nil, nil, nil, -- 106 + nil, "kana", nil, nil, nil, -- 111 + nil, nil, nil, nil, nil, -- 116 + "convert", nil, "noconvert",nil, "yen", -- 121 + nil, nil, nil, nil, nil, -- 126 + nil, nil, nil, nil, nil, -- 131 + nil, nil, nil, nil, nil, -- 136 + "numPadEquals",nil, nil, "cimcumflex","at", -- 141 + "colon", "underscore","kanji", "stop", "ax", -- 146 + nil, nil, nil, nil, nil, -- 151 + "numPadEnter","rightCtrl",nil, nil, nil, -- 156 + nil, nil, nil, nil, nil, -- 161 + nil, nil, nil, nil, nil, -- 166 + nil, nil, nil, nil, nil, -- 171 + nil, nil, nil, "numPadComma",nil, -- 176 + "numPadDivide",nil, nil, "rightAlt", nil, -- 181 + nil, nil, nil, nil, nil, -- 186 + nil, nil, nil, nil, nil, -- 191 + nil, "pause", nil, "home", "up", -- 196 + "pageUp", nil, "left", nil, "right", -- 201 + nil, "end", "down", "pageDown", "insert", -- 206 + "delete" -- 211 +} + +local keys = _ENV +for nKey, sKey in pairs( tKeys ) do + keys[sKey] = nKey +end +keys["return"] = keys.enter + +function getName( _nKey ) + return tKeys[ _nKey ] +end diff --git a/src/main/resources/assets/computercraft/lua/rom/apis/paintutils b/src/main/resources/assets/computercraft/lua/rom/apis/paintutils new file mode 100644 index 0000000000..544ce3568b --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/apis/paintutils @@ -0,0 +1,200 @@ + +local function drawPixelInternal( xPos, yPos ) + term.setCursorPos( xPos, yPos ) + term.write(" ") +end + +local tColourLookup = {} +for n=1,16 do + tColourLookup[ string.byte( "0123456789abcdef",n,n ) ] = 2^(n-1) +end + +function loadImage( sPath ) + if type( sPath ) ~= "string" then + error( "Expected path", 2 ) + end + + local tImage = {} + if fs.exists( sPath ) then + local file = io.open(sPath, "r" ) + local sLine = file:read() + while sLine do + local tLine = {} + for x=1,sLine:len() do + tLine[x] = tColourLookup[ string.byte(sLine,x,x) ] or 0 + end + table.insert( tImage, tLine ) + sLine = file:read() + end + file:close() + return tImage + end + return nil +end + +function drawPixel( xPos, yPos, nColour ) + if type( xPos ) ~= "number" or type( yPos ) ~= "number" or (nColour ~= nil and type( nColour ) ~= "number") then + error( "Expected x, y, colour", 2 ) + end + if nColour then + term.setBackgroundColor( nColour ) + end + drawPixelInternal( xPos, yPos ) +end + +function drawLine( startX, startY, endX, endY, nColour ) + if type( startX ) ~= "number" or type( startX ) ~= "number" or + type( endX ) ~= "number" or type( endY ) ~= "number" or + (nColour ~= nil and type( nColour ) ~= "number") then + error( "Expected startX, startY, endX, endY, colour", 2 ) + end + + startX = math.floor(startX) + startY = math.floor(startY) + endX = math.floor(endX) + endY = math.floor(endY) + + if nColour then + term.setBackgroundColor( nColour ) + end + if startX == endX and startY == endY then + drawPixelInternal( startX, startY ) + return + end + + local minX = math.min( startX, endX ) + if minX == startX then + minY = startY + maxX = endX + maxY = endY + else + minY = endY + maxX = startX + maxY = startY + end + + -- TODO: clip to screen rectangle? + + local xDiff = maxX - minX + local yDiff = maxY - minY + + if xDiff > math.abs(yDiff) then + local y = minY + local dy = yDiff / xDiff + for x=minX,maxX do + drawPixelInternal( x, math.floor( y + 0.5 ) ) + y = y + dy + end + else + local x = minX + local dx = xDiff / yDiff + if maxY >= minY then + for y=minY,maxY do + drawPixelInternal( math.floor( x + 0.5 ), y ) + x = x + dx + end + else + for y=minY,maxY,-1 do + drawPixelInternal( math.floor( x + 0.5 ), y ) + x = x - dx + end + end + end +end + +function drawBox( startX, startY, endX, endY, nColour ) + if type( startX ) ~= "number" or type( startX ) ~= "number" or + type( endX ) ~= "number" or type( endY ) ~= "number" or + (nColour ~= nil and type( nColour ) ~= "number") then + error( "Expected startX, startY, endX, endY, colour", 2 ) + end + + startX = math.floor(startX) + startY = math.floor(startY) + endX = math.floor(endX) + endY = math.floor(endY) + + if nColour then + term.setBackgroundColor( nColour ) + end + if startX == endX and startY == endY then + drawPixelInternal( startX, startY ) + return + end + + local minX = math.min( startX, endX ) + if minX == startX then + minY = startY + maxX = endX + maxY = endY + else + minY = endY + maxX = startX + maxY = startY + end + + for x=minX,maxX do + drawPixelInternal( x, minY ) + drawPixelInternal( x, maxY ) + end + + if (maxY - minY) >= 2 then + for y=(minY+1),(maxY-1) do + drawPixelInternal( minX, y ) + drawPixelInternal( maxX, y ) + end + end +end + +function drawFilledBox( startX, startY, endX, endY, nColour ) + if type( startX ) ~= "number" or type( startX ) ~= "number" or + type( endX ) ~= "number" or type( endY ) ~= "number" or + (nColour ~= nil and type( nColour ) ~= "number") then + error( "Expected startX, startY, endX, endY, colour", 2 ) + end + + startX = math.floor(startX) + startY = math.floor(startY) + endX = math.floor(endX) + endY = math.floor(endY) + + if nColour then + term.setBackgroundColor( nColour ) + end + if startX == endX and startY == endY then + drawPixelInternal( startX, startY ) + return + end + + local minX = math.min( startX, endX ) + if minX == startX then + minY = startY + maxX = endX + maxY = endY + else + minY = endY + maxX = startX + maxY = startY + end + + for x=minX,maxX do + for y=minY,maxY do + drawPixelInternal( x, y ) + end + end +end + +function drawImage( tImage, xPos, yPos ) + if type( tImage ) ~= "table" or type( xPos ) ~= "number" or type( yPos ) ~= "number" then + error( "Expected image, x, y", 2 ) + end + for y=1,#tImage do + local tLine = tImage[y] + for x=1,#tLine do + if tLine[x] > 0 then + term.setBackgroundColor( tLine[x] ) + drawPixelInternal( x + xPos - 1, y + yPos - 1 ) + end + end + end +end diff --git a/src/main/resources/assets/computercraft/lua/rom/apis/parallel b/src/main/resources/assets/computercraft/lua/rom/apis/parallel new file mode 100644 index 0000000000..db63a3ec58 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/apis/parallel @@ -0,0 +1,61 @@ + +local function create( first, ... ) + if first ~= nil then + if type( first ) ~= "function" then + error( "Expected function, got "..type( first ), 3 ) + end + return coroutine.create(first), create( ... ) + end + return nil +end + +local function runUntilLimit( _routines, _limit ) + local count = #_routines + local living = count + + local tFilters = {} + local eventData = {} + while true do + for n=1,count do + local r = _routines[n] + if r then + if tFilters[r] == nil or tFilters[r] == eventData[1] or eventData[1] == "terminate" then + local ok, param = coroutine.resume( r, table.unpack(eventData) ) + if not ok then + error( param, 0 ) + else + tFilters[r] = param + end + if coroutine.status( r ) == "dead" then + _routines[n] = nil + living = living - 1 + if living <= _limit then + return n + end + end + end + end + end + for n=1,count do + local r = _routines[n] + if r and coroutine.status( r ) == "dead" then + _routines[n] = nil + living = living - 1 + if living <= _limit then + return n + end + end + end + eventData = { os.pullEventRaw() } + end +end + +function waitForAny( ... ) + local routines = { create( ... ) } + return runUntilLimit( routines, #routines - 1 ) +end + +function waitForAll( ... ) + local routines = { create( ... ) } + runUntilLimit( routines, 0 ) +end diff --git a/src/main/resources/assets/computercraft/lua/rom/apis/peripheral b/src/main/resources/assets/computercraft/lua/rom/apis/peripheral new file mode 100644 index 0000000000..bbb59afed3 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/apis/peripheral @@ -0,0 +1,118 @@ +local native = peripheral + +function getNames() + local tResults = {} + for n,sSide in ipairs( rs.getSides() ) do + if native.isPresent( sSide ) then + table.insert( tResults, sSide ) + if native.getType( sSide ) == "modem" and not native.call( sSide, "isWireless" ) then + local tRemote = native.call( sSide, "getNamesRemote" ) + for n,sName in ipairs( tRemote ) do + table.insert( tResults, sName ) + end + end + end + end + return tResults +end + +function isPresent( _sSide ) + if type( _sSide ) ~= "string" then + error( "Expected string", 2 ) + end + if native.isPresent( _sSide ) then + return true + end + for n,sSide in ipairs( rs.getSides() ) do + if native.getType( sSide ) == "modem" and not native.call( sSide, "isWireless" ) then + if native.call( sSide, "isPresentRemote", _sSide ) then + return true + end + end + end + return false +end + +function getType( _sSide ) + if type( _sSide ) ~= "string" then + error( "Expected string", 2 ) + end + if native.isPresent( _sSide ) then + return native.getType( _sSide ) + end + for n,sSide in ipairs( rs.getSides() ) do + if native.getType( sSide ) == "modem" and not native.call( sSide, "isWireless" ) then + if native.call( sSide, "isPresentRemote", _sSide ) then + return native.call( sSide, "getTypeRemote", _sSide ) + end + end + end + return nil +end + +function getMethods( _sSide ) + if type( _sSide ) ~= "string" then + error( "Expected string", 2 ) + end + if native.isPresent( _sSide ) then + return native.getMethods( _sSide ) + end + for n,sSide in ipairs( rs.getSides() ) do + if native.getType( sSide ) == "modem" and not native.call( sSide, "isWireless" ) then + if native.call( sSide, "isPresentRemote", _sSide ) then + return native.call( sSide, "getMethodsRemote", _sSide ) + end + end + end + return nil +end + +function call( _sSide, _sMethod, ... ) + if type( _sSide ) ~= "string" or type( _sMethod ) ~= "string" then + error( "Expected string, string", 2 ) + end + if native.isPresent( _sSide ) then + return native.call( _sSide, _sMethod, ... ) + end + for n,sSide in ipairs( rs.getSides() ) do + if native.getType( sSide ) == "modem" and not native.call( sSide, "isWireless" ) then + if native.call( sSide, "isPresentRemote", _sSide ) then + return native.call( sSide, "callRemote", _sSide, _sMethod, ... ) + end + end + end + return nil +end + +function wrap( _sSide ) + if type( _sSide ) ~= "string" then + error( "Expected string", 2 ) + end + if peripheral.isPresent( _sSide ) then + local tMethods = peripheral.getMethods( _sSide ) + local tResult = {} + for n,sMethod in ipairs( tMethods ) do + tResult[sMethod] = function( ... ) + return peripheral.call( _sSide, sMethod, ... ) + end + end + return tResult + end + return nil +end + +function find( sType, fnFilter ) + if type( sType ) ~= "string" or (fnFilter ~= nil and type( fnFilter ) ~= "function") then + error( "Expected string, [function]", 2 ) + end + local tResults = {} + for n,sName in ipairs( peripheral.getNames() ) do + if peripheral.getType( sName ) == sType then + local wrapped = peripheral.wrap( sName ) + if fnFilter == nil or fnFilter( sName, wrapped ) then + table.insert( tResults, wrapped ) + end + end + end + return table.unpack( tResults ) +end diff --git a/src/main/resources/assets/computercraft/lua/rom/apis/rednet b/src/main/resources/assets/computercraft/lua/rom/apis/rednet new file mode 100644 index 0000000000..4d2e817cb6 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/apis/rednet @@ -0,0 +1,266 @@ + +CHANNEL_BROADCAST = 65535 +CHANNEL_REPEAT = 65533 + +local tReceivedMessages = {} +local tReceivedMessageTimeouts = {} +local tHostnames = {} + +function open( sModem ) + if type( sModem ) ~= "string" then + error( "expected string", 2 ) + end + if peripheral.getType( sModem ) ~= "modem" then + error( "No such modem: "..sModem, 2 ) + end + peripheral.call( sModem, "open", os.getComputerID() ) + peripheral.call( sModem, "open", CHANNEL_BROADCAST ) +end + +function close( sModem ) + if sModem then + -- Close a specific modem + if type( sModem ) ~= "string" then + error( "expected string", 2 ) + end + if peripheral.getType( sModem ) ~= "modem" then + error( "No such modem: "..sModem, 2 ) + end + peripheral.call( sModem, "close", os.getComputerID() ) + peripheral.call( sModem, "close", CHANNEL_BROADCAST ) + else + -- Close all modems + for n,sModem in ipairs( peripheral.getNames() ) do + if isOpen( sModem ) then + close( sModem ) + end + end + end +end + +function isOpen( sModem ) + if sModem then + -- Check if a specific modem is open + if type( sModem ) ~= "string" then + error( "expected string", 2 ) + end + if peripheral.getType( sModem ) == "modem" then + return peripheral.call( sModem, "isOpen", os.getComputerID() ) and peripheral.call( sModem, "isOpen", CHANNEL_BROADCAST ) + end + else + -- Check if any modem is open + for n,sModem in ipairs( peripheral.getNames() ) do + if isOpen( sModem ) then + return true + end + end + end + return false +end + +function send( nRecipient, message, sProtocol ) + -- Generate a (probably) unique message ID + -- We could do other things to guarantee uniqueness, but we really don't need to + -- Store it to ensure we don't get our own messages back + local nMessageID = math.random( 1, 2147483647 ) + tReceivedMessages[ nMessageID ] = true + tReceivedMessageTimeouts[ os.startTimer( 30 ) ] = nMessageID + + -- Create the message + local nReplyChannel = os.getComputerID() + local tMessage = { + nMessageID = nMessageID, + nRecipient = nRecipient, + message = message, + sProtocol = sProtocol, + } + + if nRecipient == os.getComputerID() then + -- Loopback to ourselves + os.queueEvent( "rednet_message", nReplyChannel, message, sProtocol ) + + else + -- Send on all open modems, to the target and to repeaters + local sent = false + for n,sModem in ipairs( peripheral.getNames() ) do + if isOpen( sModem ) then + peripheral.call( sModem, "transmit", nRecipient, nReplyChannel, tMessage ); + peripheral.call( sModem, "transmit", CHANNEL_REPEAT, nReplyChannel, tMessage ); + sent = true + end + end + end +end + +function broadcast( message, sProtocol ) + send( CHANNEL_BROADCAST, message, sProtocol ) +end + +function receive( sProtocolFilter, nTimeout ) + -- The parameters used to be ( nTimeout ), detect this case for backwards compatibility + if type(sProtocolFilter) == "number" and nTimeout == nil then + sProtocolFilter, nTimeout = nil, sProtocolFilter + end + + -- Start the timer + local timer = nil + local sFilter = nil + if nTimeout then + timer = os.startTimer( nTimeout ) + sFilter = nil + else + sFilter = "rednet_message" + end + + -- Wait for events + while true do + local sEvent, p1, p2, p3 = os.pullEvent( sFilter ) + if sEvent == "rednet_message" then + -- Return the first matching rednet_message + local nSenderID, message, sProtocol = p1, p2, p3 + if sProtocolFilter == nil or sProtocol == sProtocolFilter then + return nSenderID, message, sProtocol + end + elseif sEvent == "timer" then + -- Return nil if we timeout + if p1 == timer then + return nil + end + end + end +end + +function host( sProtocol, sHostname ) + if type( sProtocol ) ~= "string" or type( sHostname ) ~= "string" then + error( "expected string, string", 2 ) + end + if sHostname == "localhost" then + error( "Reserved hostname", 2 ) + end + if tHostnames[ sProtocol ] ~= sHostname then + if lookup( sProtocol, sHostname ) ~= nil then + error( "Hostname in use", 2 ) + end + tHostnames[ sProtocol ] = sHostname + end +end + +function unhost( sProtocol ) + if type( sProtocol ) ~= "string" then + error( "expected string", 2 ) + end + tHostnames[ sProtocol ] = nil +end + +function lookup( sProtocol, sHostname ) + if type( sProtocol ) ~= "string" then + error( "expected string", 2 ) + end + + -- Build list of host IDs + local tResults = nil + if sHostname == nil then + tResults = {} + end + + -- Check localhost first + if tHostnames[ sProtocol ] then + if sHostname == nil then + table.insert( tResults, os.getComputerID() ) + elseif sHostname == "localhost" or sHostname == tHostnames[ sProtocol ] then + return os.getComputerID() + end + end + + if not isOpen() then + if tResults then + return table.unpack( tResults ) + end + return nil + end + + -- Broadcast a lookup packet + broadcast( { + sType = "lookup", + sProtocol = sProtocol, + sHostname = sHostname, + }, "dns" ) + + -- Start a timer + local timer = os.startTimer( 2 ) + + -- Wait for events + while true do + local event, p1, p2, p3 = os.pullEvent() + if event == "rednet_message" then + -- Got a rednet message, check if it's the response to our request + local nSenderID, tMessage, sMessageProtocol = p1, p2, p3 + if sMessageProtocol == "dns" and type(tMessage) == "table" and tMessage.sType == "lookup response" then + if tMessage.sProtocol == sProtocol then + if sHostname == nil then + table.insert( tResults, nSenderID ) + elseif tMessage.sHostname == sHostname then + return nSenderID + end + end + end + else + -- Got a timer event, check it's the end of our timeout + if p1 == timer then + break + end + end + end + if tResults then + return table.unpack( tResults ) + end + return nil +end + +local bRunning = false +function run() + if bRunning then + error( "rednet is already running", 2 ) + end + bRunning = true + + while bRunning do + local sEvent, p1, p2, p3, p4 = os.pullEventRaw() + if sEvent == "modem_message" then + -- Got a modem message, process it and add it to the rednet event queue + local sModem, nChannel, nReplyChannel, tMessage = p1, p2, p3, p4 + if isOpen( sModem ) and ( nChannel == os.getComputerID() or nChannel == CHANNEL_BROADCAST ) then + if type( tMessage ) == "table" and tMessage.nMessageID then + if not tReceivedMessages[ tMessage.nMessageID ] then + tReceivedMessages[ tMessage.nMessageID ] = true + tReceivedMessageTimeouts[ os.startTimer( 30 ) ] = nMessageID + os.queueEvent( "rednet_message", nReplyChannel, tMessage.message, tMessage.sProtocol ) + end + end + end + + elseif sEvent == "rednet_message" then + -- Got a rednet message (queued from above), respond to dns lookup + local nSenderID, tMessage, sProtocol = p1, p2, p3 + if sProtocol == "dns" and type(tMessage) == "table" and tMessage.sType == "lookup" then + local sHostname = tHostnames[ tMessage.sProtocol ] + if sHostname ~= nil and (tMessage.sHostname == nil or tMessage.sHostname == sHostname) then + rednet.send( nSenderID, { + sType = "lookup response", + sHostname = sHostname, + sProtocol = tMessage.sProtocol, + }, "dns" ) + end + end + + elseif sEvent == "timer" then + -- Got a timer event, use it to clear the event queue + local nTimer = p1 + local nMessage = tReceivedMessageTimeouts[ nTimer ] + if nMessage then + tReceivedMessageTimeouts[ nTimer ] = nil + tReceivedMessages[ nMessage ] = nil + end + end + end +end diff --git a/src/main/resources/assets/computercraft/lua/rom/apis/settings b/src/main/resources/assets/computercraft/lua/rom/apis/settings new file mode 100644 index 0000000000..6f22867662 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/apis/settings @@ -0,0 +1,100 @@ + +local tSettings = {} + +function set( sName, value ) + if type(sName) ~= "string" or + (type(value) ~= "string" and type(value) ~= "number" and type(value) ~= "boolean" and type(value) ~= "table") then + error( "Expected string, value", 2 ) + end + if type(value) == "table" then + -- Ensure value is serializeable + value = textutils.unserialize( textutils.serialize(value) ) + end + tSettings[ sName ] = value +end + +local copy +function copy( value ) + if type(value) == "table" then + local result = {} + for k,v in pairs(value) do + result[k] = copy(v) + end + return result + else + return value + end +end + +function get( sName, default ) + if type(sName) ~= "string" then + error( "Expected string", 2 ) + end + local result = tSettings[ sName ] + if result ~= nil then + return copy(result) + else + return default + end +end + +function unset( sName ) + if type(sName) ~= "string" then + error( "Expected string", 2 ) + end + tSettings[ sName ] = nil +end + +function clear() + tSettings = {} +end + +function getNames() + local result = {} + for k,v in pairs( tSettings ) do + result[ #result + 1 ] = k + end + return result +end + +function load( sPath ) + if type(sPath) ~= "string" then + error( "Expected string", 2 ) + end + local file = fs.open( sPath, "r" ) + if not file then + return false + end + + local sText = file.readAll() + file.close() + + local tFile = textutils.unserialize( sText ) + if type(tFile) ~= "table" then + return false + end + + for k,v in pairs(tFile) do + if type(k) == "string" and + (type(v) == "string" or type(v) == "number" or type(v) == "boolean" or type(v) == "table") then + set( k, v ) + end + end + + return true +end + +function save( sPath ) + if type(sPath) ~= "string" then + error( "Expected string", 2 ) + end + local file = fs.open( sPath, "w" ) + if not file then + return false + end + + file.write( textutils.serialize( tSettings ) ) + file.close() + + return true +end diff --git a/src/main/resources/assets/computercraft/lua/rom/apis/term b/src/main/resources/assets/computercraft/lua/rom/apis/term new file mode 100644 index 0000000000..5d00c0ee08 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/apis/term @@ -0,0 +1,56 @@ + +local native = (term.native and term.native()) or term +local redirectTarget = native + +local function wrap( _sFunction ) + return function( ... ) + return redirectTarget[ _sFunction ]( ... ) + end +end + +local term = {} + +term.redirect = function( target ) + if target == nil or type( target ) ~= "table" then + error( "Invalid redirect target", 2 ) + end + if target == term then + error( "term is not a recommended redirect target, try term.current() instead", 2 ) + end + for k,v in pairs( native ) do + if type( k ) == "string" and type( v ) == "function" then + if type( target[k] ) ~= "function" then + target[k] = function() + error( "Redirect object is missing method "..k..".", 2 ) + end + end + end + end + local oldRedirectTarget = redirectTarget + redirectTarget = target + return oldRedirectTarget +end + +term.current = function() + return redirectTarget +end + +term.native = function() + -- NOTE: please don't use this function unless you have to. + -- If you're running in a redirected or multitasked enviorment, term.native() will NOT be + -- the current terminal when your program starts up. It is far better to use term.current() + return native +end + +for k,v in pairs( native ) do + if type( k ) == "string" and type( v ) == "function" then + if term[k] == nil then + term[k] = wrap( k ) + end + end +end + +local env = _ENV +for k,v in pairs( term ) do + env[k] = v +end diff --git a/src/main/resources/assets/computercraft/lua/rom/apis/textutils b/src/main/resources/assets/computercraft/lua/rom/apis/textutils new file mode 100644 index 0000000000..fc2dc34955 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/apis/textutils @@ -0,0 +1,393 @@ + +function slowWrite( sText, nRate ) + nRate = nRate or 20 + if nRate < 0 then + error( "Rate must be positive", 2 ) + end + local nSleep = 1 / nRate + + sText = tostring( sText ) + local x,y = term.getCursorPos(x,y) + local len = string.len( sText ) + + for n=1,len do + term.setCursorPos( x, y ) + sleep( nSleep ) + local nLines = write( string.sub( sText, 1, n ) ) + local newX, newY = term.getCursorPos() + y = newY - nLines + end +end + +function slowPrint( sText, nRate ) + slowWrite( sText, nRate) + print() +end + +function formatTime( nTime, bTwentyFourHour ) + local sTOD = nil + if not bTwentyFourHour then + if nTime >= 12 then + sTOD = "PM" + else + sTOD = "AM" + end + if nTime >= 13 then + nTime = nTime - 12 + end + end + + local nHour = math.floor(nTime) + local nMinute = math.floor((nTime - nHour)*60) + if sTOD then + return string.format( "%d:%02d %s", nHour, nMinute, sTOD ) + else + return string.format( "%d:%02d", nHour, nMinute ) + end +end + +local function makePagedScroll( _term, _nFreeLines ) + local nativeScroll = _term.scroll + local nFreeLines = _nFreeLines or 0 + return function( _n ) + for n=1,_n do + nativeScroll( 1 ) + + if nFreeLines <= 0 then + local w,h = _term.getSize() + _term.setCursorPos( 1, h ) + _term.write( "Press any key to continue" ) + os.pullEvent( "key" ) + _term.clearLine() + _term.setCursorPos( 1, h ) + else + nFreeLines = nFreeLines - 1 + end + end + end +end + +function pagedPrint( _sText, _nFreeLines ) + -- Setup a redirector + local oldTerm = term.current() + local newTerm = {} + for k,v in pairs( oldTerm ) do + newTerm[k] = v + end + newTerm.scroll = makePagedScroll( oldTerm, _nFreeLines ) + term.redirect( newTerm ) + + -- Print the text + local result + local ok, err = pcall( function() + if _sText ~= nil then + result = print( _sText ) + else + result = print() + end + end ) + + -- Removed the redirector + term.redirect( oldTerm ) + + -- Propogate errors + if not ok then + error( err, 0 ) + end + return result +end + +local function tabulateCommon( bPaged, ... ) + local tAll = { ... } + + local w,h = term.getSize() + local nMaxLen = w / 8 + for n, t in ipairs( tAll ) do + if type(t) == "table" then + for n, sItem in pairs(t) do + nMaxLen = math.max( string.len( sItem ) + 1, nMaxLen ) + end + end + end + local nCols = math.floor( w / nMaxLen ) + local nLines = 0 + local function newLine() + if bPaged and nLines >= (h-3) then + pagedPrint() + else + print() + end + nLines = nLines + 1 + end + + local function drawCols( _t ) + local nCol = 1 + for n, s in ipairs( _t ) do + if nCol > nCols then + nCol = 1 + newLine() + end + + local cx, cy = term.getCursorPos() + cx = 1 + ((nCol - 1) * nMaxLen) + term.setCursorPos( cx, cy ) + term.write( s ) + + nCol = nCol + 1 + end + print() + end + for n, t in ipairs( tAll ) do + if type(t) == "table" then + if #t > 0 then + drawCols( t ) + end + elseif type(t) == "number" then + term.setTextColor( t ) + end + end +end + +function tabulate( ... ) + tabulateCommon( false, ... ) +end + +function pagedTabulate( ... ) + tabulateCommon( true, ... ) +end + +local g_tLuaKeywords = { + [ "and" ] = true, + [ "break" ] = true, + [ "do" ] = true, + [ "else" ] = true, + [ "elseif" ] = true, + [ "end" ] = true, + [ "false" ] = true, + [ "for" ] = true, + [ "function" ] = true, + [ "if" ] = true, + [ "in" ] = true, + [ "local" ] = true, + [ "nil" ] = true, + [ "not" ] = true, + [ "or" ] = true, + [ "repeat" ] = true, + [ "return" ] = true, + [ "then" ] = true, + [ "true" ] = true, + [ "until" ] = true, + [ "while" ] = true, +} + +local function serializeImpl( t, tTracking, sIndent ) + local sType = type(t) + if sType == "table" then + if tTracking[t] ~= nil then + error( "Cannot serialize table with recursive entries", 0 ) + end + tTracking[t] = true + + if next(t) == nil then + -- Empty tables are simple + return "{}" + else + -- Other tables take more work + local sResult = "{\n" + local sSubIndent = sIndent .. " " + local tSeen = {} + for k,v in ipairs(t) do + tSeen[k] = true + sResult = sResult .. sSubIndent .. serializeImpl( v, tTracking, sSubIndent ) .. ",\n" + end + for k,v in pairs(t) do + if not tSeen[k] then + local sEntry + if type(k) == "string" and not g_tLuaKeywords[k] and string.match( k, "^[%a_][%a%d_]*$" ) then + sEntry = k .. " = " .. serializeImpl( v, tTracking, sSubIndent ) .. ",\n" + else + sEntry = "[ " .. serializeImpl( k, tTracking, sSubIndent ) .. " ] = " .. serializeImpl( v, tTracking, sSubIndent ) .. ",\n" + end + sResult = sResult .. sSubIndent .. sEntry + end + end + sResult = sResult .. sIndent .. "}" + return sResult + end + + elseif sType == "string" then + return string.format( "%q", t ) + + elseif sType == "number" or sType == "boolean" or sType == "nil" then + return tostring(t) + + else + error( "Cannot serialize type "..sType, 0 ) + + end +end + +empty_json_array = {} + +local function serializeJSONImpl( t, tTracking, bNBTStyle ) + local sType = type(t) + if t == empty_json_array then + return "[]" + + elseif sType == "table" then + if tTracking[t] ~= nil then + error( "Cannot serialize table with recursive entries", 0 ) + end + tTracking[t] = true + + if next(t) == nil then + -- Empty tables are simple + return "{}" + else + -- Other tables take more work + local sObjectResult = "{" + local sArrayResult = "[" + local nObjectSize = 0 + local nArraySize = 0 + for k,v in pairs(t) do + if type(k) == "string" then + local sEntry + if bNBTStyle then + sEntry = tostring(k) .. ":" .. serializeJSONImpl( v, tTracking, bNBTStyle ) + else + sEntry = string.format( "%q", k ) .. ":" .. serializeJSONImpl( v, tTracking, bNBTStyle ) + end + if nObjectSize == 0 then + sObjectResult = sObjectResult .. sEntry + else + sObjectResult = sObjectResult .. "," .. sEntry + end + nObjectSize = nObjectSize + 1 + end + end + for n,v in ipairs(t) do + local sEntry = serializeJSONImpl( v, tTracking, bNBTStyle ) + if nArraySize == 0 then + sArrayResult = sArrayResult .. sEntry + else + sArrayResult = sArrayResult .. "," .. sEntry + end + nArraySize = nArraySize + 1 + end + sObjectResult = sObjectResult .. "}" + sArrayResult = sArrayResult .. "]" + if nObjectSize > 0 or nArraySize == 0 then + return sObjectResult + else + return sArrayResult + end + end + + elseif sType == "string" then + return string.format( "%q", t ) + + elseif sType == "number" or sType == "boolean" then + return tostring(t) + + else + error( "Cannot serialize type "..sType, 0 ) + + end +end + +function serialize( t ) + local tTracking = {} + return serializeImpl( t, tTracking, "" ) +end + +function unserialize( s ) + local func = load( "return "..s, "unserialize", "t", {} ) + if func then + local ok, result = pcall( func ) + if ok then + return result + end + end + return nil +end + +function serializeJSON( t, bNBTStyle ) + local tTracking = {} + return serializeJSONImpl( t, tTracking, bNBTStyle or false ) +end + +function urlEncode( str ) + if str then + str = string.gsub(str, "\n", "\r\n") + str = string.gsub(str, "([^A-Za-z0-9 %-%_%.])", function(c) + local n = string.byte(c) + if n < 128 then + -- ASCII + return string.format("%%%02X", n) + else + -- Non-ASCII (encode as UTF-8) + return + string.format("%%%02X", 192 + bit32.band( bit32.arshift(n,6), 31 ) ) .. + string.format("%%%02X", 128 + bit32.band( n, 63 ) ) + end + end ) + str = string.gsub(str, " ", "+") + end + return str +end + +local tEmpty = {} +function complete( sSearchText, tSearchTable ) + local nStart = 1 + local nDot = string.find( sSearchText, ".", nStart, true ) + local tTable = tSearchTable or _ENV + while nDot do + local sPart = string.sub( sSearchText, nStart, nDot - 1 ) + local value = tTable[ sPart ] + if type( value ) == "table" then + tTable = value + nStart = nDot + 1 + nDot = string.find( sSearchText, ".", nStart, true ) + else + return tEmpty + end + end + + local sPart = string.sub( sSearchText, nStart, nDot ) + local nPartLength = string.len( sPart ) + + local tResults = {} + local tSeen = {} + while tTable do + for k,v in pairs( tTable ) do + if not tSeen[k] and type(k) == "string" then + if string.find( k, sPart, 1, true ) == 1 then + if not g_tLuaKeywords[k] and string.match( k, "^[%a_][%a%d_]*$" ) then + local sResult = string.sub( k, nPartLength + 1 ) + if type(v) == "function" then + sResult = sResult .. "(" + elseif type(v) == "table" and next(v) ~= nil then + sResult = sResult .. "." + end + table.insert( tResults, sResult ) + end + end + end + tSeen[k] = true + end + local tMetatable = getmetatable( tTable ) + if tMetatable and type( tMetatable.__index ) == "table" then + tTable = tMetatable.__index + else + tTable = nil + end + end + + table.sort( tResults ) + return tResults +end + +-- GB versions +serialise = serialize +unserialise = unserialize +serialiseJSON = serializeJSON diff --git a/src/main/resources/assets/computercraft/lua/rom/apis/turtle/turtle b/src/main/resources/assets/computercraft/lua/rom/apis/turtle/turtle new file mode 100644 index 0000000000..fab90d5afe --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/apis/turtle/turtle @@ -0,0 +1,34 @@ + +if not turtle then + error( "Cannot load turtle API on computer", 2 ) +end +native = turtle.native or turtle + +local function addCraftMethod( object ) + if peripheral.getType( "left" ) == "workbench" then + object.craft = function( ... ) + return peripheral.call( "left", "craft", ... ) + end + elseif peripheral.getType( "right" ) == "workbench" then + object.craft = function( ... ) + return peripheral.call( "right", "craft", ... ) + end + else + object.craft = nil + end +end + +-- Put commands into environment table +local env = _ENV +for k,v in pairs( native ) do + if k == "equipLeft" or k == "equipRight" then + env[k] = function( ... ) + local result, err = v( ... ) + addCraftMethod( turtle ) + return result, err + end + else + env[k] = v + end +end +addCraftMethod( env ) diff --git a/src/main/resources/assets/computercraft/lua/rom/apis/vector b/src/main/resources/assets/computercraft/lua/rom/apis/vector new file mode 100644 index 0000000000..e5d1a981a9 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/apis/vector @@ -0,0 +1,85 @@ + +local vector = { + add = function( self, o ) + return vector.new( + self.x + o.x, + self.y + o.y, + self.z + o.z + ) + end, + sub = function( self, o ) + return vector.new( + self.x - o.x, + self.y - o.y, + self.z - o.z + ) + end, + mul = function( self, m ) + return vector.new( + self.x * m, + self.y * m, + self.z * m + ) + end, + div = function( self, m ) + return vector.new( + self.x / m, + self.y / m, + self.z / m + ) + end, + unm = function( self ) + return vector.new( + -self.x, + -self.y, + -self.z + ) + end, + dot = function( self, o ) + return self.x*o.x + self.y*o.y + self.z*o.z + end, + cross = function( self, o ) + return vector.new( + self.y*o.z - self.z*o.y, + self.z*o.x - self.x*o.z, + self.x*o.y - self.y*o.x + ) + end, + length = function( self ) + return math.sqrt( self.x*self.x + self.y*self.y + self.z*self.z ) + end, + normalize = function( self ) + return self:mul( 1 / self:length() ) + end, + round = function( self, nTolerance ) + nTolerance = nTolerance or 1.0 + return vector.new( + math.floor( (self.x + (nTolerance * 0.5)) / nTolerance ) * nTolerance, + math.floor( (self.y + (nTolerance * 0.5)) / nTolerance ) * nTolerance, + math.floor( (self.z + (nTolerance * 0.5)) / nTolerance ) * nTolerance + ) + end, + tostring = function( self ) + return self.x..","..self.y..","..self.z + end, +} + +local vmetatable = { + __index = vector, + __add = vector.add, + __sub = vector.sub, + __mul = vector.mul, + __div = vector.div, + __unm = vector.unm, + __tostring = vector.tostring, +} + +function new( x, y, z ) + local v = { + x = x or 0, + y = y or 0, + z = z or 0 + } + setmetatable( v, vmetatable ) + return v +end diff --git a/src/main/resources/assets/computercraft/lua/rom/apis/window b/src/main/resources/assets/computercraft/lua/rom/apis/window new file mode 100644 index 0000000000..c5e83c61c1 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/apis/window @@ -0,0 +1,422 @@ + +local tHex = { + [ colors.white ] = "0", + [ colors.orange ] = "1", + [ colors.magenta ] = "2", + [ colors.lightBlue ] = "3", + [ colors.yellow ] = "4", + [ colors.lime ] = "5", + [ colors.pink ] = "6", + [ colors.gray ] = "7", + [ colors.lightGray ] = "8", + [ colors.cyan ] = "9", + [ colors.purple ] = "a", + [ colors.blue ] = "b", + [ colors.brown ] = "c", + [ colors.green ] = "d", + [ colors.red ] = "e", + [ colors.black ] = "f", +} + +local string_rep = string.rep +local string_sub = string.sub + +function create( parent, nX, nY, nWidth, nHeight, bStartVisible ) + + if type( parent ) ~= "table" or + type( nX ) ~= "number" or + type( nY ) ~= "number" or + type( nWidth ) ~= "number" or + type( nHeight ) ~= "number" or + (bStartVisible ~= nil and type( bStartVisible ) ~= "boolean") then + error( "Expected object, number, number, number, number, [boolean]", 2 ) + end + + if parent == term then + error( "term is not a recommended window parent, try term.current() instead", 2 ) + end + + local sEmptySpaceLine + local tEmptyColorLines = {} + local function createEmptyLines( nWidth ) + sEmptySpaceLine = string_rep( " ", nWidth ) + for n=0,15 do + local nColor = 2^n + local sHex = tHex[nColor] + tEmptyColorLines[nColor] = string_rep( sHex, nWidth ) + end + end + + createEmptyLines( nWidth ) + + -- Setup + local bVisible = (bStartVisible ~= false) + local nCursorX = 1 + local nCursorY = 1 + local bCursorBlink = false + local nTextColor = colors.white + local nBackgroundColor = colors.black + local tLines = {} + do + local sEmptyText = sEmptySpaceLine + local sEmptyTextColor = tEmptyColorLines[ nTextColor ] + local sEmptyBackgroundColor = tEmptyColorLines[ nBackgroundColor ] + for y=1,nHeight do + tLines[y] = { + text = sEmptyText, + textColor = sEmptyTextColor, + backgroundColor = sEmptyBackgroundColor, + } + end + end + + -- Helper functions + local function updateCursorPos() + if nCursorX >= 1 and nCursorY >= 1 and + nCursorX <= nWidth and nCursorY <= nHeight then + parent.setCursorPos( nX + nCursorX - 1, nY + nCursorY - 1 ) + else + parent.setCursorPos( 0, 0 ) + end + end + + local function updateCursorBlink() + parent.setCursorBlink( bCursorBlink ) + end + + local function updateCursorColor() + parent.setTextColor( nTextColor ) + end + + local function redrawLine( n ) + local tLine = tLines[ n ] + parent.setCursorPos( nX, nY + n - 1 ) + parent.blit( tLine.text, tLine.textColor, tLine.backgroundColor ) + end + + local function redraw() + for n=1,nHeight do + redrawLine( n ) + end + end + + local function internalBlit( sText, sTextColor, sBackgroundColor ) + local nStart = nCursorX + local nEnd = nStart + #sText - 1 + if nCursorY >= 1 and nCursorY <= nHeight then + if nStart <= nWidth and nEnd >= 1 then + -- Modify line + local tLine = tLines[ nCursorY ] + if nStart == 1 and nEnd == nWidth then + tLine.text = sText + tLine.textColor = sTextColor + tLine.backgroundColor = sBackgroundColor + else + local sClippedText, sClippedTextColor, sClippedBackgroundColor + if nStart < 1 then + local nClipStart = 1 - nStart + 1 + local nClipEnd = nWidth - nStart + 1 + sClippedText = string_sub( sText, nClipStart, nClipEnd ) + sClippedTextColor = string_sub( sTextColor, nClipStart, nClipEnd ) + sClippedBackgroundColor = string_sub( sBackgroundColor, nClipStart, nClipEnd ) + elseif nEnd > nWidth then + local nClipEnd = nWidth - nStart + 1 + sClippedText = string_sub( sText, 1, nClipEnd ) + sClippedTextColor = string_sub( sTextColor, 1, nClipEnd ) + sClippedBackgroundColor = string_sub( sBackgroundColor, 1, nClipEnd ) + else + sClippedText = sText + sClippedTextColor = sTextColor + sClippedBackgroundColor = sBackgroundColor + end + + local sOldText = tLine.text + local sOldTextColor = tLine.textColor + local sOldBackgroundColor = tLine.backgroundColor + local sNewText, sNewTextColor, sNewBackgroundColor + if nStart > 1 then + local nOldEnd = nStart - 1 + sNewText = string_sub( sOldText, 1, nOldEnd ) .. sClippedText + sNewTextColor = string_sub( sOldTextColor, 1, nOldEnd ) .. sClippedTextColor + sNewBackgroundColor = string_sub( sOldBackgroundColor, 1, nOldEnd ) .. sClippedBackgroundColor + else + sNewText = sClippedText + sNewTextColor = sClippedTextColor + sNewBackgroundColor = sClippedBackgroundColor + end + if nEnd < nWidth then + local nOldStart = nEnd + 1 + sNewText = sNewText .. string_sub( sOldText, nOldStart, nWidth ) + sNewTextColor = sNewTextColor .. string_sub( sOldTextColor, nOldStart, nWidth ) + sNewBackgroundColor = sNewBackgroundColor .. string_sub( sOldBackgroundColor, nOldStart, nWidth ) + end + + tLine.text = sNewText + tLine.textColor = sNewTextColor + tLine.backgroundColor = sNewBackgroundColor + end + + -- Redraw line + if bVisible then + redrawLine( nCursorY ) + end + end + end + + -- Move and redraw cursor + nCursorX = nEnd + 1 + if bVisible then + updateCursorColor() + updateCursorPos() + end + end + + -- Terminal implementation + local window = {} + + function window.write( sText ) + sText = tostring( sText ) + internalBlit( sText, string_rep( tHex[ nTextColor ], #sText ), string_rep( tHex[ nBackgroundColor ], #sText ) ) + end + + function window.blit( sText, sTextColor, sBackgroundColor ) + if type(sText) ~= "string" or type(sTextColor) ~= "string" or type(sBackgroundColor) ~= "string" then + error( "Expected string, string, string", 2 ) + end + if #sTextColor ~= #sText or #sBackgroundColor ~= #sText then + error( "Arguments must be the same length", 2 ) + end + internalBlit( sText, sTextColor, sBackgroundColor ) + end + + function window.clear() + local sEmptyText = sEmptySpaceLine + local sEmptyTextColor = tEmptyColorLines[ nTextColor ] + local sEmptyBackgroundColor = tEmptyColorLines[ nBackgroundColor ] + for y=1,nHeight do + tLines[y] = { + text = sEmptyText, + textColor = sEmptyTextColor, + backgroundColor = sEmptyBackgroundColor, + } + end + if bVisible then + redraw() + updateCursorColor() + updateCursorPos() + end + end + + function window.clearLine() + if nCursorY >= 1 and nCursorY <= nHeight then + local sEmptyText = sEmptySpaceLine + local sEmptyTextColor = tEmptyColorLines[ nTextColor ] + local sEmptyBackgroundColor = tEmptyColorLines[ nBackgroundColor ] + tLines[ nCursorY ] = { + text = sEmptyText, + textColor = sEmptyTextColor, + backgroundColor = sEmptyBackgroundColor, + } + if bVisible then + redrawLine( nCursorY ) + updateCursorColor() + updateCursorPos() + end + end + end + + function window.getCursorPos() + return nCursorX, nCursorY + end + + function window.setCursorPos( x, y ) + nCursorX = math.floor( x ) + nCursorY = math.floor( y ) + if bVisible then + updateCursorPos() + end + end + + function window.setCursorBlink( blink ) + bCursorBlink = blink + if bVisible then + updateCursorBlink() + end + end + + local function isColor() + return parent.isColor() + end + + function window.isColor() + return isColor() + end + + function window.isColour() + return isColor() + end + + local function setTextColor( color ) + if not parent.isColor() then + if color ~= colors.white and color ~= colors.black and color ~= colors.gray and color ~= colors.lightGray then + error( "Color not supported", 3 ) + end + end + nTextColor = color + if bVisible then + updateCursorColor() + end + end + + function window.setTextColor( color ) + setTextColor( color ) + end + + function window.setTextColour( color ) + setTextColor( color ) + end + + local function setBackgroundColor( color ) + if not parent.isColor() then + if color ~= colors.white and color ~= colors.black and color ~= colors.gray and color ~= colors.lightGray then + error( "Color not supported", 3 ) + end + end + nBackgroundColor = color + end + + function window.setBackgroundColor( color ) + setBackgroundColor( color ) + end + + function window.setBackgroundColour( color ) + setBackgroundColor( color ) + end + + function window.getSize() + return nWidth, nHeight + end + + function window.scroll( n ) + if n ~= 0 then + local tNewLines = {} + local sEmptyText = sEmptySpaceLine + local sEmptyTextColor = tEmptyColorLines[ nTextColor ] + local sEmptyBackgroundColor = tEmptyColorLines[ nBackgroundColor ] + for newY=1,nHeight do + local y = newY + n + if y >= 1 and y <= nHeight then + tNewLines[newY] = tLines[y] + else + tNewLines[newY] = { + text = sEmptyText, + textColor = sEmptyTextColor, + backgroundColor = sEmptyBackgroundColor, + } + end + end + tLines = tNewLines + if bVisible then + redraw() + updateCursorColor() + updateCursorPos() + end + end + end + + function window.getTextColor() + return nTextColor + end + + function window.getTextColour() + return nTextColor + end + + function window.getBackgroundColor() + return nBackgroundColor + end + + function window.getBackgroundColour() + return nBackgroundColor + end + + -- Other functions + function window.setVisible( bVis ) + if bVisible ~= bVis then + bVisible = bVis + if bVisible then + window.redraw() + end + end + end + + function window.redraw() + if bVisible then + redraw() + updateCursorBlink() + updateCursorColor() + updateCursorPos() + end + end + + function window.restoreCursor() + if bVisible then + updateCursorBlink() + updateCursorColor() + updateCursorPos() + end + end + + function window.getPosition() + return nX, nY + end + + function window.reposition( nNewX, nNewY, nNewWidth, nNewHeight ) + nX = nNewX + nY = nNewY + if nNewWidth and nNewHeight then + local tNewLines = {} + createEmptyLines( nNewWidth ) + local sEmptyText = sEmptySpaceLine + local sEmptyTextColor = tEmptyColorLines[ nTextColor ] + local sEmptyBackgroundColor = tEmptyColorLines[ nBackgroundColor ] + for y=1,nNewHeight do + if y > nHeight then + tNewLines[y] = { + text = sEmptyText, + textColor = sEmptyTextColor, + backgroundColor = sEmptyBackgroundColor + } + else + local tOldLine = tLines[y] + if nNewWidth == nWidth then + tNewLines[y] = tOldLine + elseif nNewWidth < nWidth then + tNewLines[y] = { + text = string_sub( tOldLine.text, 1, nNewWidth ), + textColor = string_sub( tOldLine.textColor, 1, nNewWidth ), + backgroundColor = string_sub( tOldLine.backgroundColor, 1, nNewWidth ), + } + else + tNewLines[y] = { + text = tOldLine.text .. string_sub( sEmptyText, nWidth + 1, nNewWidth ), + textColor = tOldLine.textColor .. string_sub( sEmptyTextColor, nWidth + 1, nNewWidth ), + backgroundColor = tOldLine.backgroundColor .. string_sub( sEmptyBackgroundColor, nWidth + 1, nNewWidth ), + } + end + end + end + nWidth = nNewWidth + nHeight = nNewHeight + tLines = tNewLines + end + if bVisible then + window.redraw() + end + end + + if bVisible then + window.redraw() + end + return window +end diff --git a/src/main/resources/assets/computercraft/lua/rom/autorun/.ignoreme b/src/main/resources/assets/computercraft/lua/rom/autorun/.ignoreme new file mode 100644 index 0000000000..25655383c3 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/autorun/.ignoreme @@ -0,0 +1,4 @@ +--[[ +Alright then, don't ignore me. This file is to ensure the existance of the "autorun" folder, files placed in this folder +using resource packs will always run when computers startup. +]] \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/adventure b/src/main/resources/assets/computercraft/lua/rom/help/adventure new file mode 100644 index 0000000000..bd1d982cff --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/adventure @@ -0,0 +1 @@ +adventure is a text adventure game for CraftOS. To navigate around the world of adventure, type simple instructions to the interpreter, for example: "go north", "punch tree", "craft planks", "mine coal with pickaxe", "hit creeper with sword" \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/alias b/src/main/resources/assets/computercraft/lua/rom/help/alias new file mode 100644 index 0000000000..0b1f04425f --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/alias @@ -0,0 +1,6 @@ +alias assigns shell commands to run other programs. + +ex: +"alias dir ls" will make the "dir" command run the "ls" program +"alias dir" will remove the alias set on "dir" +"alias" will list all current aliases. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/apis b/src/main/resources/assets/computercraft/lua/rom/help/apis new file mode 100644 index 0000000000..20fc893fb5 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/apis @@ -0,0 +1,4 @@ +apis lists the currently loaded APIs available to programs in CraftOS. + +Type "help " to see help for a specific api. +Call os.loadAPI( path ) to load extra apis. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/bg b/src/main/resources/assets/computercraft/lua/rom/help/bg new file mode 100644 index 0000000000..e674e21844 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/bg @@ -0,0 +1,5 @@ +bg is a program for Advanced Computers which opens a new tab in the background. + +ex: +"bg" will open a background tab running the shell +"bg worm" will open a background tab running the "worm" program diff --git a/src/main/resources/assets/computercraft/lua/rom/help/bit b/src/main/resources/assets/computercraft/lua/rom/help/bit new file mode 100644 index 0000000000..eeee09e057 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/bit @@ -0,0 +1,7 @@ +Functions in the bit manipulation API (NOTE: This API will be removed in a future version. Use bit32 instead): +bit.bnot(n) -- bitwise not (~n) +bit.band(m, n) -- bitwise and (m & n) +bit.bor(m, n) -- bitwise or (m | n) +bit.bxor(m, n) -- bitwise xor (m ^ n) +bit.brshift(n, bits) -- right shift (n >> bits) +bit.blshift(n, bits) -- left shift (n << bits) diff --git a/src/main/resources/assets/computercraft/lua/rom/help/bundled b/src/main/resources/assets/computercraft/lua/rom/help/bundled new file mode 100644 index 0000000000..9b0a94187f --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/bundled @@ -0,0 +1,15 @@ +To set bundled outputs: +c = colors.combine( colors.red, colors.blue ) +rs.setBundledOutput( "left", c ) + +c = colors.combine( c, colors.green ) +rs.setBundledOutput( "left", c ) + +c = colors.subtract( c, colors.blue ) +rs.setBundledOutput( "left", c ) + +To get bundled inputs: +c = rs.getBundledInput( "right" ) +red = colors.test( c, colors.red ) + +Type "help colors" for the list of wire colors. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/cd b/src/main/resources/assets/computercraft/lua/rom/help/cd new file mode 100644 index 0000000000..263317bda5 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/cd @@ -0,0 +1,6 @@ +cd changes the the directory you're in. + +ex: +"cd rom" will move to "rom" folder. +"cd .." will move up one folder. +"cd /" will move to the root. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/changelog b/src/main/resources/assets/computercraft/lua/rom/help/changelog new file mode 100644 index 0000000000..ac4d31afa4 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/changelog @@ -0,0 +1,332 @@ +New Features in ComputerCraft 1.79: + +* Ported ComputerCraftEdu to Minecraft 1.8.9 +* Fixed a handful of bugs in ComputerCraft + +New Features in ComputerCraft 1.77: + +* Ported to Minecraft 1.8.9 +* Added "settings" API +* Added "set" and "wget" programs +* Added settings to disable multishell, startup scripts, and tab completion on a per-computer basis. The default values for these settings can be customised in ComputerCraft.cfg +* All Computer and Turtle items except Command Computers can now be mounted in Disk Drives + +New Features in ComputerCraft 1.76: + +* Ported to Minecraft 1.8 +* Added Ender Modems for cross-dimensional communication +* Fixed handling of 8-bit characters. All the characters in the ISO 8859-1 codepage can now be displayed +* Added some extra graphical characters in the unused character positions, including a suite of characters for Teletext style drawing +* Added support for the new commands in Minecraft 1.8 to the Command Computer +* The return values of turtle.inspect() and commands.getBlockInfo() now include blockstate information +* Added commands.getBlockInfos() function for Command Computers +* Added new "peripherals" program +* Replaced the "_CC_VERSION" and "_MC_VERSION" constants with a new "_HOST" constant +* Shortened the length of time that "Ctrl+T", "Ctrl+S" and "Ctrl+R" must be held down for to terminate, shutdown and reboot the computer +* textutils.serialiseJSON() now takes an optional parameter allowing it to produce JSON text with unquoted object keys. This is used by all autogenerated methods in the "commands" api except for "title" and "tellraw" +* Fixed many bugs + +New Features in ComputerCraft 1.75: + +* Fixed monitors sometimes rendering without part of their text. +* Fixed a regression in the "bit" API. + +New Features in ComputerCraft 1.74: + +* Added tab completion to "edit", "lua" and the shell. +* Added textutils.complete(), fs.complete(), shell.complete(), shell.setCompletionFunction() and help.complete(). +* Added tab completion options to read(). +* Added "key_up" and "mouse_up" events. +* Non-advanced terminals now accept both grey colours. +* Added term.getTextColour(), term.getBackgroundColour() and term.blit(). +* Improved the performance of text rendering on Advanced Computers. +* Added a "Run" button to the edit program on Advanced Computers. +* Turtles can now push players and entities (configurable). +* Turtles now respect server spawn protection (configurable). +* Added a turtle permissions API for mod authors. +* Implemented a subset of the Lua 5.2 API so programs can be written against it now, ahead of a future Lua version upgrade. +* Added a config option to disable parts of the Lua 5.1 API which will be removed when a future Lua version upgrade happens. +* Command Computers can no longer be broken by survival players. +* Fixed the "pick block" key not working on ComputerCraft items in creative mode. +* Fixed the "edit" program being hard to use on certain European keyboards. +* Added "_CC_VERSION" and "_MC_VERSION" constants. + +New Features in ComputerCraft 1.73: + +* The "exec" program, commands.exec() and all related Command Computer functions now return the console output of the command. +* Fixed two multiplayer crash bugs. + +New Features in ComputerCraft 1.7: + +* Added Command Computers +* Added new API: commands +* Added new programs: commands, exec +* Added textutils.serializeJSON() +* Added ILuaContext.executeMainThreadTask() for peripheral developers +* Disk Drives and Printers can now be renamed with Anvils +* Fixed various bugs, crashes and exploits +* Fixed problems with HD texture packs +* Documented the new features in the in-game help + +New Features in ComputerCraft 1.65: + +* Fixed a multiplayer-only crash with turtle.place() +* Fixed some problems with http.post() +* Fixed fs.getDrive() returning incorrect results on remote peripherals + +New Features in ComputerCraft 1.64: + +* Ported to Minecraft 1.7.10 +* New turtle functions: turtle.inspect(), turtle.inspectUp(), turtle.inspectDown(), turtle.getItemDetail() +* Lots of bug and crash fixes, a huge stability improvement over previous versions + +New Features in ComputerCraft 1.63: + +* Turtles can now be painted with dyes, and cleaned with water buckets +* Added a new game: Redirection - ComputerCraft Edition +* Turtle label nameplates now only show when the Turtle is moused-over +* The HTTP API is now enabled by default, and can be configured with a whitelist of permitted domains +* http.get() and http.post() now accept parameters to control the request headers +* New fs function: fs.getDir( path ) +* Fixed some bugs + +New Features in ComputerCraft 1.62: + +* Added IRC-style commands to the "chat" program +* Fixed some bugs and crashes + +New Features in ComputerCraft 1.6: + +* Added Pocket Computers +* Added a multi-tasking system for Advanced Computers and Turtles +* Turtles can now swap out their tools and peripherals at runtime +* Turtles can now carry two tools or peripherals at once in any combination +* Turtles and Computers can now be labelled using Name Tags and Anvils +* Added a configurable fuel limit for Turtles +* Added hostnames, protocols and long distance routing to the rednet API +* Added a peer-to-peer chat program to demonstrate new rednet capabilities +* Added a new game, only on Pocket Computers: "falling" by GopherATL +* File system commands in the shell now accept wildcard arguments +* The shell now accepts long arguments in quotes +* Terminal redirection now no longer uses a stack-based system. Instead: term.current() gets the current terminal object and term.redirect() replaces it. term.restore() has been removed. +* Added a new Windowing API for addressing sub-areas of the terminal +* New programs: fg, bg, multishell, chat, repeat, redstone, equip, unequip +* Improved programs: copy, move, delete, rename, paint, shell +* Removed programs: redset, redprobe, redpulse +* New APIs: window, multishell +* New turtle functions: turtle.equipLeft() and turtle.equipRight() +* New peripheral functions: peripheral.find( [type] ) +* New rednet functions: rednet.host( protocol, hostname ), rednet.unhost( protocol ), rednet.locate( protocol, [hostname] ) +* New fs function: fs.find( wildcard ) +* New shell functions: shell.openTab(), shell.switchTab( [number] ) +* New event "term_resize" fired when the size of a terminal changes +* Improved rednet functions: rednet.send(), rednet.broadcast() and rednet.receive() now take optional protocol parameters +* turtle.craft(0) and turtle.refuel(0) now return true if there is a valid recipe or fuel item, but do not craft of refuel anything +* turtle.suck( [limit] ) can now be used to limit the number of items picked up +* Users of turtle.dig() and turtle.attack() can now specify which side of the turtle to look for a tool to use (by default, both will be considered) +* textutils.serialise( text ) now produces human-readable output +* Refactored most of the codebase and fixed many old bugs and instabilities, turtles should never ever lose their content now +* Fixed the "turtle_inventory" event firing when it shouldn't have +* Added error messages to many more turtle functions after they return false +* Documented all new programs and API changes in the "help" system + +New Features in ComputerCraft 1.58: + +* Fixed a long standing bug where turtles could lose their identify if they travel too far away +* Fixed use of deprecated code, ensuring mod compatibility with the latest versions of Minecraft Forge, and world compatibility with future versions of Minecraft + +New Features in ComputerCraft 1.57: + +* Ported to Minecraft 1.6.4 +* Added two new Treasure Disks: Conway's Game of Life by vilsol and Protector by fredthead +* Fixed a very nasty item duplication bug + +New Features in ComputerCraft 1.56: + +* Added Treasure Disks: Floppy Disks in dungeons which contain interesting community made programs. Find them all! +* All turtle functions now return additional error messages when they fail. +* Resource Packs with Lua Programs can now be edited when extracted to a folder, for easier editing. + +New Features in ComputerCraft 1.55: + +* Ported to Minecraft 1.6.2 +* Added Advanced Turtles +* Added "turtle_inventory" event. Fires when any change is made to the inventory of a turtle +* Added missing functions io.close, io.flush, io.input, io.lines, io.output +* Tweaked the screen colours used by Advanced Computers, Monitors and Turtles +* Added new features for Peripheral authors +* Lua programs can now be included in Resource Packs + +New Features in ComputerCraft 1.52: + +* Ported to Minecraft 1.5.1 + +New Features in ComputerCraft 1.51: + +* Ported to Minecraft 1.5 +* Added Wired Modems +* Added Networking Cables +* Made Wireless Modems more expensive to craft +* New redstone API functions: getAnalogInput(), setAnalogOutput(), getAnalogOutput() +* Peripherals can now be controlled remotely over wired networks. New peripheral API function: getNames() +* New event: "monitor_resize" when the size of a monitor changes +* Except for labelled computers and turtles, ComputerCraft blocks no longer drop items in creative mode +* The pick block function works in creative mode now works for all ComputerCraft blocks +* All blocks and items now use the IDs numbers assigned by FTB by default +* Fixed turtles sometimes placing blocks with incorrect orientations +* Fixed Wireless modems being able to send messages to themselves +* Fixed turtle.attack() having a very short range +* Various bugfixes + +New Features in ComputerCraft 1.5: + +* Redesigned Wireless Modems; they can now send and receive on multiple channels, independent of the computer ID. To use these features, interface with modem peripherals directly. The rednet API still functions as before +* Floppy Disks can now be dyed with multiple dyes, just like armour +* The "excavate" program now retains fuel in it's inventory, so can run unattended +* turtle.place() now tries all possible block orientations before failing +* turtle.refuel(0) returns true if a fuel item is selected +* turtle.craft(0) returns true if the inventory is a valid recipe +* The in-game help system now has documentation for all the peripherals and their methods, including the new modem functionality +* A romantic surprise + +New Features in ComputerCraft 1.48: + +* Ported to Minecraft 1.4.6 +* Advanced Monitors now emit a "monitor_touch" event when right clicked +* Advanced Monitors are now cheaper to craft +* Turtles now get slightly less fuel from items +* Computers can now interact with Command Blocks (if enabled in ComputerCraft.cfg) +* New API function: os.day() +* A christmas surprise + +New Features in ComputerCraft 1.45: + +* Added Advanced Computers +* Added Advanced Monitors +* New program: paint by nitrogenfingers +* New API: paintutils +* New term functions: term.setBackgroundColor, term.setTextColor, term.isColor +* New turtle function: turtle.transferTo + +New Features in ComputerCraft 1.43: + +* Added Printed Pages +* Added Printed Books +* Fixed incompatibility with Forge 275 and above +* Labelled Turtles now keep their fuel when broken + +New Features in ComputerCraft 1.42: + +* Ported to Minecraft 1.3.2 +* Added Printers +* Floppy Disks can be dyed different colours +* Wireless Crafty Turtles can now be crafted +* New textures +* New forge config file +* Bug fixes + +New Features in ComputerCraft 1.4: + +* Ported to Forge Mod Loader. ComputerCraft can now be ran directly from the .zip without extraction +* Added Farming Turtles +* Added Felling Turtles +* Added Digging Turtles +* Added Melee Turtles +* Added Crafty Turtles +* Added 14 new Turtle Combinations accessible by combining the turtle upgrades above +* Labelled computers and turtles can now be crafted into turtles or other turtle types without losing their ID, label and data +* Added a "Turtle Upgrade API" for mod developers to create their own tools and peripherals for turtles +* Turtles can now attack entities with turtle.attack(), and collect their dropped items +* Turtles can now use turtle.place() with any item the player can, and can interact with entities +* Turtles can now craft items with turtle.craft() +* Turtles can now place items into inventories with turtle.drop() +* Changed the behaviour of turtle.place() and turtle.drop() to only consider the currently selected slot +* Turtles can now pick up items from the ground, or from inventories, with turtle.suck() +* Turtles can now compare items in their inventories +* Turtles can place signs with text on them with turtle.place( [signText] ) +* Turtles now optionally require fuel items to move, and can refuel themselves +* The size of the the turtle inventory has been increased to 16 +* The size of the turtle screen has been increased +* New turtle functions: turtle.compareTo( [slotNum] ), turtle.craft(), turtle.attack(), turtle.attackUp(), turtle.attackDown(), turtle.dropUp(), turtle.dropDown(), turtle.getFuelLevel(), turtle.refuel() +* New disk function: disk.getID() +* New turtle programs: craft, refuel +* "excavate" program now much smarter: Will return items to a chest when full, attack mobs, and refuel itself automatically +* New API: keys +* Added optional Floppy Disk and Hard Drive space limits for computers and turtles +* New fs function: fs.getFreeSpace( path ), also fs.getDrive() works again +* The send and receive range of wireless modems now increases with altitude, allowing long range networking from high-altitude computers (great for GPS networks) +* http.request() now supports https:// URLs +* Right clicking a Disk Drive with a Floppy Disk or a Record when sneaking will insert the item into the Disk Drive automatically +* The default size of the computer screen has been increased +* Several stability and security fixes. LuaJ can now no longer leave dangling threads when a computer is unloaded, turtles can no longer be destroyed by tree leaves or walking off the edge of the loaded map. Computers no longer crash when used with RedPower frames. + +New Features in ComputerCraft 1.31: + +* Ported to Minecraft 1.2.3 +* Added Monitors (thanks to Cloudy) +* Updated LuaJ to a newer, less memory hungry version +* rednet_message event now has a third parameter, "distance", to support position triangulation. +* New programs: gps, monitor, pastebin. +* Added a secret program. Use with large monitors! +* New apis: gps, vector +* New turtle functions: turtle.compare(), turtle.compareUp(), turtle.compareDown(), turtle.drop( quantity ) +* New http functions: http.post(). +* New term functions: term.redirect(), term.restore() +* New textutils functions: textutils.urlEncode() +* New rednet functions: rednet.isOpen() +* New config options: modem_range, modem_rangeDuringStorm +* Bug fixes, program tweaks, and help updates + +New Features in ComputerCraft 1.3: + +* Ported to Minecraft Forge +* Added Turtles +* Added Wireless Modems +* Added Mining Turtles +* Added Wireless Turtles +* Added Wireless Mining Turtles +* Computers and Disk Drives no longer get destroyed by water. +* Computers and Turtles can now be labelled with the label program, and labelled devices keep their state when destroyed. +* Computers/Turtles can connect to adjacent devices, and turn them on and off +* User programs now give line numbers in their error messages +* New APIs: turtle, peripheral +* New programs for turtles: tunnel, excavate, go, turn, dance +* New os functions: os.getComputerLabel(), os.setComputerLabel() +* Added "filter" parameter to os.pullEvent() +* New shell function: shell.getCurrentProgram() +* New textutils functions: textutils.serialize(), textutils.unserialize(), textutils.tabulate(), textutils.pagedTabulate(), textutils.slowWrite() +* New io file function: file:lines() +* New fs function: fs.getSize() +* Disk Drives can now play records from other mods +* Bug fixes, program tweaks, and help updates + +New Features in ComputerCraft 1.2: + +* Added Disk Drives and Floppy Disks +* Added Ctrl+T shortcut to terminate the current program (hold) +* Added Ctrl+S shortcut to shutdown the computer (hold) +* Added Ctrl+R shortcut to reboot the computer (hold) +* New Programs: alias, apis, copy, delete, dj, drive, eject, id, label, list, move, reboot, redset, rename, time, worm. +* New APIs: bit, colours, disk, help, rednet, parallel, textutils. +* New color functions: colors.combine(), colors.subtract(), colors.test() +* New fs functions: fs.getName(), new modes for fs.open() +* New os functions: os.loadAPI(), os.unloadAPI(), +os.clock(), os.time(), os.setAlarm(), +os.reboot(), os.queueEvent() +* New redstone function: redstone.getSides() +* New shell functions: shell.setPath(), shell.programs(), shell.resolveProgram(), shell.setAlias() +* Lots of updates to the help pages +* Bug fixes + +New Features in ComputerCraft 1.1: + +* Added Multiplayer support throughout. +* Added connectivity with RedPower bundled cables +* Added HTTP api, enabled via the mod config, to allow computers to access the real world internet +* Added command history to the shell. +* Programs which spin in an infinite loop without yielding will no longer freeze minecraft +* Help updates and bug fixes + +New Features in ComputerCraft 1.0: + +* First Release! diff --git a/src/main/resources/assets/computercraft/lua/rom/help/chat b/src/main/resources/assets/computercraft/lua/rom/help/chat new file mode 100644 index 0000000000..1e99ca45c6 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/chat @@ -0,0 +1,5 @@ +Surf the rednet superhighway with "chat", the networked chat program for CraftOS! Host chatrooms and invite your friends! Requires a Wired or Wireless Modem on each computer. When running chat, type "/help" to see a list of available commands. + +ex: +"chat host forgecraft" will create a chatroom with the name "forgecraft" +"chat join forgecraft direwolf20" will connect to the chatroom with the name "forgecraft", using the nickname "direwolf20" \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/clear b/src/main/resources/assets/computercraft/lua/rom/help/clear new file mode 100644 index 0000000000..ea517ddb32 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/clear @@ -0,0 +1 @@ +clear clears the screen. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/colors b/src/main/resources/assets/computercraft/lua/rom/help/colors new file mode 100644 index 0000000000..b1a76c3f12 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/colors @@ -0,0 +1,8 @@ +Functions in the colors api +(used for redstone.setBundledOutput): +colors.combine( color1, color2, color3, ... ) +colors.subtract( colors, color1, color2, ... ) +colors.test( colors, color ) + +Color constants in the colors api, in ascending bit order: +colors.white, colors.orange, colors.magenta, colors.lightBlue, colors.yellow, colors.lime, colors.pink, colors.gray, colors.lightGray, colors.cyan, colors.purple, colors.blue, colors.brown, colors.green, colors.red, colors.black. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/colours b/src/main/resources/assets/computercraft/lua/rom/help/colours new file mode 100644 index 0000000000..a3d62ee32d --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/colours @@ -0,0 +1,8 @@ +Functions in the colours api +(used for redstone.setBundledOutput): +colours.combine( colour1, colour2, colour3, ...) +colours.subtract( colours, colour1, colour2, ...) +colours.test( colours, colour ) + +Colour constants in the colours api, in ascending bit order: +colours.white, colours.orange, colours.magenta, colours.lightBlue, colours.yellow, colours.lime, colours.pink, colours.grey, colours.lightGrey, colours.cyan, colours.purple, colours.blue, colours.brown, colours.green, colours.red, colours.black. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/commands b/src/main/resources/assets/computercraft/lua/rom/help/commands new file mode 100644 index 0000000000..6026a6ee21 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/commands @@ -0,0 +1,2 @@ +On a Command Computer, "commands" will list all the commands available for use. Use "exec" to execute them. +Type "help commandsapi" for help using commands in lua programs. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/commandsapi b/src/main/resources/assets/computercraft/lua/rom/help/commandsapi new file mode 100644 index 0000000000..de8cffd517 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/commandsapi @@ -0,0 +1,15 @@ +Functions in the commands API: +commands.exec( command ) +commands.execAsync( command ) +commands.list() +commands.getBlockPosition() +commands.getBlockInfo( x, y, z ) +commands.getBlockInfos( minx, miny, minz, maxx, maxy, maxz ) + +The commands API can also be used to invoke commands directly, like so: +commands.say( "Hello World" ) +commands.give( "dan200", "minecraft:diamond", 64 ) +This works with any command. Use "commands.async" instead of "commands" to execute asynchronously. + +The commands API is only available on Command Computers. +Visit http://minecraft.gamepedia.com/Commands for documentation on all commands. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/copy b/src/main/resources/assets/computercraft/lua/rom/help/copy new file mode 100644 index 0000000000..57b3187cb4 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/copy @@ -0,0 +1,6 @@ +cp copies a file or directory from one location to another. + +ex: +"cp rom myrom" copies "rom" to "myrom". +"cp rom mystuff/rom" copies "rom" to "mystuff/rom". +"cp disk/* disk2" copies the contents of one disk to another diff --git a/src/main/resources/assets/computercraft/lua/rom/help/coroutine b/src/main/resources/assets/computercraft/lua/rom/help/coroutine new file mode 100644 index 0000000000..12b366bd27 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/coroutine @@ -0,0 +1,2 @@ +coroutine is a standard Lua5.1 API. +Refer to http://www.lua.org/manual/5.1/ for more information. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/craft b/src/main/resources/assets/computercraft/lua/rom/help/craft new file mode 100644 index 0000000000..de6f6eb60f --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/craft @@ -0,0 +1,5 @@ +craft is a program for Crafty Turtles. Craft will craft a stack of items using the current inventory. + +ex: +"craft" will craft as many items as possible +"craft 5" will craft at most 5 times diff --git a/src/main/resources/assets/computercraft/lua/rom/help/credits b/src/main/resources/assets/computercraft/lua/rom/help/credits new file mode 100644 index 0000000000..9bd3db15cd --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/credits @@ -0,0 +1,10 @@ +ComputerCraft was created by Daniel "dan200" Ratcliffe, with additional code by Aaron "Cloudy" Mills. +Thanks to nitrogenfingers, GopherATL and RamiLego for program contributions. +Thanks to Mojang, the Forge team, and the MCP team. +Uses LuaJ from http://luaj.sourceforge.net/ + +The ComputerCraft 1.76 update was sponsored by MinecraftU and Deep Space. +Visit http://www.minecraftu.org and http://www.deepspace.me/space-cadets to find out more. + +Join the ComputerCraft community online at http://www.computercraft.info +Follow @DanTwoHundred on Twitter! diff --git a/src/main/resources/assets/computercraft/lua/rom/help/dance b/src/main/resources/assets/computercraft/lua/rom/help/dance new file mode 100644 index 0000000000..3c776f8f08 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/dance @@ -0,0 +1 @@ +dance is a program for Turtles. Turtles love to get funky. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/delete b/src/main/resources/assets/computercraft/lua/rom/help/delete new file mode 100644 index 0000000000..f1c0927496 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/delete @@ -0,0 +1,5 @@ +rm deletes a file or a directory and its contents. + +ex: +"rm foo" will delete the file foo. +"rm disk/*" will delete the contents of a disk. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/disk b/src/main/resources/assets/computercraft/lua/rom/help/disk new file mode 100644 index 0000000000..f47bc625c9 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/disk @@ -0,0 +1,17 @@ +Functions in the disk API. These functions are for interacting with disk drives: +disk.isPresent( drive ) +disk.setLabel( drive, label ) +disk.getLabel( drive ) +disk.hasData( drive ) +disk.getMountPath( drive ) +disk.hasAudio( drive ) +disk.getAudioTitle( drive ) +disk.playAudio( drive ) +disk.stopAudio( ) +disk.eject( drive ) +disk.getID( drive ) + +Events fired by the disk API: +"disk" when a disk or other item is inserted into a disk drive. Argument is the name of the drive +"disk_eject" when a disk is removed from a disk drive. Argument is the name of the drive +Type "help events" to learn about the event system. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/dj b/src/main/resources/assets/computercraft/lua/rom/help/dj new file mode 100644 index 0000000000..2c7a02bd13 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/dj @@ -0,0 +1,6 @@ +dj plays Music Discs from disk drives attached to the computer. + +ex: +"dj" or "dj play" plays a random disc. +"dj play left" plays the disc in the drive on the left of the computer. +"dj stop" stops the current disc. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/drive b/src/main/resources/assets/computercraft/lua/rom/help/drive new file mode 100644 index 0000000000..397c98c30f --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/drive @@ -0,0 +1,5 @@ +drive tells you which disk drive the current or specified directory is located in. + +ex: +"drive" tell you the disk drive of the current directory. +"drive foo" tells you the disk drive of the subdirectory "foo" \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/drives b/src/main/resources/assets/computercraft/lua/rom/help/drives new file mode 100644 index 0000000000..6f15f40f39 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/drives @@ -0,0 +1,19 @@ +The Disk Drive is a peripheral device available for CraftOS. Type "help peripheral" to learn about using the Peripheral API to connect with peripherals. When a Disk Drive is connected, peripheral.getType() will return "drive". + +Methods exposed by the Disk Drive: +isDiskPresent() +getDiskLabel() +setDiskLabel( label ) +hasData() +getMountPath() +hasAudio() +getAudioTitle() +playAudio() +stopAudio() +ejectDisk() +getDiskID() + +Events fired by the Disk Drive: +"disk" when a disk or other item is inserted into the drive. Argument is the name of the drive. +"disk_eject" when a disk is removed from a drive. Argument is the name of the drive. +Type "help events" to learn about the event system. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/earth b/src/main/resources/assets/computercraft/lua/rom/help/earth new file mode 100644 index 0000000000..d1b4526733 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/earth @@ -0,0 +1 @@ +Mostly harmless. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/edit b/src/main/resources/assets/computercraft/lua/rom/help/edit new file mode 100644 index 0000000000..31d0444968 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/edit @@ -0,0 +1,4 @@ +edit is a text editor for creating or modifying programs or text files. After creating a program with edit, type its filename in the shell to run it. You can open any of the builtin programs with edit to learn how to program. + +ex: +"edit hello" opens a file called "hello" for editing. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/eject b/src/main/resources/assets/computercraft/lua/rom/help/eject new file mode 100644 index 0000000000..ba6ad1b6c7 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/eject @@ -0,0 +1,4 @@ +eject ejects the contents of an attached disk drive. + +ex: +"eject left" ejects the contents of the disk drive to the left of the computer. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/equip b/src/main/resources/assets/computercraft/lua/rom/help/equip new file mode 100644 index 0000000000..dfb7bebb24 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/equip @@ -0,0 +1,4 @@ +equip is a program for Turtles. equip will equip an item from the Turtle's inventory for use as a tool of peripheral. + +ex: +"equip 5 left" will equip the item from slot 5 of the turtle onto the left side of the turtle diff --git a/src/main/resources/assets/computercraft/lua/rom/help/events b/src/main/resources/assets/computercraft/lua/rom/help/events new file mode 100644 index 0000000000..2fa405881e --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/events @@ -0,0 +1,15 @@ +The function os.pullEvent() will yield the program until a system event occurs. The first return value is the event name, followed by any arguments. + +Some events which can occur are: +"char" when text is typed on the keyboard. Argument is the character typed. +"key" when a key is pressed on the keyboard. Arguments are the keycode and whether the key is a repeat. Compare the keycode to the values in keys API to see which key was pressed. +"key_up" when a key is released on the keyboard. Argument is the numerical keycode. Compare to the values in keys API to see which key was released. +"paste" when text is pasted from the users keyboard. Argument is the line of text pasted. + +Events only on advanced computers: +"mouse_click" when a user clicks the mouse. Arguments are button, xPos, yPos. +"mouse_drag" when a user moves the mouse when held. Arguments are button, xPos, yPos. +"mouse_up" when a user releases the mouse button. Arguments are button, xPos, yPos. +"mouse_scroll" when a user uses the scrollwheel on the mouse. Arguments are direction, xPos, yPos. + +Other APIs and peripherals will emit their own events. See their respective help pages for details. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/excavate b/src/main/resources/assets/computercraft/lua/rom/help/excavate new file mode 100644 index 0000000000..fc868d378a --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/excavate @@ -0,0 +1,4 @@ +excavate is a program for Mining Turtles. When excavate is run, the turtle will mine a rectangular shaft into the ground, collecting blocks as it goes, and return to the surface once bedrock is hit. + +ex: +"excavate 3" will mine a 3x3 shaft. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/exec b/src/main/resources/assets/computercraft/lua/rom/help/exec new file mode 100644 index 0000000000..3e2e0429db --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/exec @@ -0,0 +1,7 @@ +On a Command Computer, "exec" will execute a command as if entered on a command block. Use "commands" to list all the available commands. + +ex: +"exec say Hello World" +"exec setblock ~0 ~1 ~0 minecraft:dirt" + +Type "help commandsapi" for help using commands in lua programs. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/exit b/src/main/resources/assets/computercraft/lua/rom/help/exit new file mode 100644 index 0000000000..9b6c4347f7 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/exit @@ -0,0 +1 @@ +exit will exit the current shell. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/falling b/src/main/resources/assets/computercraft/lua/rom/help/falling new file mode 100644 index 0000000000..ac25172445 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/falling @@ -0,0 +1 @@ +"From Russia with Fun" comes a fun, new, suspiciously-familiar falling block game for CraftOS. Only on Pocket Computers! diff --git a/src/main/resources/assets/computercraft/lua/rom/help/fg b/src/main/resources/assets/computercraft/lua/rom/help/fg new file mode 100644 index 0000000000..989efde676 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/fg @@ -0,0 +1,5 @@ +fg is a program for Advanced Computers which opens a new tab in the foreground. + +ex: +"fg" will open a foreground tab running the shell +"fg worm" will open a foreground tab running the "worm" program diff --git a/src/main/resources/assets/computercraft/lua/rom/help/fs b/src/main/resources/assets/computercraft/lua/rom/help/fs new file mode 100644 index 0000000000..400e5ba6f5 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/fs @@ -0,0 +1,39 @@ +Functions in the Filesystem API: +fs.list( path ) +fs.find( wildcard ) +fs.exists( path ) +fs.isDir( path ) +fs.isReadOnly( path ) +fs.getDir( path ) +fs.getName( path ) +fs.getSize( path ) +fs.getDrive( path ) +fs.getFreeSpace( path ) +fs.makeDir( path ) +fs.move( path, path ) +fs.copy( path, path ) +fs.delete( path ) +fs.combine( path, localpath ) +fs.open( path, mode ) +fs.complete( path, location ) +Available fs.open() modes are "r", "w", "a", "rb", "wb" and "ab". + +Functions on files opened with mode "r": +readLine() +readAll() +close() + +Functions on files opened with mode "w" or "a": +write( string ) +writeLine( string ) +flush() +close() + +Functions on files opened with mode "rb": +read() +close() + +Functions on files opened with mode "wb" or "ab": +write( byte ) +flush() +close() \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/go b/src/main/resources/assets/computercraft/lua/rom/help/go new file mode 100644 index 0000000000..c005a9a593 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/go @@ -0,0 +1,6 @@ +go is a program for Turtles, used to control the turtle without programming. It accepts one or more commands as a direction followed by a distance. + +ex: +"go forward" moves the turtle 1 space forward. +"go forward 3" moves the turtle 3 spaces forward. +"go forward 3 up left 2" moves the turtle 3 spaces forward, 1 spaces up, then left 180 degrees. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/gps b/src/main/resources/assets/computercraft/lua/rom/help/gps new file mode 100644 index 0000000000..e3e14b566f --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/gps @@ -0,0 +1,10 @@ +gps can be used to host a GPS server, or to determine a position using trilateration. +Type "help gpsapi" for help using GPS functions in lua programs. + +ex: +"gps locate" will connect to nearby GPS servers, and try to determine the position of the computer or turtle. +"gps host" will try to determine the position, and host a GPS server if successful. +"gps host 10 20 30" will host a GPS server, using the manually entered position 10,20,30. + +Take care when manually entering host positions. If the positions entered into multiple GPS hosts +are not consistent, the results of locate calls will be incorrect. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/gpsapi b/src/main/resources/assets/computercraft/lua/rom/help/gpsapi new file mode 100644 index 0000000000..7bb9fe601a --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/gpsapi @@ -0,0 +1,4 @@ +Functions in the GPS API: +gps.locate( timeout ) + +The locate function will send a signal to nearby gps servers, and wait for responses before the timeout. If it receives enough responses to determine this computers position then x, y and z co-ordinates will be returned, otherwise it will return nil. If GPS hosts do not have their positions configured correctly, results will be inaccurate. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/hello b/src/main/resources/assets/computercraft/lua/rom/help/hello new file mode 100644 index 0000000000..a58ae99082 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/hello @@ -0,0 +1 @@ +hello prints the text "Hello World!" to the screen. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/help b/src/main/resources/assets/computercraft/lua/rom/help/help new file mode 100644 index 0000000000..fe85a23709 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/help @@ -0,0 +1,4 @@ +help is the help tool you're currently using. +Type "help index" to see all help topics. +Type "help" to see the help intro. +Type "help helpapi" for information on the help Lua API. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/helpapi b/src/main/resources/assets/computercraft/lua/rom/help/helpapi new file mode 100644 index 0000000000..322ce03457 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/helpapi @@ -0,0 +1,5 @@ +Functions in the help API: +help.setPath( path ) +help.lookup( topic ) +help.topics() +help.completeTopic( topic ) diff --git a/src/main/resources/assets/computercraft/lua/rom/help/http b/src/main/resources/assets/computercraft/lua/rom/help/http new file mode 100644 index 0000000000..336496e268 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/http @@ -0,0 +1,8 @@ +Functions in the HTTP API: +http.checkURL( url ) +http.request( url, [postData], [headers] ) +http.get( url, [headers] ) +http.post( url, postData, [headers] ) + +The HTTP API may be disabled in ComputerCraft.cfg +A period of time after a http.request() call is made, a "http_success" or "http_failure" event will be raised. Arguments are the url and a file handle if successful. http.get() and http.post() block until this event fires instead. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/id b/src/main/resources/assets/computercraft/lua/rom/help/id new file mode 100644 index 0000000000..f87492bee9 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/id @@ -0,0 +1,5 @@ +id prints the unique identifier of this computer, or a Disk in an attached Disk Drive. + +ex: +"id" will print this Computers ID and label +"id left" will print the ID and label of the disk in the Disk Drive on the left \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/intro b/src/main/resources/assets/computercraft/lua/rom/help/intro new file mode 100644 index 0000000000..0165fbe667 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/intro @@ -0,0 +1,7 @@ +Welcome to CraftOS! +Type "programs" to see the programs you can run. +Type "help " to see help for a specific program. +Type "help programming" to learn about programming. +Type "help whatsnew" to find out about new features. +Type "help credits" to learn who made all this. +Type "help index" to see all help topics. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/io b/src/main/resources/assets/computercraft/lua/rom/help/io new file mode 100644 index 0000000000..f71cca207e --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/io @@ -0,0 +1,2 @@ +io is a standard Lua5.1 API, reimplemented for CraftOS. Not all the features are availiable. +Refer to http://www.lua.org/manual/5.1/ for more information. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/keys b/src/main/resources/assets/computercraft/lua/rom/help/keys new file mode 100644 index 0000000000..0adb2016cd --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/keys @@ -0,0 +1,9 @@ +The keys API contains constants for all the key codes that can be returned by the "key" event: + +Example usage: +local sEvent, nKey = os.pullEvent() +if sEvent == "key" and nKey == keys.enter then + -- Do something +end + +See http://www.minecraftwiki.net/wiki/Key_codes, or the source code, for a complete reference. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/label b/src/main/resources/assets/computercraft/lua/rom/help/label new file mode 100644 index 0000000000..7bacfbec1d --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/label @@ -0,0 +1,9 @@ +label gets or sets the label of the Computer, or of Floppy Disks in attached disk drives. + +ex: +"label get" prints the label of the computer. +"label get left" prints the label of the disk in the left drive. +"label set "My Computer"" set the label of the computer to "My Computer". +"label set left "My Programs"" - sets the label of the disk in the left drive to "My Programs". +"label clear" clears the label of the computer. +"label clear left" clears the label of the disk in the left drive. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/licenses/luaj b/src/main/resources/assets/computercraft/lua/rom/help/licenses/luaj new file mode 100644 index 0000000000..d50e90a170 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/licenses/luaj @@ -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. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/list b/src/main/resources/assets/computercraft/lua/rom/help/list new file mode 100644 index 0000000000..9ab8cd06c9 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/list @@ -0,0 +1 @@ +ls will list all the directories and files in the current location. Use "type" to find out if an item is a file or a directory. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/lua b/src/main/resources/assets/computercraft/lua/rom/help/lua new file mode 100644 index 0000000000..da1cb187ab --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/lua @@ -0,0 +1 @@ +lua is an interactive prompt for the lua programming language. It's a useful tool for learning the language. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/math b/src/main/resources/assets/computercraft/lua/rom/help/math new file mode 100644 index 0000000000..ed3da1e49a --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/math @@ -0,0 +1,2 @@ +math is a standard Lua5.1 API. +Refer to http://www.lua.org/manual/5.1/ for more information. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/mkdir b/src/main/resources/assets/computercraft/lua/rom/help/mkdir new file mode 100644 index 0000000000..e7268dc632 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/mkdir @@ -0,0 +1,5 @@ +mkdir creates a directory in the current location. + +ex: +"mkdir foo" creates a directory named "foo". +"mkdir ../foo" creates a directory named "foo" in the directory above the current directory. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/modems b/src/main/resources/assets/computercraft/lua/rom/help/modems new file mode 100644 index 0000000000..960bc50588 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/modems @@ -0,0 +1,12 @@ +Wired and Wireless Modems are peripheral devices available for CraftOS. Type "help peripheral" to learn about using the Peripheral API to connect with peripherals. When a Modem is connected, peripheral.getType() will return "modem". + +Methods exposed by Modems: +open( channel ) +isOpen( channel ) +close( channel ) +closeAll() +transmit( channel, replyChannel, message ) +isWireless() + +Events fired by Modems: +"modem_message" when a message is received on an open channel. Arguments are name, channel, replyChannel, message, distance \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/monitor b/src/main/resources/assets/computercraft/lua/rom/help/monitor new file mode 100644 index 0000000000..6837b38d4f --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/monitor @@ -0,0 +1,6 @@ +monitor will connect to an attached Monitor peripheral, and run a program on its display. +Type "help monitors" for help using monitors as peripherals in lua programs. + +ex: +"monitor left hello" will run the "hello" program on the monitor to the left of the computer. +"monitor top edit foo" will run the edit program on the top monitor, editing the file "foo". \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/monitors b/src/main/resources/assets/computercraft/lua/rom/help/monitors new file mode 100644 index 0000000000..f1a91e925b --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/monitors @@ -0,0 +1,21 @@ +The Monitor is a peripheral device available for CraftOS. Type "help peripheral" to learn about using the Peripheral API to connect with peripherals. When a Monitor is connected, peripheral.getType() will return "monitor". A wrapped monitor can be used with term.redirect() to send all terminal output to the monitor. + +Methods exposed by the Monitor: +write( text ) +blit( text, textColor, backgroundColor ) +clear() +clearLine() +getCursorPos() +setCursorPos( x, y ) +setCursorBlink( blink ) +isColor() +setTextColor( color ) +setBackgroundColor( color ) +getTextColor() +getBackgroundColor() +getSize() +scroll( n ) + +Events fired by the Monitor: +"monitor_touch" when an Advanced Monitor is touched by the player. Arguments are name, x, y +"monitor_resize" when the size of a Monitor changes. Argument is the name of the monitor. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/move b/src/main/resources/assets/computercraft/lua/rom/help/move new file mode 100644 index 0000000000..bc16f732a5 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/move @@ -0,0 +1,6 @@ +mv moves a file or directory from one location to another. + +ex: +"mv foo bar" renames the file "foo" to "bar". +"mv foo bar/foo" moves the file "foo" to a folder called "bar". +"mv disk/* disk2" moves the contents of one disk to another diff --git a/src/main/resources/assets/computercraft/lua/rom/help/multishell b/src/main/resources/assets/computercraft/lua/rom/help/multishell new file mode 100644 index 0000000000..b162431125 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/multishell @@ -0,0 +1,2 @@ +multishell is the toplevel program on Advanced Computers which manages background tabs. +Type "help shellapi" for information about the shell lua api. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/os b/src/main/resources/assets/computercraft/lua/rom/help/os new file mode 100644 index 0000000000..d4c6f75ccb --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/os @@ -0,0 +1,25 @@ +Functions in the os (Operating System) API: +os.version() +os.getComputerID() +os.getComputerLabel() +os.setComputerLabel() +os.run( environment, programpath, arguments ) +os.loadAPI( path ) +os.unloadAPI( name ) +os.pullEvent( [filter] ) +os.queueEvent( event, arguments ) +os.clock() +os.startTimer( timeout ) +os.cancelTimer( token ) +os.sleep( timeout ) +os.time() +os.day() +os.setAlarm( time ) +os.cancelAlarm( token ) +os.shutdown() +os.reboot() + +Events emitted by the os API: +"timer" when a timeout started by os.startTimer() completes. Argument is the token returned by os.startTimer(). +"alarm" when a time passed to os.setAlarm() is reached. Argument is the token returned by os.setAlarm(). +Type "help events" to learn about the event system. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/paint b/src/main/resources/assets/computercraft/lua/rom/help/paint new file mode 100644 index 0000000000..d845b664d9 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/paint @@ -0,0 +1,4 @@ +paint is a program for creating images on Advanced Computers. Select colors from the color pallette on the right, and click on the canvas to draw. Press Ctrl to access the menu and save your pictures. + +ex: +"edit mario" opens an image called "mario" for editing. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/paintutils b/src/main/resources/assets/computercraft/lua/rom/help/paintutils new file mode 100644 index 0000000000..d7e6d20423 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/paintutils @@ -0,0 +1,7 @@ +Functions in the Paint Utilities API: +paintutils.drawPixel( x, y, colour ) +paintutils.drawLine( startX, startY, endX, endY, colour ) +paintutils.drawBox( startX, startY, endX, endY, colour ) +paintutils.drawFilledBox( startX, startY, endX, endY, colour ) +paintutils.loadImage( path ) +paintutils.drawImage( image, x, y ) diff --git a/src/main/resources/assets/computercraft/lua/rom/help/parallel b/src/main/resources/assets/computercraft/lua/rom/help/parallel new file mode 100644 index 0000000000..822dd47a71 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/parallel @@ -0,0 +1,4 @@ +Functions in the Parallel API: +parallel.waitForAny( function1, function2, ... ) +parallel.waitForAll( function1, function2, ... ) +These methods provide an easy way to run multiple lua functions simultaneously. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/pastebin b/src/main/resources/assets/computercraft/lua/rom/help/pastebin new file mode 100644 index 0000000000..8f55898284 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/pastebin @@ -0,0 +1,7 @@ +pastebin is a program for uploading files to and downloading files from pastebin.com. This is useful for sharing programs with other players. +The HTTP API must be enabled in ComputerCraft.cfg to use this program. + +ex: +"pastebin put foo" will upload the file "foo" to pastebin.com, and print the URL. +"pastebin get xq5gc7LB foo" will download the file from the URL http://pastebin.com/xq5gc7LB, and save it as "foo". +"pastebin run CxaWmPrX" will download the file from the URL http://pastebin.com/CxaWmPrX, and immediately run it. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/peripheral b/src/main/resources/assets/computercraft/lua/rom/help/peripheral new file mode 100644 index 0000000000..2b02b0a903 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/peripheral @@ -0,0 +1,15 @@ +The peripheral API is for interacting with external peripheral devices. Type "help peripherals" to learn about the peripherals available. + +Functions in the peripheral API: +peripheral.getNames() +peripheral.isPresent( name ) +peripheral.getType( name ) +peripheral.getMethods( name ) +peripheral.call( name, methodName, param1, param2, etc ) +peripheral.wrap( name ) +peripheral.find( type, [fnFilter] ) + +Events fired by the peripheral API: +"peripheral" when a new peripheral is attached. Argument is the name. +"peripheral_detach" when a peripheral is removed. Argument is the name. +Type "help events" to learn about the event system. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/peripherals b/src/main/resources/assets/computercraft/lua/rom/help/peripherals new file mode 100644 index 0000000000..7cea884e2f --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/peripherals @@ -0,0 +1,7 @@ +The "peripherals" program will list all of the peripheral devices accessible from this computer. +Peripherals are external devices which CraftOS Computers and Turtles can interact with using the peripheral API. +Type "help peripheral" to learn about using the peripheral API. +Type "help drives" to learn about using Disk Drives. +Type "help modems" to learn about using Modems. +Type "help monitors" to learn about using Monitors. +Type "help printers" to learn about using Printers. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/printers b/src/main/resources/assets/computercraft/lua/rom/help/printers new file mode 100644 index 0000000000..a855ab972e --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/printers @@ -0,0 +1,12 @@ +The Printer is a peripheral device available for CraftOS. Type "help peripheral" to learn about using the Peripheral API to connect with peripherals. When a Printer is connected, peripheral.getType() will return "printer". + +Methods exposed by the Printer: +getInkLevel() +getPaperLevel() +newPage() +setPageTitle( title ) +getPageSize() +setCursorPos( x, y ) +getCursorPos() +write( text ) +endPage() \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/programming b/src/main/resources/assets/computercraft/lua/rom/help/programming new file mode 100644 index 0000000000..68e8621fc5 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/programming @@ -0,0 +1,11 @@ +To learn the lua programming language, visit http://lua-users.org/wiki/TutorialDirectory. + +To experiment with lua in CraftOS, run the "lua" program and start typing code. +To create programs, use "edit" to create files, then type their names in the shell to run them. If you name a program "startup" and place it in the root or on a disk drive, it will run automatically when the computer starts. + +To terminate a program stuck in a loop, hold Ctrl+T for 1 second. +To quickly shutdown a computer, hold Ctrl+S for 1 second. +To quickly reboot a computer, hold Ctrl+R for 1 second. + +To learn about the programming APIs availiable, type "apis" or "help apis". +If you get stuck, visit the forums at http://www.computercraft.info/ for advice and tutorials. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/programs b/src/main/resources/assets/computercraft/lua/rom/help/programs new file mode 100644 index 0000000000..e1bc3c575a --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/programs @@ -0,0 +1 @@ +programs lists all the programs on the rom of the computer. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/reboot b/src/main/resources/assets/computercraft/lua/rom/help/reboot new file mode 100644 index 0000000000..6cae9184df --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/reboot @@ -0,0 +1,2 @@ +reboot will turn the computer off and on again. +You can also hold Ctrl+R at any time to quickly reboot. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/redirection b/src/main/resources/assets/computercraft/lua/rom/help/redirection new file mode 100644 index 0000000000..01ec7dfb3d --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/redirection @@ -0,0 +1,2 @@ +Redirection ComputerCraft Edition is the CraftOS version of a fun new puzzle game by Dan200, the author of ComputerCraft. +Play it on any Advanced Computer, then visit http://www.redirectiongame.com to play the full game! diff --git a/src/main/resources/assets/computercraft/lua/rom/help/rednet b/src/main/resources/assets/computercraft/lua/rom/help/rednet new file mode 100644 index 0000000000..ddff18b2f8 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/rednet @@ -0,0 +1,18 @@ +The rednet API provides a simple computer networking model using modems. + +Functions in the rednet API: +rednet.open( side ) +rednet.close( [side] ) +rednet.isOpen( [side] ) +rednet.send( receiverID, message, [protocol] ) -- Send to a specific computer +rednet.broadcast( message, [protocol] ) -- Send to all computers +rednet.receive( [protocol], [timeout] ) -- Returns: senderID, message, protocol +rednet.host( protocol, hostname ) +rednet.unhost( protocol ) +rednet.lookup( protocol, [hostname] ) -- Returns: ID + +Events fired by the rednet API: +"rednet_message" when a message is received. Arguments are senderID, message, protocol +Type "help events" to learn about the event system. + +Rednet is not the only way to use modems for networking. Interfacing with the modem directly using the peripheral API and listening for the "modem_message" event allows for lower level control, at the expense of powerful high level networking features. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/redstone b/src/main/resources/assets/computercraft/lua/rom/help/redstone new file mode 100644 index 0000000000..ea76f7827e --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/redstone @@ -0,0 +1,9 @@ +The redstone program can be used to get, set or pulse redstone inputs and outputs from the computer. + +ex: +"redstone probe" will list all the redstone inputs to the computer +"redstone set left true" turns on the left redstone output. +"redstone set right blue false" turns off the blue wire in the bundled cable on the right redstone output. +"redstone pulse front 10 1" emits 10 one second redstone pulses on the front redstone output. + +Type "help redstoneapi" or "help rs" for information on the redstone Lua API. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/redstoneapi b/src/main/resources/assets/computercraft/lua/rom/help/redstoneapi new file mode 100644 index 0000000000..a8db92dcf6 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/redstoneapi @@ -0,0 +1,19 @@ +Functions in the Redstone API: +redstone.getSides( ) +redstone.getInput( side ) +redstone.setOutput( side, boolean ) +redstone.getOutput( side ) +redstone.getAnalogInput( side ) +redstone.setAnalogOutput( side, number ) +redstone.getAnalogOutput( side ) + +Functions in the Redstone API for working with bundled cables: +redstone.getBundledInput( side ) +redstone.testBundledInput( side, color ) +redstone.setBundledOutput( side, colors ) +redstone.getBundledOutput( side ) +Type "help bundled" for usage examples. + +Events emitted by the redstone API: +"redstone", when the state of any redstone input changes. Use getInput() or getBundledInput() to inspect the changes +Type "help events" to learn about the event system. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/refuel b/src/main/resources/assets/computercraft/lua/rom/help/refuel new file mode 100644 index 0000000000..9fab3fa189 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/refuel @@ -0,0 +1,6 @@ +refuel is a program for Turtles. Refuel will consume items from the inventory as fuel for turtle. + +ex: +"refuel" will refuel with at most one fuel item +"refuel 10" will refuel with at most 10 fuel items +"refuel all" will refuel with as many fuel items as possible \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/rename b/src/main/resources/assets/computercraft/lua/rom/help/rename new file mode 100644 index 0000000000..a050c81c07 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/rename @@ -0,0 +1,4 @@ +rename renames a file or directory. + +ex: +"rename foo bar" renames the file "foo" to "bar". diff --git a/src/main/resources/assets/computercraft/lua/rom/help/repeat b/src/main/resources/assets/computercraft/lua/rom/help/repeat new file mode 100644 index 0000000000..f65697d4a3 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/repeat @@ -0,0 +1 @@ +repeat is a program for repeating rednet messages across long distances. To use, connect 2 or more modems to a computer and run the "repeat" program; from then on, any rednet message sent from any computer in wireless range or connected by networking cable to either of the modems will be repeated to those on the other side. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/rs b/src/main/resources/assets/computercraft/lua/rom/help/rs new file mode 100644 index 0000000000..5b8909d071 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/rs @@ -0,0 +1,19 @@ +Functions in the Redstone API: +rs.getSides( ) +rs.getInput( side ) +rs.setOutput( side, boolean ) +rs.getOutput( side ) +rs.getAnalogInput( side ) +rs.setAnalogOutput( side, number ) +rs.getAnalogOutput( side ) + +Functions in the Redstone API for working with RedPower bundled cables: +rs.getBundledInput( side ) +rs.testBundledInput( side, color ) +rs.setBundledOutput( side, colors ) +rs.getBundledOutput( side ) +Type "help bundled" for usage examples. + +Events emitted by the redstone API: +"redstone", when the state of any redstone input changes. Use getInput() or getBundledInput() to inspect the changes +Type "help events" to learn about the event system. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/set b/src/main/resources/assets/computercraft/lua/rom/help/set new file mode 100644 index 0000000000..7e1d93cf08 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/set @@ -0,0 +1,6 @@ +The set program can be used to inspect and change system settings. + +Usage: +"set" will print all the system settings and their values +"set foo" will print the value of the system setting "foo" +"set foo bar" will set the value of the system setting "foo" to "bar" diff --git a/src/main/resources/assets/computercraft/lua/rom/help/settings b/src/main/resources/assets/computercraft/lua/rom/help/settings new file mode 100644 index 0000000000..a44fd85a20 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/settings @@ -0,0 +1,8 @@ +Functions in the Settings API: +settings.get( name, [default] ) +settings.set( name, value ) +settings.unset( name ) +settings.load( path ) +settings.save( path ) +settings.clear() +settings.getNames() diff --git a/src/main/resources/assets/computercraft/lua/rom/help/shell b/src/main/resources/assets/computercraft/lua/rom/help/shell new file mode 100644 index 0000000000..080b8390ab --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/shell @@ -0,0 +1,2 @@ +shell is the toplevel program which interprets commands and runs program. +Type "help shellapi" for information about the shell lua api. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/shellapi b/src/main/resources/assets/computercraft/lua/rom/help/shellapi new file mode 100644 index 0000000000..287c4dc7a5 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/shellapi @@ -0,0 +1,19 @@ +Functions in the Shell API: +shell.exit() +shell.dir() +shell.setDir( path ) +shell.path() +shell.setPath( path ) +shell.resolve( localpath ) +shell.resolveProgram( name ) +shell.aliases() +shell.setAlias( alias, command ) +shell.clearAlias( alias ) +shell.programs() +shell.run( program, arguments ) +shell.getRunningProgram() +shell.complete( line ) +shell.completeProgram( program ) +shell.setCompletionFunction( program, fnComplete ) +shell.openTab( program, arguments ) (Advanced Computer required) +shell.switchTab( n ) (Advanced Computer required) diff --git a/src/main/resources/assets/computercraft/lua/rom/help/shutdown b/src/main/resources/assets/computercraft/lua/rom/help/shutdown new file mode 100644 index 0000000000..4a63391db0 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/shutdown @@ -0,0 +1 @@ +shutdown will turn off the computer. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/sleep b/src/main/resources/assets/computercraft/lua/rom/help/sleep new file mode 100644 index 0000000000..5d10ccb9b3 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/sleep @@ -0,0 +1,4 @@ +sleep makes the computer idle for a specific number of seconds. + +ex: +"sleep 10" puts the computer to sleep for 10 seconds \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/string b/src/main/resources/assets/computercraft/lua/rom/help/string new file mode 100644 index 0000000000..5dfe5d5013 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/string @@ -0,0 +1,2 @@ +string is a standard Lua5.1 API. +Refer to http://www.lua.org/manual/5.1/ for more information. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/table b/src/main/resources/assets/computercraft/lua/rom/help/table new file mode 100644 index 0000000000..80760d0dee --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/table @@ -0,0 +1,2 @@ +table is a standard Lua5.1 API. +Refer to http://www.lua.org/manual/5.1/ for more information. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/term b/src/main/resources/assets/computercraft/lua/rom/help/term new file mode 100644 index 0000000000..268b9cdf66 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/term @@ -0,0 +1,20 @@ +Functions in the Terminal API: +term.write( text ) +term.blit( text, textColor, backgroundColor ) +term.clear() +term.clearLine() +term.getCursorPos() +term.setCursorPos( x, y ) +term.setCursorBlink( blink ) +term.isColor() +term.setTextColor( color ) +term.setBackgroundColor( color ) +term.getTextColor() +term.getBackgroundColor() +term.getSize() +term.scroll( n ) +term.redirect( object ) +term.current() + +Events emitted by the terminals: +"term_resize", when the size of a terminal changes. This can happen in multitasking environments, or when the terminal out is being redirected by the "monitor" program. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/textutils b/src/main/resources/assets/computercraft/lua/rom/help/textutils new file mode 100644 index 0000000000..ee91a883fd --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/textutils @@ -0,0 +1,10 @@ +Functions in the Text Utilities API: +textutils.slowPrint( text ) +textutils.tabulate( table, table2, ... ) +textutils.pagedTabulate( table, table2, ... ) +textutils.formatTime( time, bTwentyFourHour ) +textutils.serialize( table ) +textutils.unserialize( string ) +textutils.serializeJSON( table, [useNBTStyle] ) +textutils.urlEncode( string ) +textutils.complete( string, table ) diff --git a/src/main/resources/assets/computercraft/lua/rom/help/time b/src/main/resources/assets/computercraft/lua/rom/help/time new file mode 100644 index 0000000000..ae51135998 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/time @@ -0,0 +1 @@ +time prints the current time of day. \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/tunnel b/src/main/resources/assets/computercraft/lua/rom/help/tunnel new file mode 100644 index 0000000000..07d05c482d --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/tunnel @@ -0,0 +1,4 @@ +tunnel is a program for Mining Turtles. Tunnel will mine a 3x2 tunnel of the depth specified. + +ex: +"tunnel 20" will tunnel a tunnel 20 blocks long. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/turn b/src/main/resources/assets/computercraft/lua/rom/help/turn new file mode 100644 index 0000000000..15782e3489 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/turn @@ -0,0 +1,6 @@ +turn is a program for Turtles, used to turn the turtle around without programming. It accepts one or more commands as a direction and a number of turns. The "go" program can also be used for turning. + +ex: +"turn left" turns the turtle 90 degrees left. +"turn right 2" turns the turtle 180 degrees right. +"turn left 2 right" turns left 180 degrees, then right 90 degrees. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/turtle b/src/main/resources/assets/computercraft/lua/rom/help/turtle new file mode 100644 index 0000000000..aad6cf5d48 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/turtle @@ -0,0 +1,48 @@ +turtle is an api availiable on Turtles, which controls their movement. +Functions in the Turtle API: +turtle.forward() +turtle.back() +turtle.up() +turtle.down() +turtle.turnLeft() +turtle.turnRight() +turtle.select( slotNum ) +turtle.getSelectedSlot() +turtle.getItemCount( [slotNum] ) +turtle.getItemSpace( [slotNum] ) +turtle.getItemDetail( [slotNum] ) +turtle.equipLeft() +turtle.equipRight() +turtle.dig( [toolSide] ) +turtle.digUp( [toolSide] ) +turtle.digDown( [toolSide] ) +turtle.place() +turtle.placeUp() +turtle.placeDown() +turtle.attack( [toolSide] ) +turtle.attackUp( [toolSide] ) +turtle.attackDown( [toolSide] ) +turtle.detect() +turtle.detectUp() +turtle.detectDown() +turtle.compare() +turtle.compareUp() +turtle.compareDown() +turtle.inspect() +turtle.inspectUp() +turtle.inspectDown() +turtle.compareTo( slotNum ) +turtle.transferTo( slotNum, [quantity] ) +turtle.drop( [quantity] ) +turtle.dropUp( [quantity] ) +turtle.dropDown( [quantity] ) +turtle.suck( [quantity] ) +turtle.suckUp( [quantity] ) +turtle.suckDown( [quantity] ) +turtle.getFuelLevel() +turtle.getFuelLimit() +turtle.refuel( [quantity] ) +turtle.craft( [quantity] ) (requires Crafty Turtle) + +Events fired by the Turtle API: +"turtle_inventory" when any of the items in the inventory are changed. Use comparison operations to inspect the changes. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/type b/src/main/resources/assets/computercraft/lua/rom/help/type new file mode 100644 index 0000000000..74a4e8e791 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/type @@ -0,0 +1 @@ +type determines the type of a file or directory. Prints "file", "directory" or "does not exist". \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/help/unequip b/src/main/resources/assets/computercraft/lua/rom/help/unequip new file mode 100644 index 0000000000..f1d8169b4d --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/unequip @@ -0,0 +1,4 @@ +unequip is a program for Turtles. unequip will remove tools of peripherals from the specified side of the turtle. + +ex: +"unequip left" will remove the item on the left side of the turtle diff --git a/src/main/resources/assets/computercraft/lua/rom/help/vector b/src/main/resources/assets/computercraft/lua/rom/help/vector new file mode 100644 index 0000000000..b85a373d3d --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/vector @@ -0,0 +1,17 @@ +Functions in the 3D Vector Math API: +vector.new( x,y,z ) + +Vectors returned by vector.new() have the following fields and methods: +vector.x +vector.y +vector.z +vector:add( vector ) +vector:sub( vector ) +vector:mul( number ) +vector:dot( vector ) +vector:cross( vector ) +vector:length() +vector:normalize() +vector:round() +vector:tostring() +The +, - and * operators can also be used on vectors. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/wget b/src/main/resources/assets/computercraft/lua/rom/help/wget new file mode 100644 index 0000000000..f4d2a81b28 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/wget @@ -0,0 +1,5 @@ +wget is a program for downloading files from the internet. This is useful for downloading programs created by other players. +The HTTP API must be enabled in ComputerCraft.cfg to use this program. + +ex: +"wget http://pastebin.com/raw/CxaWmPrX test" will download the file from the URL http://pastebin.com/raw/CxaWmPrX, and save it as "test". diff --git a/src/main/resources/assets/computercraft/lua/rom/help/whatsnew b/src/main/resources/assets/computercraft/lua/rom/help/whatsnew new file mode 100644 index 0000000000..f2bc578541 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/whatsnew @@ -0,0 +1,6 @@ +New Features in ComputerCraft 1.79: + +* Ported ComputerCraftEdu to Minecraft 1.8.9 +* Fixed a handful of bugs in ComputerCraft + +Type "help changelog" to see the full version history. diff --git a/src/main/resources/assets/computercraft/lua/rom/help/window b/src/main/resources/assets/computercraft/lua/rom/help/window new file mode 100644 index 0000000000..0b33ae5617 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/window @@ -0,0 +1,23 @@ +Functions in the window API: +window.create( parent, x, y, width, height, visible ) + +Windows created with the window API have the following methods: +write( text ) +blit( text, textColor, backgroundColor ) +clear() +clearLine() +getCursorPos() +setCursorPos( x, y ) +setCursorBlink( blink ) +isColor() +setTextColor( color ) +setBackgroundColor( color ) +getTextColor() +getBackgroundColor() +getSize() +scroll( n ) +setVisible( bVisible ) +redraw() +restoreCursor() +getPosition() +reposition( x, y, width, height ) diff --git a/src/main/resources/assets/computercraft/lua/rom/help/workbench b/src/main/resources/assets/computercraft/lua/rom/help/workbench new file mode 100644 index 0000000000..b6b1e96824 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/workbench @@ -0,0 +1,4 @@ +Workbenches are peripheral devices found on Crafty Turtles running CraftOS. Type "help peripheral" to learn about using the Peripheral API to connect with peripherals. When a workbench is attached to a turtle, peripheral.getType() will return "workbench". + +Methods exposed by Workbenches: +craft( channel ) diff --git a/src/main/resources/assets/computercraft/lua/rom/help/worm b/src/main/resources/assets/computercraft/lua/rom/help/worm new file mode 100644 index 0000000000..366ad3996e --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/help/worm @@ -0,0 +1 @@ +You've played it in the arcades, now experience the high-octane thrills of the hit game "WORM!" on your home computer! Only on CraftOS! diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/advanced/bg b/src/main/resources/assets/computercraft/lua/rom/programs/advanced/bg new file mode 100644 index 0000000000..41072a70ae --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/advanced/bg @@ -0,0 +1,12 @@ + +if not shell.openTab then + printError( "Requires multishell" ) + return +end + +local tArgs = { ... } +if #tArgs > 0 then + shell.openTab( table.unpack( tArgs ) ) +else + shell.openTab( "shell" ) +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/advanced/fg b/src/main/resources/assets/computercraft/lua/rom/programs/advanced/fg new file mode 100644 index 0000000000..9eb4f968f2 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/advanced/fg @@ -0,0 +1,18 @@ + +if not shell.openTab then + printError( "Requires multishell" ) + return +end + +local tArgs = { ... } +if #tArgs > 0 then + local nTask = shell.openTab( table.unpack( tArgs ) ) + if nTask then + shell.switchTab( nTask ) + end +else + local nTask = shell.openTab( "shell" ) + if nTask then + shell.switchTab( nTask ) + end +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/advanced/multishell b/src/main/resources/assets/computercraft/lua/rom/programs/advanced/multishell new file mode 100644 index 0000000000..cf73b35bde --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/advanced/multishell @@ -0,0 +1,306 @@ + +-- Setup process switching +local parentTerm = term.current() +local w,h = parentTerm.getSize() + +local tProcesses = {} +local nCurrentProcess = nil +local nRunningProcess = nil +local bShowMenu = false +local bWindowsResized = false + +local function selectProcess( n ) + if nCurrentProcess ~= n then + if nCurrentProcess then + local tOldProcess = tProcesses[ nCurrentProcess ] + tOldProcess.window.setVisible( false ) + end + nCurrentProcess = n + if nCurrentProcess then + local tNewProcess = tProcesses[ nCurrentProcess ] + tNewProcess.window.setVisible( true ) + tNewProcess.bInteracted = true + end + end +end + +local function setProcessTitle( n, sTitle ) + tProcesses[ n ].sTitle = sTitle +end + +local function resumeProcess( nProcess, sEvent, ... ) + local tProcess = tProcesses[ nProcess ] + local sFilter = tProcess.sFilter + if sFilter == nil or sFilter == sEvent or sEvent == "terminate" then + local nPreviousProcess = nRunningProcess + nRunningProcess = nProcess + term.redirect( tProcess.terminal ) + local ok, result = coroutine.resume( tProcess.co, sEvent, ... ) + tProcess.terminal = term.current() + if ok then + tProcess.sFilter = result + else + printError( result ) + end + nRunningProcess = nPreviousProcess + end +end + +local function launchProcess( tProgramEnv, sProgramPath, ... ) + local tProgramArgs = { ... } + local nProcess = #tProcesses + 1 + local tProcess = {} + tProcess.sTitle = fs.getName( sProgramPath ) + if bShowMenu then + tProcess.window = window.create( parentTerm, 1, 2, w, h-1, false ) + else + tProcess.window = window.create( parentTerm, 1, 1, w, h, false ) + end + tProcess.co = coroutine.create( function() + os.run( tProgramEnv, sProgramPath, table.unpack( tProgramArgs ) ) + if not tProcess.bInteracted then + term.setCursorBlink( false ) + print( "Press any key to continue" ) + os.pullEvent( "char" ) + end + end ) + tProcess.sFilter = nil + tProcess.terminal = tProcess.window + tProcess.bInteracted = false + tProcesses[ nProcess ] = tProcess + resumeProcess( nProcess ) + return nProcess +end + +local function cullProcess( nProcess ) + local tProcess = tProcesses[ nProcess ] + if coroutine.status( tProcess.co ) == "dead" then + if nCurrentProcess == nProcess then + selectProcess( nil ) + end + table.remove( tProcesses, nProcess ) + if nCurrentProcess == nil then + if nProcess > 1 then + selectProcess( nProcess - 1 ) + elseif #tProcesses > 0 then + selectProcess( 1 ) + end + end + return true + end + return false +end + +local function cullProcesses() + local culled = false + for n=#tProcesses,1,-1 do + culled = culled or cullProcess( n ) + end + return culled +end + +-- Setup the main menu +local menuMainTextColor, menuMainBgColor, menuOtherTextColor, menuOtherBgColor +if parentTerm.isColor() then + menuMainTextColor, menuMainBgColor = colors.yellow, colors.black + menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray +else + menuMainTextColor, menuMainBgColor = colors.white, colors.black + menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray +end + +local function redrawMenu() + if bShowMenu then + -- Draw menu + parentTerm.setCursorPos( 1, 1 ) + parentTerm.setBackgroundColor( menuOtherBgColor ) + parentTerm.clearLine() + for n=1,#tProcesses do + if n == nCurrentProcess then + parentTerm.setTextColor( menuMainTextColor ) + parentTerm.setBackgroundColor( menuMainBgColor ) + else + parentTerm.setTextColor( menuOtherTextColor ) + parentTerm.setBackgroundColor( menuOtherBgColor ) + end + parentTerm.write( " " .. tProcesses[n].sTitle .. " " ) + end + + -- Put the cursor back where it should be + local tProcess = tProcesses[ nCurrentProcess ] + if tProcess then + tProcess.window.restoreCursor() + end + end +end + +local function resizeWindows() + local windowY, windowHeight + if bShowMenu then + windowY = 2 + windowHeight = h-1 + else + windowY = 1 + windowHeight = h + end + for n=1,#tProcesses do + local tProcess = tProcesses[n] + local window = tProcess.window + local x,y = tProcess.window.getCursorPos() + if y > windowHeight then + tProcess.window.scroll( y - windowHeight ) + tProcess.window.setCursorPos( x, windowHeight ) + end + tProcess.window.reposition( 1, windowY, w, windowHeight ) + end + bWindowsResized = true +end + +local function setMenuVisible( bVis ) + if bShowMenu ~= bVis then + bShowMenu = bVis + resizeWindows() + redrawMenu() + end +end + +local multishell = {} + +function multishell.getFocus() + return nCurrentProcess +end + +function multishell.setFocus( n ) + if n >= 1 and n <= #tProcesses then + selectProcess( n ) + redrawMenu() + return true + end + return false +end + +function multishell.getTitle( n ) + if n >= 1 and n <= #tProcesses then + return tProcesses[n].sTitle + end + return nil +end + +function multishell.setTitle( n, sTitle ) + if n >= 1 and n <= #tProcesses then + setProcessTitle( n, sTitle ) + redrawMenu() + end +end + +function multishell.getCurrent() + return nRunningProcess +end + +function multishell.launch( tProgramEnv, sProgramPath, ... ) + local previousTerm = term.current() + setMenuVisible( (#tProcesses + 1) >= 2 ) + local nResult = launchProcess( tProgramEnv, sProgramPath, ... ) + redrawMenu() + term.redirect( previousTerm ) + return nResult +end + +function multishell.getCount() + return #tProcesses +end + +-- Begin +parentTerm.clear() +setMenuVisible( false ) +selectProcess( launchProcess( { + ["shell"] = shell, + ["multishell"] = multishell, +}, "/rom/programs/shell" ) ) +redrawMenu() + +-- Run processes +while #tProcesses > 0 do + -- Get the event + local tEventData = { os.pullEventRaw() } + local sEvent = tEventData[1] + if sEvent == "term_resize" then + -- Resize event + w,h = parentTerm.getSize() + resizeWindows() + redrawMenu() + + elseif sEvent == "char" or sEvent == "key" or sEvent == "key_up" or sEvent == "paste" or sEvent == "terminate" then + -- Keyboard event + -- Passthrough to current process + resumeProcess( nCurrentProcess, table.unpack( tEventData ) ) + if cullProcess( nCurrentProcess ) then + setMenuVisible( #tProcesses >= 2 ) + redrawMenu() + end + + elseif sEvent == "mouse_click" then + -- Click event + local button, x, y = tEventData[2], tEventData[3], tEventData[4] + if bShowMenu and y == 1 then + -- Switch process + local tabStart = 1 + for n=1,#tProcesses do + tabEnd = tabStart + string.len( tProcesses[n].sTitle ) + 1 + if x >= tabStart and x <= tabEnd then + selectProcess( n ) + redrawMenu() + break + end + tabStart = tabEnd + 1 + end + else + -- Passthrough to current process + resumeProcess( nCurrentProcess, sEvent, button, x, (bShowMenu and y-1) or y ) + if cullProcess( nCurrentProcess ) then + setMenuVisible( #tProcesses >= 2 ) + redrawMenu() + end + end + + elseif sEvent == "mouse_drag" or sEvent == "mouse_up" or sEvent == "mouse_scroll" then + -- Other mouse event + local p1, x, y = tEventData[2], tEventData[3], tEventData[4] + if not (bShowMenu and y == 1) then + -- Passthrough to current process + resumeProcess( nCurrentProcess, sEvent, p1, x, (bShowMenu and y-1) or y ) + if cullProcess( nCurrentProcess ) then + setMenuVisible( #tProcesses >= 2 ) + redrawMenu() + end + end + + else + -- Other event + -- Passthrough to all processes + local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event + for n=1,nLimit do + resumeProcess( n, table.unpack( tEventData ) ) + end + if cullProcesses() then + setMenuVisible( #tProcesses >= 2 ) + redrawMenu() + end + end + + if bWindowsResized then + -- Pass term_resize to all processes + local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event + for n=1,nLimit do + resumeProcess( n, "term_resize" ) + end + bWindowsResized = false + if cullProcesses() then + setMenuVisible( #tProcesses >= 2 ) + redrawMenu() + end + end +end + +-- Shutdown +term.redirect( parentTerm ) diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/alias b/src/main/resources/assets/computercraft/lua/rom/programs/alias new file mode 100644 index 0000000000..a748659912 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/alias @@ -0,0 +1,27 @@ + +local tArgs = { ... } +if #tArgs > 2 then + print( "Usage: alias " ) + return +end + +local sAlias = tArgs[1] +local sProgram = tArgs[2] + +if sAlias and sProgram then + -- Set alias + shell.setAlias( sAlias, sProgram ) +elseif sAlias then + -- Clear alias + shell.clearAlias( sAlias ) +else + -- List aliases + local tAliases = shell.aliases() + local tList = {} + for sAlias, sCommand in pairs( tAliases ) do + table.insert( tList, sAlias ) + end + table.sort( tList ) + textutils.pagedTabulate( tList ) +end + \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/apis b/src/main/resources/assets/computercraft/lua/rom/programs/apis new file mode 100644 index 0000000000..5ce20526f7 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/apis @@ -0,0 +1,11 @@ + +local tApis = {} +for k,v in pairs( _G ) do + if type(k) == "string" and type(v) == "table" and k ~= "_G" then + table.insert( tApis, k ) + end +end +table.insert( tApis, "shell" ) +table.sort( tApis ) + +textutils.pagedTabulate( tApis ) diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/cd b/src/main/resources/assets/computercraft/lua/rom/programs/cd new file mode 100644 index 0000000000..aa6a395061 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/cd @@ -0,0 +1,14 @@ + +local tArgs = { ... } +if #tArgs < 1 then + print( "Usage: cd " ) + return +end + +local sNewDir = shell.resolve( tArgs[1] ) +if fs.isDir( sNewDir ) then + shell.setDir( sNewDir ) +else + print( "Not a directory" ) + return +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/clear b/src/main/resources/assets/computercraft/lua/rom/programs/clear new file mode 100644 index 0000000000..50283c8d71 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/clear @@ -0,0 +1,2 @@ +term.clear() +term.setCursorPos( 1, 1 ) diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/command/commands b/src/main/resources/assets/computercraft/lua/rom/programs/command/commands new file mode 100644 index 0000000000..230d766f7d --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/command/commands @@ -0,0 +1,16 @@ + +if not commands then + printError( "Requires a Command Computer." ) + return +end + +local tCommands = commands.list() +table.sort( tCommands ) + +if term.isColor() then + term.setTextColor( colors.green ) +end +print( "Available commands:" ) +term.setTextColor( colors.white ) + +textutils.pagedTabulate( tCommands ) diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/command/exec b/src/main/resources/assets/computercraft/lua/rom/programs/command/exec new file mode 100644 index 0000000000..76aebc0862 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/command/exec @@ -0,0 +1,40 @@ + +local tArgs = { ... } +if not commands then + printError( "Requires a Command Computer." ) + return +end +if #tArgs == 0 then + printError( "Usage: exec " ) + return +end + +local function printSuccess( text ) + if term.isColor() then + term.setTextColor( colors.green ) + end + print( text ) + term.setTextColor( colors.white ) +end + +local sCommand = string.lower( tArgs[1] ) +for n=2,#tArgs do + sCommand = sCommand .. " " .. tArgs[n] +end + +local bResult, tOutput = commands.exec( sCommand ) +if bResult then + printSuccess( "Success" ) + if #tOutput > 0 then + for n=1,#tOutput do + print( tOutput[n] ) + end + end +else + printError( "Failed" ) + if #tOutput > 0 then + for n=1,#tOutput do + print( tOutput[n] ) + end + end +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/copy b/src/main/resources/assets/computercraft/lua/rom/programs/copy new file mode 100644 index 0000000000..8d08e9c7e6 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/copy @@ -0,0 +1,24 @@ + +local tArgs = { ... } +if #tArgs < 2 then + print( "Usage: cp " ) + return +end + +local sSource = shell.resolve( tArgs[1] ) +local sDest = shell.resolve( tArgs[2] ) +local tFiles = fs.find( sSource ) +if #tFiles > 0 then + for n,sFile in ipairs( tFiles ) do + if fs.isDir( sDest ) then + fs.copy( sFile, fs.combine( sDest, fs.getName(sFile) ) ) + elseif #tFiles == 1 then + fs.copy( sFile, sDest ) + else + printError( "Cannot overwrite file multiple times" ) + return + end + end +else + printError( "No matching files" ) +end \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/delete b/src/main/resources/assets/computercraft/lua/rom/programs/delete new file mode 100644 index 0000000000..66d834db44 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/delete @@ -0,0 +1,16 @@ + +local tArgs = { ... } +if #tArgs < 1 then + print( "Usage: rm " ) + return +end + +local sPath = shell.resolve( tArgs[1] ) +local tFiles = fs.find( sPath ) +if #tFiles > 0 then + for n,sFile in ipairs( tFiles ) do + fs.delete( sFile ) + end +else + printError( "No matching files" ) +end \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/drive b/src/main/resources/assets/computercraft/lua/rom/programs/drive new file mode 100644 index 0000000000..aa763ffbd2 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/drive @@ -0,0 +1,21 @@ +local tArgs = { ... } + +-- Get where a directory is mounted +local sPath = shell.dir() +if tArgs[1] ~= nil then + sPath = shell.resolve( tArgs[1] ) +end + +if fs.exists( sPath ) then + write( fs.getDrive( sPath ) .. " (" ) + local nSpace = fs.getFreeSpace( sPath ) + if nSpace >= 1000 * 1000 then + print( (math.floor( nSpace / (100 * 1000) ) / 10) .. "MB remaining)" ) + elseif nSpace >= 1000 then + print( (math.floor( nSpace / 100 ) / 10) .. "KB remaining)" ) + else + print( nSpace .. "B remaining)" ) + end +else + print( "No such path" ) +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/edit b/src/main/resources/assets/computercraft/lua/rom/programs/edit new file mode 100644 index 0000000000..472017c136 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/edit @@ -0,0 +1,753 @@ +-- Get file to edit +local tArgs = { ... } +if #tArgs == 0 then + print( "Usage: edit " ) + return +end + +-- Error checking +local sPath = shell.resolve( tArgs[1] ) +local bReadOnly = fs.isReadOnly( sPath ) +if fs.exists( sPath ) and fs.isDir( sPath ) then + print( "Cannot edit a directory." ) + return +end + +local x,y = 1,1 +local w,h = term.getSize() +local scrollX, scrollY = 0,0 + +local tLines = {} +local bRunning = true + +-- Colours +local highlightColour, keywordColour, commentColour, textColour, bgColour, stringColour +if term.isColour() then + bgColour = colours.black + textColour = colours.white + highlightColour = colours.yellow + keywordColour = colours.yellow + commentColour = colours.green + stringColour = colours.red +else + bgColour = colours.black + textColour = colours.white + highlightColour = colours.white + keywordColour = colours.white + commentColour = colours.white + stringColour = colours.white +end + +-- Menus +local bMenu = false +local nMenuItem = 1 +local tMenuItems = {} +if not bReadOnly then + table.insert( tMenuItems, "Save" ) +end +if shell.openTab then + table.insert( tMenuItems, "Run" ) +end +if peripheral.find( "printer" ) then + table.insert( tMenuItems, "Print" ) +end +table.insert( tMenuItems, "Exit" ) + +local sStatus = "Press Ctrl to access menu" +if string.len( sStatus ) > w - 5 then + sStatus = "Press Ctrl for menu" +end + +local function load( _sPath ) + tLines = {} + if fs.exists( _sPath ) then + local file = io.open( _sPath, "r" ) + local sLine = file:read() + while sLine do + table.insert( tLines, sLine ) + sLine = file:read() + end + file:close() + end + + if #tLines == 0 then + table.insert( tLines, "" ) + end +end + +local function save( _sPath ) + -- Create intervening folder + local sDir = _sPath:sub(1, _sPath:len() - fs.getName(_sPath):len() ) + if not fs.exists( sDir ) then + fs.makeDir( sDir ) + end + + -- Save + local file = nil + local function innerSave() + file = fs.open( _sPath, "w" ) + if file then + for n, sLine in ipairs( tLines ) do + file.write( sLine .. "\n" ) + end + else + error( "Failed to open ".._sPath ) + end + end + + local ok, err = pcall( innerSave ) + if file then + file.close() + end + return ok, err +end + +local tKeywords = { + ["and"] = true, + ["break"] = true, + ["do"] = true, + ["else"] = true, + ["elseif"] = true, + ["end"] = true, + ["false"] = true, + ["for"] = true, + ["function"] = true, + ["if"] = true, + ["in"] = true, + ["local"] = true, + ["nil"] = true, + ["not"] = true, + ["or"] = true, + ["repeat"] = true, + ["return"] = true, + ["then"] = true, + ["true"] = true, + ["until"]= true, + ["while"] = true, +} + +local function tryWrite( sLine, regex, colour ) + local match = string.match( sLine, regex ) + if match then + if type(colour) == "number" then + term.setTextColour( colour ) + else + term.setTextColour( colour(match) ) + end + term.write( match ) + term.setTextColour( textColour ) + return string.sub( sLine, string.len(match) + 1 ) + end + return nil +end + +local function writeHighlighted( sLine ) + while string.len(sLine) > 0 do + sLine = + tryWrite( sLine, "^%-%-%[%[.-%]%]", commentColour ) or + tryWrite( sLine, "^%-%-.*", commentColour ) or + tryWrite( sLine, "^\"\"", stringColour ) or + tryWrite( sLine, "^\".-[^\\]\"", stringColour ) or + tryWrite( sLine, "^\'\'", stringColour ) or + tryWrite( sLine, "^\'.-[^\\]\'", stringColour ) or + tryWrite( sLine, "^%[%[.-%]%]", stringColour ) or + tryWrite( sLine, "^[%w_]+", function( match ) + if tKeywords[ match ] then + return keywordColour + end + return textColour + end ) or + tryWrite( sLine, "^[^%w_]", textColour ) + end +end + +local tCompletions +local nCompletion + +local tCompleteEnv = _ENV +local function complete( sLine ) + if settings.get( "edit.autocomplete" ) then + local nStartPos = string.find( sLine, "[a-zA-Z0-9_%.]+$" ) + if nStartPos then + sLine = string.sub( sLine, nStartPos ) + end + if #sLine > 0 then + return textutils.complete( sLine, tCompleteEnv ) + end + end + return nil +end + +local function recomplete() + local sLine = tLines[y] + if not bMenu and not bReadOnly and x == string.len(sLine) + 1 then + tCompletions = complete( sLine ) + if tCompletions and #tCompletions > 0 then + nCompletion = 1 + else + nCompletion = nil + end + else + tCompletions = nil + nCompletion = nil + end +end + +local function writeCompletion( sLine ) + if nCompletion then + local sCompletion = tCompletions[ nCompletion ] + term.setTextColor( colours.white ) + term.setBackgroundColor( colours.grey ) + term.write( sCompletion ) + term.setTextColor( textColour ) + term.setBackgroundColor( bgColour ) + end +end + +local function redrawText() + local cursorX, cursorY = x, y + for y=1,h-1 do + term.setCursorPos( 1 - scrollX, y ) + term.clearLine() + + local sLine = tLines[ y + scrollY ] + if sLine ~= nil then + writeHighlighted( sLine ) + if cursorY == y and cursorX == #sLine + 1 then + writeCompletion() + end + end + end + term.setCursorPos( x - scrollX, y - scrollY ) +end + +local function redrawLine(_nY) + local sLine = tLines[_nY] + if sLine then + term.setCursorPos( 1 - scrollX, _nY - scrollY ) + term.clearLine() + writeHighlighted( sLine ) + if _nY == y and x == #sLine + 1 then + writeCompletion() + end + term.setCursorPos( x - scrollX, _nY - scrollY ) + end +end + +local function redrawMenu() + -- Clear line + term.setCursorPos( 1, h ) + term.clearLine() + + -- Draw line numbers + term.setCursorPos( w - string.len( "Ln "..y ) + 1, h ) + term.setTextColour( highlightColour ) + term.write( "Ln " ) + term.setTextColour( textColour ) + term.write( y ) + + term.setCursorPos( 1, h ) + if bMenu then + -- Draw menu + term.setTextColour( textColour ) + for nItem,sItem in pairs( tMenuItems ) do + if nItem == nMenuItem then + term.setTextColour( highlightColour ) + term.write( "[" ) + term.setTextColour( textColour ) + term.write( sItem ) + term.setTextColour( highlightColour ) + term.write( "]" ) + term.setTextColour( textColour ) + else + term.write( " "..sItem.." " ) + end + end + else + -- Draw status + term.setTextColour( highlightColour ) + term.write( sStatus ) + term.setTextColour( textColour ) + end + + -- Reset cursor + term.setCursorPos( x - scrollX, y - scrollY ) +end + +local tMenuFuncs = { + Save = function() + if bReadOnly then + sStatus = "Access denied" + else + local ok, err = save( sPath ) + if ok then + sStatus="Saved to "..sPath + else + sStatus="Error saving to "..sPath + end + end + redrawMenu() + end, + Print = function() + local printer = peripheral.find( "printer" ) + if not printer then + sStatus = "No printer attached" + return + end + + local nPage = 0 + local sName = fs.getName( sPath ) + if printer.getInkLevel() < 1 then + sStatus = "Printer out of ink" + return + elseif printer.getPaperLevel() < 1 then + sStatus = "Printer out of paper" + return + end + + local screenTerminal = term.current() + local printerTerminal = { + getCursorPos = printer.getCursorPos, + setCursorPos = printer.setCursorPos, + getSize = printer.getPageSize, + write = printer.write, + } + printerTerminal.scroll = function() + if nPage == 1 then + printer.setPageTitle( sName.." (page "..nPage..")" ) + end + + while not printer.newPage() do + if printer.getInkLevel() < 1 then + sStatus = "Printer out of ink, please refill" + elseif printer.getPaperLevel() < 1 then + sStatus = "Printer out of paper, please refill" + else + sStatus = "Printer output tray full, please empty" + end + + term.redirect( screenTerminal ) + redrawMenu() + term.redirect( printerTerminal ) + + local timer = os.startTimer(0.5) + sleep(0.5) + end + + nPage = nPage + 1 + if nPage == 1 then + printer.setPageTitle( sName ) + else + printer.setPageTitle( sName.." (page "..nPage..")" ) + end + end + + bMenu = false + term.redirect( printerTerminal ) + local ok, error = pcall( function() + term.scroll() + for n, sLine in ipairs( tLines ) do + print( sLine ) + end + end ) + term.redirect( screenTerminal ) + if not ok then + print( error ) + end + + while not printer.endPage() do + sStatus = "Printer output tray full, please empty" + redrawMenu() + sleep( 0.5 ) + end + bMenu = true + + if nPage > 1 then + sStatus = "Printed "..nPage.." Pages" + else + sStatus = "Printed 1 Page" + end + redrawMenu() + end, + Exit = function() + bRunning = false + end, + Run = function() + local sTempPath = "/.temp" + local ok, err = save( sTempPath ) + if ok then + local nTask = shell.openTab( sTempPath ) + if nTask then + shell.switchTab( nTask ) + else + sStatus="Error starting Task" + end + fs.delete( sTempPath ) + else + sStatus="Error saving to "..sTempPath + end + redrawMenu() + end +} + +local function doMenuItem( _n ) + tMenuFuncs[tMenuItems[_n]]() + if bMenu then + bMenu = false + term.setCursorBlink( true ) + end + redrawMenu() +end + +local function setCursor( newX, newY ) + local oldX, oldY = x, y + x, y = newX, newY + local screenX = x - scrollX + local screenY = y - scrollY + + local bRedraw = false + if screenX < 1 then + scrollX = x - 1 + screenX = 1 + bRedraw = true + elseif screenX > w then + scrollX = x - w + screenX = w + bRedraw = true + end + + if screenY < 1 then + scrollY = y - 1 + screenY = 1 + bRedraw = true + elseif screenY > h-1 then + scrollY = y - (h-1) + screenY = h-1 + bRedraw = true + end + + recomplete() + if bRedraw then + redrawText() + elseif y ~= oldY then + redrawLine( oldY ) + redrawLine( y ) + else + redrawLine( y ) + end + term.setCursorPos( screenX, screenY ) + + redrawMenu() +end + +-- Actual program functionality begins +load(sPath) + +term.setBackgroundColour( bgColour ) +term.clear() +term.setCursorPos(x,y) +term.setCursorBlink( true ) + +recomplete() +redrawText() +redrawMenu() + +local function acceptCompletion() + if nCompletion then + -- Append the completion + local sCompletion = tCompletions[ nCompletion ] + tLines[y] = tLines[y] .. sCompletion + setCursor( x + string.len( sCompletion ), y ) + end +end + +-- Handle input +while bRunning do + local sEvent, param, param2, param3 = os.pullEvent() + if sEvent == "key" then + local oldX, oldY = x, y + if param == keys.up then + -- Up + if not bMenu then + if nCompletion then + -- Cycle completions + nCompletion = nCompletion - 1 + if nCompletion < 1 then + nCompletion = #tCompletions + end + redrawLine(y) + + elseif y > 1 then + -- Move cursor up + setCursor( + math.min( x, string.len( tLines[y - 1] ) + 1 ), + y - 1 + ) + end + end + + elseif param == keys.down then + -- Down + if not bMenu then + -- Move cursor down + if nCompletion then + -- Cycle completions + nCompletion = nCompletion + 1 + if nCompletion > #tCompletions then + nCompletion = 1 + end + redrawLine(y) + + elseif y < #tLines then + -- Move cursor down + setCursor( + math.min( x, string.len( tLines[y + 1] ) + 1 ), + y + 1 + ) + end + end + + elseif param == keys.tab then + -- Tab + if not bMenu and not bReadOnly then + if nCompletion and x == string.len(tLines[y]) + 1 then + -- Accept autocomplete + acceptCompletion() + else + -- Indent line + local sLine = tLines[y] + tLines[y] = string.sub(sLine,1,x-1) .. " " .. string.sub(sLine,x) + setCursor( x + 2, y ) + end + end + + elseif param == keys.pageUp then + -- Page Up + if not bMenu then + -- Move up a page + local newY + if y - (h - 1) >= 1 then + newY = y - (h - 1) + else + newY = 1 + end + setCursor( + math.min( x, string.len( tLines[newY] ) + 1 ), + newY + ) + end + + elseif param == keys.pageDown then + -- Page Down + if not bMenu then + -- Move down a page + local newY + if y + (h - 1) <= #tLines then + newY = y + (h - 1) + else + newY = #tLines + end + local newX = math.min( x, string.len( tLines[newY] ) + 1 ) + setCursor( newX, newY ) + end + + elseif param == keys.home then + -- Home + if not bMenu then + -- Move cursor to the beginning + if x > 1 then + setCursor(1,y) + end + end + + elseif param == keys["end"] then + -- End + if not bMenu then + -- Move cursor to the end + local nLimit = string.len( tLines[y] ) + 1 + if x < nLimit then + setCursor( nLimit, y ) + end + end + + elseif param == keys.left then + -- Left + if not bMenu then + if x > 1 then + -- Move cursor left + setCursor( x - 1, y ) + elseif x==1 and y>1 then + setCursor( string.len( tLines[y-1] ) + 1, y - 1 ) + end + else + -- Move menu left + nMenuItem = nMenuItem - 1 + if nMenuItem < 1 then + nMenuItem = #tMenuItems + end + redrawMenu() + end + + elseif param == keys.right then + -- Right + if not bMenu then + local nLimit = string.len( tLines[y] ) + 1 + if x < nLimit then + -- Move cursor right + setCursor( x + 1, y ) + elseif nCompletion and x == string.len(tLines[y]) + 1 then + -- Accept autocomplete + acceptCompletion() + elseif x==nLimit and y<#tLines then + -- Go to next line + setCursor( 1, y + 1 ) + end + else + -- Move menu right + nMenuItem = nMenuItem + 1 + if nMenuItem > #tMenuItems then + nMenuItem = 1 + end + redrawMenu() + end + + elseif param == keys.delete then + -- Delete + if not bMenu and not bReadOnly then + local nLimit = string.len( tLines[y] ) + 1 + if x < nLimit then + local sLine = tLines[y] + tLines[y] = string.sub(sLine,1,x-1) .. string.sub(sLine,x+1) + recomplete() + redrawLine(y) + elseif y<#tLines then + tLines[y] = tLines[y] .. tLines[y+1] + table.remove( tLines, y+1 ) + recomplete() + redrawText() + end + end + + elseif param == keys.backspace then + -- Backspace + if not bMenu and not bReadOnly then + if x > 1 then + -- Remove character + local sLine = tLines[y] + tLines[y] = string.sub(sLine,1,x-2) .. string.sub(sLine,x) + setCursor( x - 1, y ) + elseif y > 1 then + -- Remove newline + local sPrevLen = string.len( tLines[y-1] ) + tLines[y-1] = tLines[y-1] .. tLines[y] + table.remove( tLines, y ) + setCursor( sPrevLen + 1, y - 1 ) + redrawText() + end + end + + elseif param == keys.enter then + -- Enter + if not bMenu and not bReadOnly then + -- Newline + local sLine = tLines[y] + local _,spaces=string.find(sLine,"^[ ]+") + if not spaces then + spaces=0 + end + tLines[y] = string.sub(sLine,1,x-1) + table.insert( tLines, y+1, string.rep(' ',spaces)..string.sub(sLine,x) ) + setCursor( spaces + 1, y + 1 ) + redrawText() + + elseif bMenu then + -- Menu selection + doMenuItem( nMenuItem ) + + end + + elseif param == keys.leftCtrl or param == keys.rightCtrl or param == keys.rightAlt then + -- Menu toggle + bMenu = not bMenu + if bMenu then + term.setCursorBlink( false ) + else + term.setCursorBlink( true ) + end + redrawMenu() + + end + + elseif sEvent == "char" then + if not bMenu and not bReadOnly then + -- Input text + local sLine = tLines[y] + tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x) + setCursor( x + 1, y ) + + elseif bMenu then + -- Select menu items + for n,sMenuItem in ipairs( tMenuItems ) do + if string.lower(string.sub(sMenuItem,1,1)) == string.lower(param) then + doMenuItem( n ) + break + end + end + end + + elseif sEvent == "paste" then + if not bMenu and not bReadOnly then + -- Input text + local sLine = tLines[y] + tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x) + setCursor( x + string.len( param ), y ) + end + + elseif sEvent == "mouse_click" then + if not bMenu then + if param == 1 then + -- Left click + local cx,cy = param2, param3 + if cy < h then + local newY = math.min( math.max( scrollY + cy, 1 ), #tLines ) + local newX = math.min( math.max( scrollX + cx, 1 ), string.len( tLines[newY] ) + 1 ) + setCursor( newX, newY ) + end + end + end + + elseif sEvent == "mouse_scroll" then + if not bMenu then + if param == -1 then + -- Scroll up + if scrollY > 0 then + -- Move cursor up + scrollY = scrollY - 1 + redrawText() + end + + elseif param == 1 then + -- Scroll down + local nMaxScroll = #tLines - (h-1) + if scrollY < nMaxScroll then + -- Move cursor down + scrollY = scrollY + 1 + redrawText() + end + + end + end + + elseif sEvent == "term_resize" then + w,h = term.getSize() + setCursor( x, y ) + redrawMenu() + redrawText() + + end +end + +-- Cleanup +term.clear() +term.setCursorBlink( false ) +term.setCursorPos( 1, 1 ) \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/eject b/src/main/resources/assets/computercraft/lua/rom/programs/eject new file mode 100644 index 0000000000..33210c956c --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/eject @@ -0,0 +1,18 @@ + +-- Get arguments +local tArgs = { ... } +if #tArgs == 0 then + print( "Usage: eject " ) + return +end + +local sDrive = tArgs[1] + +-- Check the disk exists +local bPresent = disk.isPresent( sDrive ) +if not bPresent then + print( "Nothing in "..sDrive.." drive" ) + return +end + +disk.eject( sDrive ) diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/exit b/src/main/resources/assets/computercraft/lua/rom/programs/exit new file mode 100644 index 0000000000..b90092cba1 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/exit @@ -0,0 +1 @@ +shell.exit() diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/0 b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/0 new file mode 100755 index 0000000000..7231b84214 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/0 @@ -0,0 +1,8 @@ +0 +77 77 +718888887 + 8 8 + 8 8 + 8 8 +788888897 +77 77 diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/1 b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/1 new file mode 100755 index 0000000000..e51a790de2 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/1 @@ -0,0 +1,7 @@ +1 + 777 + 7b7 + 787 +7777778777 +7188888887 +7777777777 diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/10 b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/10 new file mode 100644 index 0000000000..bf1d7cb122 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/10 @@ -0,0 +1,11 @@ +5 + 777 77777 + 727777778837 + 788888878787 + 787777888887 +77877778777777 +7e8b7888b888e7 +7787787b777877 + 777887887887 + 7487807487 + 7777777777 diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/11 b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/11 new file mode 100644 index 0000000000..304f5808fd --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/11 @@ -0,0 +1,10 @@ +4 + 777777777 + 727872787 + 787878787 +777787878787777 +7be888888888be7 +777787878787777 + 787878787 + 787478747 + 777777777 diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/12 b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/12 new file mode 100644 index 0000000000..cad16afe4f --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/12 @@ -0,0 +1,12 @@ +6 +77 777 77 +72888888897 + 8 8 8 + 8 8b888 8 +78 e8888 87 +78888788887 +78 8888e 87 + 8 888b8 8 + 8 8 8 +75888888807 +77 777 77 diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/2 b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/2 new file mode 100755 index 0000000000..0bf3034ebb --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/2 @@ -0,0 +1,10 @@ +1 +777777777 +7888888b7 +787778887 +787 78777 +7877787 +7888887 +7777787 + 707 + 777 diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/3 b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/3 new file mode 100755 index 0000000000..40c2c2518f --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/3 @@ -0,0 +1,10 @@ +2 + 77777777 +777888188777 +7b78777787b7 +78787 78787 +78787 78787 +78887 78887 +777877778777 + 78838887 + 77777777 diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/4 b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/4 new file mode 100755 index 0000000000..c77c49a9a2 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/4 @@ -0,0 +1,10 @@ +2 + 77777777 +777778888887 +788888777787 +7b77787 787 +787 787 787 +7b77787 787 +7888887 787 +7777707 707 + 777 777 diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/5 b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/5 new file mode 100755 index 0000000000..5d084d9e42 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/5 @@ -0,0 +1,10 @@ +3 +777777777 +788888887 +787787787 +787787787 +788888887 +787787787 +787787787 +78e748887 +777777777 diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/6 b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/6 new file mode 100755 index 0000000000..38f0f42ea4 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/6 @@ -0,0 +1,11 @@ +4 +7777777777 +7288888837 +78 87 +788888b 87 +788888b 87 +788888b 87 +788888b 87 +78 87 +7188888807 +7777777777 diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/7 b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/7 new file mode 100644 index 0000000000..1456442e40 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/7 @@ -0,0 +1,10 @@ +3 +728777778b7 +78888888887 +78777877787 +787 787 787 +787 7877788 +787 7888889 +88777877777 +e888887 +7777887 diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/8 b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/8 new file mode 100644 index 0000000000..0eb44de0dc --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/8 @@ -0,0 +1,10 @@ +4 +777777 7777 +7287b7 7867 +788787 7887 +77878777877 + 7888eb8887 + 77877787877 + 7887 787887 + 7487 7e7807 + 7777 777777 diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/9 b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/9 new file mode 100644 index 0000000000..9965aa10ba --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/levels/9 @@ -0,0 +1,12 @@ +2 + 777 777 + 777877778777 + 788838888887 +7778bbbbbbbb8777 +7888b888888b8897 +7878be8888eb8787 +7588b888888b8887 +7778bbbbbbbb8777 + 788888818887 + 777877778777 + 777 777 diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/paint b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/paint new file mode 100644 index 0000000000..61e9ca2d41 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/paint @@ -0,0 +1,394 @@ +-- Paint created by nitrogenfingers (edited by dan200) +-- http://www.youtube.com/user/NitrogenFingers + +------------ +-- Fields -- +------------ + +-- The width and height of the terminal +local w,h = term.getSize() + +-- The selected colours on the left and right mouse button, and the colour of the canvas +local leftColour, rightColour = colours.white, nil +local canvasColour = colours.black + +-- The values stored in the canvas +local canvas = {} + +-- The menu options +local mChoices = { "Save","Exit" } + +-- The message displayed in the footer bar +local fMessage = "Press Ctrl to access menu" + +------------------------- +-- Initialisation -- +------------------------- + +-- Determine if we can even run this +if not term.isColour() then + print("Requires an Advanced Computer") + return +end + +-- Determines if the file exists, and can be edited on this computer +local tArgs = {...} +if #tArgs == 0 then + print("Usage: paint ") + return +end +local sPath = shell.resolve(tArgs[1]) +local bReadOnly = fs.isReadOnly(sPath) +if fs.exists(sPath) and fs.isDir(sPath) then + print("Cannot edit a directory.") + return +end + +--------------- +-- Functions -- +--------------- + +local function getCanvasPixel( x, y ) + if canvas[y] then + return canvas[y][x] + end + return nil +end + +--[[ + Converts a colour value to a text character + params: colour = the number to convert to a hex value + returns: a string representing the chosen colour +]] +local function getCharOf( colour ) + -- Incorrect values always convert to nil + if type(colour) == "number" then + local value = math.floor( math.log(colour) / math.log(2) ) + 1 + if value >= 1 and value <= 16 then + return string.sub( "0123456789abcdef", value, value ) + end + end + return " " +end + +--[[ + Converts a text character to colour value + params: char = the char (from string.byte) to convert to number + returns: the colour number of the hex value +]] +local tColourLookup = {} +for n=1,16 do + tColourLookup[ string.byte( "0123456789abcdef",n,n ) ] = 2^(n-1) +end +local function getColourOf( char ) + -- Values not in the hex table are transparent (canvas coloured) + return tColourLookup[char] +end + +--[[ + Loads the file into the canvas + params: path = the path of the file to open + returns: nil +]] +local function load(path) + -- Load the file + if fs.exists(path) then + local file = fs.open(sPath, "r") + local sLine = file.readLine() + while sLine do + local line = {} + for x=1,w-2 do + line[x] = getColourOf( string.byte(sLine,x,x) ) + end + table.insert( canvas, line ) + sLine = file.readLine() + end + file.close() + end +end + +--[[ + Saves the current canvas to file + params: path = the path of the file to save + returns: true if save was successful, false otherwise +]] +local function save(path) + -- Open file + local sDir = string.sub(sPath, 1, #sPath - #fs.getName(sPath)) + if not fs.exists(sDir) then + fs.makeDir(sDir) + end + + local file = fs.open( path, "w" ) + if not file then + return false + end + + -- Encode (and trim) + local tLines = {} + local nLastLine = 0 + for y=1,h-1 do + local sLine = "" + local nLastChar = 0 + for x=1,w-2 do + local c = getCharOf( getCanvasPixel( x, y ) ) + sLine = sLine .. c + if c ~= " " then + nLastChar = x + end + end + sLine = string.sub( sLine, 1, nLastChar ) + tLines[y] = sLine + if string.len( sLine ) > 0 then + nLastLine = y + end + end + + -- Save out + for n=1,nLastLine do + file.writeLine( tLines[ n ] ) + end + file.close() + return true +end + +--[[ + Draws colour picker sidebar, the pallette and the footer + returns: nil +]] +local function drawInterface() + -- Footer + term.setCursorPos(1, h) + term.setBackgroundColour(colours.black) + term.setTextColour(colours.yellow) + term.clearLine() + term.write(fMessage) + + -- Colour Picker + for i=1,16 do + term.setCursorPos(w-1, i) + term.setBackgroundColour( 2^(i-1) ) + term.write(" ") + end + + term.setCursorPos(w-1, 17) + term.setBackgroundColour( canvasColour ) + term.setTextColour( colours.grey ) + term.write("\127\127") + + -- Left and Right Selected Colours + for i=18,18 do + term.setCursorPos(w-1, i) + if leftColour ~= nil then + term.setBackgroundColour( leftColour ) + term.write(" ") + else + term.setBackgroundColour( canvasColour ) + term.setTextColour( colours.grey ) + term.write("\127") + end + if rightColour ~= nil then + term.setBackgroundColour( rightColour ) + term.write(" ") + else + term.setBackgroundColour( canvasColour ) + term.setTextColour( colours.grey ) + term.write("\127") + end + end + + -- Padding + term.setBackgroundColour( canvasColour ) + for i=20,h-1 do + term.setCursorPos(w-1, i) + term.write(" ") + end +end + +--[[ + Converts a single pixel of a single line of the canvas and draws it + returns: nil +]] +local function drawCanvasPixel( x, y ) + local pixel = getCanvasPixel( x, y ) + if pixel then + term.setBackgroundColour( pixel or canvasColour ) + term.setCursorPos(x, y) + term.write(" ") + else + term.setBackgroundColour( canvasColour ) + term.setTextColour( colours.grey ) + term.setCursorPos(x, y) + term.write("\127") + end +end + +--[[ + Converts each colour in a single line of the canvas and draws it + returns: nil +]] +local function drawCanvasLine( y ) + for x = 1, w-2 do + drawCanvasPixel( x, y ) + end +end + +--[[ + Converts each colour in the canvas and draws it + returns: nil +]] +local function drawCanvas() + for y = 1, h-1 do + drawCanvasLine( y ) + end +end + +--[[ + Draws menu options and handles input from within the menu. + returns: true if the program is to be exited; false otherwise +]] +local function accessMenu() + -- Selected menu option + local selection = 1 + + term.setBackgroundColour(colours.black) + while true do + -- Draw the menu + term.setCursorPos(1,h) + term.clearLine() + term.setTextColour(colours.white) + for k,v in pairs(mChoices) do + if selection==k then + term.setTextColour(colours.yellow) + local ox,_ = term.getCursorPos() + term.write("["..string.rep(" ",#v).."]") + term.setCursorPos(ox+1,h) + term.setTextColour(colours.white) + term.write(v) + term.setCursorPos(term.getCursorPos()+1,h) + else + term.write(" "..v.." ") + end + end + + -- Handle input in the menu + local id,key = os.pullEvent("key") + if id == "key" then + -- S and E are shortcuts + if key == keys.s then + selection = 1 + key = keys.enter + elseif key == keys.e then + selection = 2 + key = keys.enter + end + + if key == keys.right then + -- Move right + selection = selection + 1 + if selection > #mChoices then + selection = 1 + end + + elseif key == keys.left and selection > 1 then + -- Move left + selection = selection - 1 + if selection < 1 then + selection = #mChoices + end + + elseif key == keys.enter then + -- Select an option + if mChoices[selection]=="Save" then + if bReadOnly then + fMessage = "Access Denied" + return false + end + local success = save(sPath) + if success then + fMessage = "Saved to "..sPath + else + fMessage = "Error saving to "..sPath + end + return false + elseif mChoices[selection]=="Exit" then + return true + end + elseif key == keys.leftCtrl or keys == keys.rightCtrl then + -- Cancel the menu + return false + end + end + end +end + +--[[ + Runs the main thread of execution. Draws the canvas and interface, and handles + mouse and key events. + returns: nil +]] +local function handleEvents() + local programActive = true + while programActive do + local id,p1,p2,p3 = os.pullEvent() + if id=="mouse_click" or id=="mouse_drag" then + if p2 >= w-1 and p3 >= 1 and p3 <= 17 then + if id ~= "mouse_drag" then + -- Selecting an items in the colour picker + if p3 <= 16 then + if p1==1 then + leftColour = 2^(p3-1) + else + rightColour = 2^(p3-1) + end + else + if p1==1 then + leftColour = nil + else + rightColour = nil + end + end + --drawCanvas() + drawInterface() + end + elseif p2 < w-1 and p3 <= h-1 then + -- Clicking on the canvas + local paintColour = nil + if p1==1 then + paintColour = leftColour + elseif p1==2 then + paintColour = rightColour + end + if not canvas[p3] then + canvas[p3] = {} + end + canvas[p3][p2] = paintColour + + drawCanvasPixel( p2, p3 ) + end + elseif id=="key" then + if p1==keys.leftCtrl or p1==keys.rightCtrl then + programActive = not accessMenu() + drawInterface() + end + elseif id=="term_resize" then + w,h = term.getSize() + drawCanvas() + drawInterface() + end + end +end + +-- Init +load(sPath) +drawCanvas() +drawInterface() + +-- Main loop +handleEvents() + +-- Shutdown +term.setBackgroundColour(colours.black) +term.setTextColour(colours.white) +term.clear() +term.setCursorPos(1,1) diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/redirection b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/redirection new file mode 100755 index 0000000000..000243c843 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/fun/advanced/redirection @@ -0,0 +1,705 @@ +--CCRedirection by : RamiLego4Game and Dan200-- +--Based on Redirection by Dan200: http://www.redirectiongame.com-- +--Clearing Screen-- + +--Vars-- +local TermW,TermH = term.getSize() + +local sLevelTitle +local tScreen +local oScreen +local SizeW,SizeH +local aExits +local fExit +local nSpeed +local Speed +local fSpeed +local fSpeedS +local bPaused +local Tick +local Blocks +local XOrgin,YOrgin +local fLevel + +local function reset() + sLevelTitle = "" + tScreen = {} + oScreen = {} + SizeW,SizeH = TermW,TermH + aExits = 0 + fExit = "nop" + nSpeed = 0.6 + Speed = nSpeed + fSpeed = 0.2 + fSpeedS = false + bPaused = false + Tick = os.startTimer(Speed) + Blocks = 0 + XOrgin,YOrgin = 1,1 + + term.setBackgroundColor(colors.black) + term.setTextColor(colors.white) + term.clear() +end + +local InterFace = {} +InterFace.cExit = colors.red +InterFace.cSpeedD = colors.white +InterFace.cSpeedA = colors.red +InterFace.cTitle = colors.red + +local cG = colors.lightGray +local cW = colors.gray +local cS = colors.black +local cR1 = colors.blue +local cR2 = colors.red +local cR3 = colors.green +local cR4 = colors.yellow + +local tArgs = { ... } + +--Functions-- +local function printCentred( yc, stg ) + local xc = math.floor((TermW - string.len(stg)) / 2) + 1 + term.setCursorPos(xc,yc) + term.write( stg ) +end + +local function centerOrgin() + XOrgin = math.floor((TermW/2)-(SizeW/2)) + YOrgin = math.floor((TermH/2)-(SizeH/2)) +end + +local function reMap() + tScreen = nil + tScreen = {} + for x=1,SizeW do + tScreen[x] = {} + for y=1,SizeH do + tScreen[x][y] = { space = true, wall = false, ground = false, robot = "zz", start = "zz", exit = "zz" } + end + end +end + +local function tablecopy(t) + local t2 = {} + for k,v in pairs(t) do + t2[k] = v + end + return t2 +end + +local function buMap() + oScreen = nil + oScreen = {} + for x=1,SizeW do + oScreen[x] = {} + for y=1,SizeH do + oScreen[x][y] = tablecopy(tScreen[x][y]) + end + end +end + +local function addRobot(x,y,side,color) + local obj = tScreen[x][y] + local data = side..color + if obj.wall == nil and obj.robot == nil then + tScreen[x][y].robot = data + else + obj.wall = nil + obj.robot = "zz" + tScreen[x][y].robot = data + end +end + +local function addStart(x,y,side,color) + local obj = tScreen[x][y] + local data = side..color + if obj.wall == nil and obj.space == nil then + tScreen[x][y].start = data + else + obj.wall = nil + obj.space = nil + tScreen[x][y].start = data + end + aExits = aExits+1 +end + +local function addGround(x,y) + local obj = tScreen[x][y] + if obj.space == nil and obj.exit == nil and obj.wall == nil and obj.robot == nil and obj.start == nil then + tScreen[x][y].ground = true + else + obj.space = nil + obj.exit = "zz" + obj.wall = nil + obj.robot = "zz" + obj.start = "zz" + tScreen[x][y].ground = true + end +end + +local function addExit(x,y,cl) + local obj = tScreen[x][y] + if obj.space == nil and obj.ground == nil and obj.wall == nil and obj.robot == nil and obj.start == nil then + tScreen[x][y].exit = cl + else + obj.space = nil + obj.ground = nil + obj.wall = nil + obj.robot = "zz" + obj.start = "zz" + tScreen[x][y].exit = cl + end +end + +local function addWall(x,y) + local obj = tScreen[x][y] + if obj == nil then + return error("Here X"..x.." Y"..y) + end + if obj.space == nil and obj.exit == nil and obj.ground == nil and obj.robot == nil and obj.start == nil then + tScreen[x][y].wall = true + else + obj.space = nil + obj.exit = nil + obj.ground = nil + obj.robot = nil + obj.start = nil + tScreen[x][y].wall = true + end +end + +local function loadLevel(nNum) + sLevelTitle = "Level "..nNum + if nNum == nil then return error("nNum == nil") end + local sDir = fs.getDir( shell.getRunningProgram() ) + local sLevelD = sDir .. "/levels/" .. tostring(nNum) + if not ( fs.exists(sLevelD) or fs.isDir(sLevelD) ) then return error("Level Not Exists : "..sLevelD) end + fLevel = fs.open(sLevelD,"r") + local Line = 0 + local wl = true + Blocks = tonumber(string.sub(fLevel.readLine(),1,1)) + local xSize = string.len(fLevel.readLine())+2 + local Lines = 3 + while wl do + local wLine = fLevel.readLine() + if wLine == nil then + fLevel.close() + wl = false + else + xSize = math.max(string.len(wLine)+2,xSize) + Lines = Lines + 1 + end + end + SizeW,SizeH = xSize,Lines + reMap() + fLevel = fs.open(sLevelD,"r") + fLevel.readLine() + for Line=2,Lines-1 do + sLine = fLevel.readLine() + local chars = string.len(sLine) + for char = 1, chars do + local el = string.sub(sLine,char,char) + if el == "8" then + addGround(char+1,Line) + elseif el == "0" then + addStart(char+1,Line,"a","a") + elseif el == "1" then + addStart(char+1,Line,"b","a") + elseif el == "2" then + addStart(char+1,Line,"c","a") + elseif el == "3" then + addStart(char+1,Line,"d","a") + elseif el == "4" then + addStart(char+1,Line,"a","b") + elseif el == "5" then + addStart(char+1,Line,"b","b") + elseif el == "6" then + addStart(char+1,Line,"c","b") + elseif el == "9" then + addStart(char+1,Line,"d","b") + elseif el == "b" then + addExit(char+1,Line,"a") + elseif el == "e" then + addExit(char+1,Line,"b") + elseif el == "7" then + addWall(char+1,Line) + end + end + end + fLevel.close() +end + +local function drawStars() + --CCR Background By : RamiLego-- + local cStar,cStarG,crStar,crStarB = colors.lightGray,colors.gray,".","*" + local DStar,BStar,nStar,gStar = 14,10,16,3 + local TermW,TermH = term.getSize() + + term.clear() + term.setCursorPos(1,1) + for x=1,TermW do + for y=1,TermH do + local StarT = math.random(1,30) + if StarT == DStar then + term.setCursorPos(x,y) + term.setTextColor(cStar) + write(crStar) + elseif StarT == BStar then + term.setCursorPos(x,y) + term.setTextColor(cStar) + write(crStarB) + elseif StarT == nStar then + term.setCursorPos(x,y) + term.setTextColor(cStarG) + write(crStar) + elseif StarT == gStar then + term.setCursorPos(x,y) + term.setTextColor(cStarG) + write(crStarB) + end + end + end +end + +local function drawMap() + for x=1,SizeW do + for y=1,SizeH do + + local obj = tScreen[x][y] + if obj.ground == true then + paintutils.drawPixel(XOrgin+x,YOrgin+y+1,cG) + end + if obj.wall == true then + paintutils.drawPixel(XOrgin+x,YOrgin+y+1,cW) + end + + local ex = tostring(tScreen[x][y].exit) + if not(ex == "zz" or ex == "nil") then + if ex == "a" then + ex = cR1 + elseif ex == "b" then + ex = cR2 + elseif ex == "c" then + ex = cR3 + elseif ex == "d" then + ex = cR4 + else + return error("Exit Color Out") + end + term.setBackgroundColor(cG) + term.setTextColor(ex) + term.setCursorPos(XOrgin+x,YOrgin+y+1) + print("X") + end + + local st = tostring(tScreen[x][y].start) + if not(st == "zz" or st == "nil") then + local Cr = string.sub(st,2,2) + if Cr == "a" then + Cr = cR1 + elseif Cr == "b" then + Cr = cR2 + elseif Cr == "c" then + Cr = cR3 + elseif Cr == "d" then + Cr = cR4 + else + return error("Start Color Out") + end + + term.setTextColor(Cr) + term.setBackgroundColor(cG) + term.setCursorPos(XOrgin+x,YOrgin+y+1) + + sSide = string.sub(st,1,1) + if sSide == "a" then + print("^") + elseif sSide == "b" then + print(">") + elseif sSide == "c" then + print("v") + elseif sSide == "d" then + print("<") + else + print("@") + end + end + + if obj.space == true then + paintutils.drawPixel(XOrgin+x,YOrgin+y+1,cS) + end + + local rb = tostring(tScreen[x][y].robot) + if not(rb == "zz" or rb == "nil") then + local Cr = string.sub(rb,2,2) + if Cr == "a" then + Cr = cR1 + elseif Cr == "b" then + Cr = cR2 + elseif Cr == "c" then + Cr = cR3 + elseif Cr == "d" then + Cr = cR4 + else + Cr = colors.white + end + term.setBackgroundColor(Cr) + term.setTextColor(colors.white) + term.setCursorPos(XOrgin+x,YOrgin+y+1) + sSide = string.sub(rb,1,1) + if sSide == "a" then + print("^") + elseif sSide == "b" then + print(">") + elseif sSide == "c" then + print("v") + elseif sSide == "d" then + print("<") + else + print("@") + end + end + end + end +end + +local function isBrick(x,y) + local brb = tostring(tScreen[x][y].robot) + local bobj = oScreen[x][y] + if (brb == "zz" or brb == "nil") and not bobj.wall == true then + return false + else + return true + end +end + +local function gRender(sContext) + if sContext == "start" then + for x=1,SizeW do + for y=1,SizeH do + local st = tostring(tScreen[x][y].start) + if not(st == "zz" or st == "nil") then + local Cr = string.sub(st,2,2) + local sSide = string.sub(st,1,1) + addRobot(x,y,sSide,Cr) + end + end + end + elseif sContext == "tick" then + buMap() + for x=1,SizeW do + for y=1,SizeH do + local rb = tostring(oScreen[x][y].robot) + if not(rb == "zz" or rb == "nil") then + local Cr = string.sub(rb,2,2) + local sSide = string.sub(rb,1,1) + local sobj = oScreen[x][y] + if sobj.space == true then + tScreen[x][y].robot = "zz" + if not sSide == "g" then + addRobot(x,y,"g",Cr) + end + elseif sobj.exit == Cr then + if sSide == "a" or sSide == "b" or sSide == "c" or sSide == "d" then + tScreen[x][y].robot = "zz" + addRobot(x,y,"g",Cr) + aExits = aExits-1 + end + elseif sSide == "a" then + local obj = isBrick(x,y-1) + tScreen[x][y].robot = "zz" + if not obj == true then + addRobot(x,y-1,sSide,Cr) + else + local obj2 = isBrick(x-1,y) + local obj3 = isBrick(x+1,y) + if not obj2 == true and not obj3 == true then + if Cr == "a" then + addRobot(x,y,"d",Cr) + elseif Cr == "b" then + addRobot(x,y,"b",Cr) + end + elseif obj == true and obj2 == true and obj3 == true then + addRobot(x,y,"c",Cr) + else + if obj3 == true then + addRobot(x,y,"d",Cr) + elseif obj2 == true then + addRobot(x,y,"b",Cr) + end + end + end + elseif sSide == "b" then + local obj = isBrick(x+1,y) + tScreen[x][y].robot = "zz" + if not obj == true then + addRobot(x+1,y,sSide,Cr) + else + local obj2 = isBrick(x,y-1) + local obj3 = isBrick(x,y+1) + if not obj2 == true and not obj3 == true then + if Cr == "a" then + addRobot(x,y,"a",Cr) + elseif Cr == "b" then + addRobot(x,y,"c",Cr) + end + elseif obj == true and obj2 == true and obj3 == true then + addRobot(x,y,"d",Cr) + else + if obj3 == true then + addRobot(x,y,"a",Cr) + elseif obj2 == true then + addRobot(x,y,"c",Cr) + end + end + end + elseif sSide == "c" then + local obj = isBrick(x,y+1) + tScreen[x][y].robot = "zz" + if not obj == true then + addRobot(x,y+1,sSide,Cr) + else + local obj2 = isBrick(x-1,y) + local obj3 = isBrick(x+1,y) + if not obj2 == true and not obj3 == true then + if Cr == "a" then + addRobot(x,y,"b",Cr) + elseif Cr == "b" then + addRobot(x,y,"d",Cr) + end + elseif obj == true and obj2 == true and obj3 == true then + addRobot(x,y,"a",Cr) + else + if obj3 == true then + addRobot(x,y,"d",Cr) + elseif obj2 == true then + addRobot(x,y,"b",Cr) + end + end + end + elseif sSide == "d" then + local obj = isBrick(x-1,y) + tScreen[x][y].robot = "zz" + if not obj == true then + addRobot(x-1,y,sSide,Cr) + else + local obj2 = isBrick(x,y-1) + local obj3 = isBrick(x,y+1) + if not obj2 == true and not obj3 == true then + if Cr == "a" then + addRobot(x,y,"c",Cr) + elseif Cr == "b" then + addRobot(x,y,"a",Cr) + end + elseif obj == true and obj2 == true and obj3 == true then + addRobot(x,y,"b",Cr) + else + if obj3 == true then + addRobot(x,y,"a",Cr) + elseif obj2 == true then + addRobot(x,y,"c",Cr) + end + end + end + else + addRobot(x,y,sSide,"g") + end + end + end + end + end +end + +function InterFace.drawBar() + term.setBackgroundColor( colors.black ) + term.setTextColor( InterFace.cTitle ) + printCentred( 1, " "..sLevelTitle.." " ) + + term.setCursorPos(1,1) + term.setBackgroundColor( cW ) + write( " " ) + term.setBackgroundColor( colors.black ) + write( " x "..tostring(Blocks).." " ) + + term.setCursorPos( TermW-8,TermH ) + term.setBackgroundColor( colors.black ) + term.setTextColour(InterFace.cSpeedD) + write(" <<" ) + if bPaused then + term.setTextColour(InterFace.cSpeedA) + else + term.setTextColour(InterFace.cSpeedD) + end + write(" ||") + if fSpeedS then + term.setTextColour(InterFace.cSpeedA) + else + term.setTextColour(InterFace.cSpeedD) + end + write(" >>") + + term.setCursorPos( TermW-1, 1 ) + term.setBackgroundColor( colors.black ) + term.setTextColour( InterFace.cExit ) + write(" X") + term.setBackgroundColor(colors.black) +end + +function InterFace.render() + local id,p1,p2,p3 = os.pullEvent() + if id == "mouse_click" then + if p3 == 1 and p2 == TermW then + return "end" + elseif p3 == TermH and p2 >= TermW-7 and p2 <= TermW-6 then + return "retry" + elseif p3 == TermH and p2 >= TermW-4 and p2 <= TermW-3 then + bPaused = not bPaused + fSpeedS = false + Speed = (bPaused and 0) or nSpeed + if Speed > 0 then + Tick = os.startTimer(Speed) + else + Tick = nil + end + InterFace.drawBar() + elseif p3 == TermH and p2 >= TermW-1 then + bPaused = false + fSpeedS = not fSpeedS + Speed = (fSpeedS and fSpeed) or nSpeed + Tick = os.startTimer(Speed) + InterFace.drawBar() + elseif p3-1 < YOrgin+SizeH+1 and p3-1 > YOrgin and + p2 < XOrgin+SizeW+1 and p2 > XOrgin then + local eobj = tScreen[p2-XOrgin][p3-YOrgin-1] + local erobj = tostring(tScreen[p2-XOrgin][p3-YOrgin-1].robot) + if (erobj == "zz" or erobj == "nil") and not eobj.wall == true and not eobj.space == true and Blocks > 0 then + addWall(p2-XOrgin,p3-YOrgin-1) + Blocks = Blocks-1 + InterFace.drawBar() + drawMap() + end + end + elseif id == "timer" and p1 == Tick then + gRender("tick") + drawMap() + if Speed > 0 then + Tick = os.startTimer(Speed) + else + Tick = nil + end + end +end + +local function startG(LevelN) + drawStars() + loadLevel(LevelN) + centerOrgin() + local create = true + drawMap() + InterFace.drawBar() + gRender("start") + drawMap() + + local NExit = true + if aExits == 0 then + NExit = false + end + + while true do + local isExit = InterFace.render() + if isExit == "end" then + return nil + elseif isExit == "retry" then + return LevelN + elseif fExit == "yes" then + if fs.exists( fs.getDir( shell.getRunningProgram() ) .. "/levels/" .. tostring(LevelN + 1) ) then + return LevelN + 1 + else + return nil + end + end + if aExits == 0 and NExit == true then + fExit = "yes" + end + end +end + +local ok, err = true, nil + +--Menu-- +local sStartLevel = tArgs[1] +if ok and not sStartLevel then + ok, err = pcall( function() + term.setTextColor(colors.white) + term.setBackgroundColor( colors.black ) + term.clear() + drawStars() + term.setTextColor( colors.red ) + printCentred( TermH/2 - 1, " REDIRECTION " ) + printCentred( TermH/2 - 0, " ComputerCraft Edition " ) + term.setTextColor( colors.yellow ) + printCentred( TermH/2 + 2, " Click to Begin " ) + os.pullEvent( "mouse_click" ) + end ) +end + +--Game-- +if ok then + ok,err = pcall( function() + local nLevel + if sStartLevel then + nLevel = tonumber( sStartLevel ) + else + nLevel = 1 + end + while nLevel do + reset() + nLevel = startG(nLevel) + end + end ) +end + +--Upsell screen-- +if ok then + ok, err = pcall( function() + term.setTextColor(colors.white) + term.setBackgroundColor( colors.black ) + term.clear() + drawStars() + term.setTextColor( colors.red ) + if TermW >= 40 then + printCentred( TermH/2 - 1, " Thank you for playing Redirection " ) + printCentred( TermH/2 - 0, " ComputerCraft Edition " ) + printCentred( TermH/2 + 2, " Check out the full game: " ) + term.setTextColor( colors.yellow ) + printCentred( TermH/2 + 3, " http://www.redirectiongame.com " ) + else + printCentred( TermH/2 - 2, " Thank you for " ) + printCentred( TermH/2 - 1, " playing Redirection " ) + printCentred( TermH/2 - 0, " ComputerCraft Edition " ) + printCentred( TermH/2 + 2, " Check out the full game: " ) + term.setTextColor( colors.yellow ) + printCentred( TermH/2 + 3, " www.redirectiongame.com " ) + end + parallel.waitForAll( + function() sleep(2) end, + function() os.pullEvent( "mouse_click" ) end + ) + end ) +end + +--Clear and exit-- +term.setCursorPos(1,1) +term.setTextColor(colors.white) +term.setBackgroundColor(colors.black) +term.clear() +if not ok then + if err == "Terminated" then + print( "Check out the full version of Redirection:" ) + print( "http://www.redirectiongame.com" ) + else + printError( err ) + end +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/fun/adventure b/src/main/resources/assets/computercraft/lua/rom/programs/fun/adventure new file mode 100644 index 0000000000..98dfea3d4b --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/fun/adventure @@ -0,0 +1,1343 @@ + +local tBiomes = { + "in a forest", + "in a pine forest", + "knee deep in a swamp", + "in a mountain range", + "in a desert", + "in a grassy plain", + "in frozen tundra", +} + +local function hasTrees( _nBiome ) + return _nBiome <= 3 +end + +local function hasStone( _nBiome ) + return _nBiome == 4 +end + +local function hasRivers( _nBiome ) + return _nBiome ~= 3 and _nBiome ~= 5 +end + +local items = { + ["no tea"] = { + droppable = false, + desc = "Pull yourself together man.", + }, + ["a pig"] = { + heavy = true, + creature = true, + drops = { "some pork" }, + aliases = { "pig" }, + desc = "The pig has a square nose.", + }, + ["a cow"] = { + heavy = true, + creature = true, + aliases = { "cow" }, + desc = "The cow stares at you blankly.", + }, + ["a sheep"] = { + heavy = true, + creature = true, + hitDrops = { "some wool" }, + aliases = { "sheep" }, + desc = "The sheep is fluffy.", + }, + ["a chicken"] = { + heavy = true, + creature = true, + drops = { "some chicken" }, + aliases = { "chicken" }, + desc = "The chicken looks delicious.", + }, + ["a creeper"] = { + heavy = true, + creature = true, + monster = true, + aliases = { "creeper" }, + desc = "The creeper needs a hug.", + }, + ["a skeleton"] = { + heavy = true, + creature = true, + monster = true, + aliases = { "skeleton" }, + nocturnal = true, + desc = "The head bone's connected to the neck bone, the neck bone's connected to the chest bone, the chest bone's connected to the arm bone, the arm bone's connected to the bow, and the bow is pointed at you.", + }, + ["a zombie"] = { + heavy = true, + creature = true, + monster = true, + aliases = { "zombie" }, + nocturnal = true, + desc = "All he wants to do is eat your brains.", + }, + ["a spider"] = { + heavy = true, + creature = true, + monster = true, + aliases = { "spider" }, + desc = "Dozens of eyes stare back at you.", + }, + ["a cave entrance"] = { + heavy = true, + aliases = { "cave entance", "cave", "entrance" }, + desc = "The entrance to the cave is dark, but it looks like you can climb down.", + }, + ["an exit to the surface"] = { + heavy = true, + aliases = { "exit to the surface", "exit", "opening" }, + desc = "You can just see the sky through the opening.", + }, + ["a river"] = { + heavy = true, + aliases = { "river" }, + desc = "The river flows majestically towards the horizon. It doesn't do anything else.", + }, + ["some wood"] = { + aliases = { "wood" }, + material = true, + desc = "You could easilly craft this wood into planks.", + }, + ["some planks"] = { + aliases = { "planks", "wooden planks", "wood planks" }, + desc = "You could easilly craft these planks into sticks.", + }, + ["some sticks"] = { + aliases = { "sticks", "wooden sticks", "wood sticks" }, + desc = "A perfect handle for torches or a pickaxe.", + }, + ["a crafting table"] = { + aliases = { "crafting table", "craft table", "work bench", "workbench", "crafting bench", "table", }, + desc = "It's a crafting table. I shouldn't tell you this, but these don't actually do anything in this game, you can craft tools whenever you like.", + }, + ["a furnace"] = { + aliases = { "furnace" }, + desc = "It's a furnace. Between you and me, these don't actually do anything in this game.", + }, + ["a wooden pickaxe"] = { + aliases = { "pickaxe", "pick", "wooden pick", "wooden pickaxe", "wood pick", "wood pickaxe" }, + tool = true, + toolLevel = 1, + toolType = "pick", + desc = "The pickaxe looks good for breaking stone and coal.", + }, + ["a stone pickaxe"] = { + aliases = { "pickaxe", "pick", "stone pick", "stone pickaxe" }, + tool = true, + toolLevel = 2, + toolType = "pick", + desc = "The pickaxe looks good for breaking iron.", + }, + ["an iron pickaxe"] = { + aliases = { "pickaxe", "pick", "iron pick", "iron pickaxe" }, + tool = true, + toolLevel = 3, + toolType = "pick", + desc = "The pickaxe looks strong enough to break diamond.", + }, + ["a diamond pickaxe"] = { + aliases = { "pickaxe", "pick", "diamond pick", "diamond pickaxe" }, + tool = true, + toolLevel = 4, + toolType = "pick", + desc = "Best. Pickaxe. Ever.", + }, + ["a wooden sword"] = { + aliases = { "sword", "wooden sword", "wood sword" }, + tool = true, + toolLevel = 1, + toolType = "sword", + desc = "Flimsy, but better than nothing.", + }, + ["a stone sword"] = { + aliases = { "sword", "stone sword" }, + tool = true, + toolLevel = 2, + toolType = "sword", + desc = "A pretty good sword.", + }, + ["an iron sword"] = { + aliases = { "sword", "iron sword" }, + tool = true, + toolLevel = 3, + toolType = "sword", + desc = "This sword can slay any enemy.", + }, + ["a diamond sword"] = { + aliases = { "sword", "diamond sword" }, + tool = true, + toolLevel = 4, + toolType = "sword", + desc = "Best. Sword. Ever.", + }, + ["a wooden shovel"] = { + aliases = { "shovel", "wooden shovel", "wood shovel" }, + tool = true, + toolLevel = 1, + toolType = "shovel", + desc = "Good for digging holes.", + }, + ["a stone shovel"] = { + aliases = { "shovel", "stone shovel" }, + tool = true, + toolLevel = 2, + toolType = "shovel", + desc = "Good for digging holes.", + }, + ["an iron shovel"] = { + aliases = { "shovel", "iron shovel" }, + tool = true, + toolLevel = 3, + toolType = "shovel", + desc = "Good for digging holes.", + }, + ["a diamond shovel"] = { + aliases = { "shovel", "diamond shovel" }, + tool = true, + toolLevel = 4, + toolType = "shovel", + desc = "Good for digging holes.", + }, + ["some coal"] = { + aliases = { "coal" }, + ore = true, + toolLevel = 1, + toolType = "pick", + desc = "That coal looks useful for building torches, if only you had a pickaxe to mine it.", + }, + ["some dirt"] = { + aliases = { "dirt" }, + material = true, + desc = "Why not build a mud hut?", + }, + ["some stone"] = { + aliases = { "stone", "cobblestone" }, + material = true, + ore = true, + infinite = true, + toolLevel = 1, + toolType = "pick", + desc = "Stone is useful for building things, and making stone pickaxes.", + }, + ["some iron"] = { + aliases = { "iron" }, + material = true, + ore = true, + toolLevel = 2, + toolType = "pick", + desc = "That iron looks mighty strong, you'll need a stone pickaxe to mine it.", + }, + ["some diamond"] = { + aliases = { "diamond", "diamonds" }, + material = true, + ore = true, + toolLevel = 3, + toolType = "pick", + desc = "Sparkly, rare, and impossible to mine without an iron pickaxe.", + }, + ["some torches"] = { + aliases = { "torches", "torch" }, + desc = "These won't run out for a while.", + }, + ["a torch"] = { + aliases = { "torch" }, + desc = "Fire, fire, burn so bright, won't you light my cave tonight?", + }, + ["some wool"] = { + aliases = { "wool" }, + material = true, + desc = "Soft and good for building.", + }, + ["some pork"] = { + aliases = { "pork", "porkchops" }, + food = true, + desc = "Delicious and nutricious.", + }, + ["some chicken"] = { + aliases = { "chicken" }, + food = true, + desc = "Finger licking good.", + }, +} + +local tAnimals = { + "a pig", "a cow", "a sheep", "a chicken", +} + +local tMonsters = { + "a creeper", "a skeleton", "a zombie", "a spider" +} + +local tRecipes = { + ["some planks"] = { "some wood" }, + ["some sticks"] = { "some planks" }, + ["some sticks"] = { "some planks" }, + ["a crafting table"] = { "some planks" }, + ["a furnace"] = { "some stone" }, + ["some torches"] = { "some sticks", "some coal" }, + + ["a wooden pickaxe"] = { "some planks", "some sticks" }, + ["a stone pickaxe"] = { "some stone", "some sticks" }, + ["an iron pickaxe"] = { "some iron", "some sticks" }, + ["a diamond pickaxe"] = { "some diamond", "some sticks" }, + + ["a wooden sword"] = { "some planks", "some sticks" }, + ["a stone sword"] = { "some stone", "some sticks" }, + ["an iron sword"] = { "some iron", "some sticks" }, + ["a diamond sword"] = { "some diamond", "some sticks" }, + + ["a wooden shovel"] = { "some planks", "some sticks" }, + ["a stone shovel"] = { "some stone", "some sticks" }, + ["an iron shovel"] = { "some iron", "some sticks" }, + ["a diamond shovel"] = { "some diamond", "some sticks" }, +} + +local tGoWest = { + "(life is peaceful there)", + "(lots of open air)", + "(to begin life anew)", + "(this is what we'll do)", + "(sun in winter time)", + "(we will do just fine)", + "(where the skies are blue)", + "(this and more we'll do)", +} +local nGoWest = 0 + +local bRunning = true +local tMap = { { {}, }, } +local x,y,z = 0,0,0 +local inventory = { + ["no tea"] = items["no tea"], +} + +local nTurn = 0 +local nTimeInRoom = 0 +local bInjured = false + +local tDayCycle = { + "It is daytime.", + "It is daytime.", + "It is daytime.", + "It is daytime.", + "It is daytime.", + "It is daytime.", + "It is daytime.", + "It is daytime.", + "The sun is setting.", + "It is night.", + "It is night.", + "It is night.", + "It is night.", + "It is night.", + "The sun is rising.", +} + +local function getTimeOfDay() + return math.fmod( math.floor(nTurn/3), #tDayCycle ) + 1 +end + +local function isSunny() + return (getTimeOfDay() < 10) +end + +local function getRoom( x, y, z, dontCreate ) + tMap[x] = tMap[x] or {} + tMap[x][y] = tMap[x][y] or {} + if not tMap[x][y][z] and dontCreate ~= true then + local room = { + items = {}, + exits = {}, + nMonsters = 0, + } + tMap[x][y][z] = room + + if y == 0 then + -- Room is above ground + + -- Pick biome + room.nBiome = math.random( 1, #tBiomes ) + room.trees = hasTrees( room.nBiome ) + + -- Add animals + if math.random(1,3) == 1 then + for n = 1,math.random(1,2) do + local sAnimal = tAnimals[ math.random( 1, #tAnimals ) ] + room.items[ sAnimal ] = items[ sAnimal ] + end + end + + -- Add surface ore + if math.random(1,5) == 1 or hasStone( room.nBiome ) then + room.items[ "some stone" ] = items[ "some stone" ] + end + if math.random(1,8) == 1 then + room.items[ "some coal" ] = items[ "some coal" ] + end + if math.random(1,8) == 1 and hasRivers( room.nBiome ) then + room.items[ "a river" ] = items[ "a river" ] + end + + -- Add exits + room.exits = { + ["north"] = true, + ["south"] = true, + ["east"] = true, + ["west"] = true, + } + if math.random(1,8) == 1 then + room.exits["down"] = true + room.items["a cave entrance"] = items["a cave entrance"] + end + + else + -- Room is underground + -- Add exits + local function tryExit( sDir, sOpp, x, y, z ) + local adj = getRoom( x, y, z, true ) + if adj then + if adj.exits[sOpp] then + room.exits[sDir] = true + end + else + if math.random(1,3) == 1 then + room.exits[sDir] = true + end + end + end + + if y == -1 then + local above = getRoom( x, y + 1, z ) + if above.exits["down"] then + room.exits["up"] = true + room.items["an exit to the surface"] = items["an exit to the surface"] + end + else + tryExit( "up", "down", x, y + 1, z ) + end + + if y > -3 then + tryExit( "down", "up", x, y - 1, z ) + end + + tryExit( "east", "west", x - 1, y, z ) + tryExit( "west", "east", x + 1, y, z ) + tryExit( "north", "south", x, y, z + 1 ) + tryExit( "south", "north", x, y, z - 1 ) + + -- Add ores + room.items[ "some stone" ] = items[ "some stone" ] + if math.random(1,3) == 1 then + room.items[ "some coal" ] = items[ "some coal" ] + end + if math.random(1,8) == 1 then + room.items[ "some iron" ] = items[ "some iron" ] + end + if y == -3 and math.random(1,15) == 1 then + room.items[ "some diamond" ] = items[ "some diamond" ] + end + + -- Turn out the lights + room.dark = true + end + end + return tMap[x][y][z] +end + +local function itemize( t ) + local item = next( t ) + if item == nil then + return "nothing" + end + + local text = "" + while item do + text = text .. item + + local nextItem = next( t, item ) + if nextItem ~= nil then + local nextNextItem = next( t, nextItem ) + if nextNextItem == nil then + text = text .. " and " + else + text = text .. ", " + end + end + item = nextItem + end + return text +end + +local function findItem( _tList, _sQuery ) + for sItem, tItem in pairs( _tList ) do + if sItem == _sQuery then + return sItem + end + if tItem.aliases ~= nil then + for n, sAlias in pairs( tItem.aliases ) do + if sAlias == _sQuery then + return sItem + end + end + end + end + return nil +end + +local tMatches = { + ["wait"] = { + "wait", + }, + ["look"] = { + "look at the ([%a ]+)", + "look at ([%a ]+)", + "look", + "inspect ([%a ]+)", + "inspect the ([%a ]+)", + "inspect", + }, + ["inventory"] = { + "check self", + "check inventory", + "inventory", + "i", + }, + ["go"] = { + "go (%a+)", + "travel (%a+)", + "walk (%a+)", + "run (%a+)", + "go", + }, + ["dig"] = { + "dig (%a+) using ([%a ]+)", + "dig (%a+) with ([%a ]+)", + "dig (%a+)", + "dig", + }, + ["take"] = { + "pick up the ([%a ]+)", + "pick up ([%a ]+)", + "pickup ([%a ]+)", + "take the ([%a ]+)", + "take ([%a ]+)", + "take", + }, + ["drop"] = { + "put down the ([%a ]+)", + "put down ([%a ]+)", + "drop the ([%a ]+)", + "drop ([%a ]+)", + "drop", + }, + ["place"] = { + "place the ([%a ]+)", + "place ([%a ]+)", + "place", + }, + ["cbreak"] = { + "punch the ([%a ]+)", + "punch ([%a ]+)", + "punch", + "break the ([%a ]+) with the ([%a ]+)", + "break ([%a ]+) with ([%a ]+) ", + "break the ([%a ]+)", + "break ([%a ]+)", + "break", + }, + ["mine"] = { + "mine the ([%a ]+) with the ([%a ]+)", + "mine ([%a ]+) with ([%a ]+)", + "mine ([%a ]+)", + "mine", + }, + ["attack"] = { + "attack the ([%a ]+) with the ([%a ]+)", + "attack ([%a ]+) with ([%a ]+)", + "attack ([%a ]+)", + "attack", + "kill the ([%a ]+) with the ([%a ]+)", + "kill ([%a ]+) with ([%a ]+)", + "kill ([%a ]+)", + "kill", + "hit the ([%a ]+) with the ([%a ]+)", + "hit ([%a ]+) with ([%a ]+)", + "hit ([%a ]+)", + "hit", + }, + ["craft"] = { + "craft a ([%a ]+)", + "craft some ([%a ]+)", + "craft ([%a ]+)", + "craft", + "make a ([%a ]+)", + "make some ([%a ]+)", + "make ([%a ]+)", + "make", + }, + ["build"] = { + "build ([%a ]+) out of ([%a ]+)", + "build ([%a ]+) from ([%a ]+)", + "build ([%a ]+)", + "build", + }, + ["eat"] = { + "eat a ([%a ]+)", + "eat the ([%a ]+)", + "eat ([%a ]+)", + "eat", + }, + ["help"] = { + "help me", + "help", + }, + ["exit"] = { + "exit", + "quit", + "goodbye", + "good bye", + "bye", + "farewell", + }, +} + +local commands = {} +local function doCommand( text ) + if text == "" then + commands[ "noinput" ]() + return + end + + for sCommand, t in pairs( tMatches ) do + for n, sMatch in pairs( t ) do + local tCaptures = { string.match( text, "^" .. sMatch .. "$" ) } + if #tCaptures ~= 0 then + local fnCommand = commands[ sCommand ] + if #tCaptures == 1 and tCaptures[1] == sMatch then + fnCommand() + else + fnCommand( table.unpack( tCaptures ) ) + end + return + end + end + end + commands[ "badinput" ]() +end + +function commands.wait() + print( "Time passes..." ) +end + +function commands.look( _sTarget ) + local room = getRoom( x,y,z ) + if room.dark then + print( "It is pitch dark." ) + return + end + + if _sTarget == nil then + -- Look at the world + if y == 0 then + io.write( "You are standing " .. tBiomes[room.nBiome] .. ". " ) + print( tDayCycle[ getTimeOfDay() ] ) + else + io.write( "You are underground. " ) + if next( room.exits ) ~= nil then + print( "You can travel "..itemize( room.exits ).."." ) + else + print() + end + end + if next( room.items ) ~= nil then + print( "There is " .. itemize( room.items ) .. " here." ) + end + if room.trees then + print( "There are trees here." ) + end + + else + -- Look at stuff + if room.trees and (_sTarget == "tree" or _sTarget == "trees") then + print( "The trees look easy to break." ) + elseif _sTarget == "self" or _sTarget == "myself" then + print( "Very handsome." ) + else + local tItem = nil + local sItem = findItem( room.items, _sTarget ) + if sItem then + tItem = room.items[sItem] + else + sItem = findItem( inventory, _sTarget ) + if sItem then + tItem = inventory[sItem] + end + end + + if tItem then + print( tItem.desc or ("You see nothing special about "..sItem..".") ) + else + print( "You don't see any ".._sTarget.." here." ) + end + end + end +end + +function commands.go( _sDir ) + local room = getRoom( x,y,z ) + if _sDir == nil then + print( "Go where?" ) + return + end + + if nGoWest ~= nil then + if _sDir == "west" then + nGoWest = nGoWest + 1 + if nGoWest > #tGoWest then + nGoWest = 1 + end + print( tGoWest[ nGoWest ] ) + else + if nGoWest > 0 or nTurn > 6 then + nGoWest = nil + end + end + end + + if room.exits[_sDir] == nil then + print( "You can't go that way." ) + return + end + + if _sDir == "north" then + z = z + 1 + elseif _sDir == "south" then + z = z - 1 + elseif _sDir == "east" then + x = x - 1 + elseif _sDir == "west" then + x = x + 1 + elseif _sDir == "up" then + y = y + 1 + elseif _sDir == "down" then + y = y - 1 + else + print( "I don't understand that direction." ) + return + end + + nTimeInRoom = 0 + doCommand( "look" ) +end + +function commands.dig( _sDir, _sTool ) + local room = getRoom( x,y,z ) + if _sDir == nil then + print( "Dig where?" ) + return + end + + local sTool = nil + local tTool = nil + if _sTool ~= nil then + sTool = findItem( inventory, _sTool ) + if not sTool then + print( "You're not carrying a ".._sTool.."." ) + return + end + tTool = inventory[ sTool ] + end + + local room = getRoom( x, y, z ) + local bActuallyDigging = (room.exits[ _sDir ] ~= true) + if bActuallyDigging then + if sTool == nil or tTool.toolType ~= "pick" then + print( "You need to use a pickaxe to dig through stone." ) + return + end + end + + if _sDir == "north" then + room.exits["north"] = true + z = z + 1 + getRoom( x, y, z ).exits["south"] = true + + elseif _sDir == "south" then + room.exits["south"] = true + z = z - 1 + getRoom( x, y, z ).exits["north"] = true + + elseif _sDir == "east" then + room.exits["east"] = true + x = x - 1 + getRoom( x, y, z ).exits["west"] = true + + elseif _sDir == "west" then + room.exits["west"] = true + x = x + 1 + getRoom( x, y, z ).exits["east"] = true + + elseif _sDir == "up" then + if y == 0 then + print( "You can't dig that way." ) + return + end + + room.exits["up"] = true + if y == -1 then + room.items[ "an exit to the surface" ] = items[ "an exit to the surface" ] + end + y = y + 1 + + room = getRoom( x, y, z ) + room.exits["down"] = true + if y == 0 then + room.items[ "a cave entrance" ] = items[ "a cave entrance" ] + end + + elseif _sDir == "down" then + if y <= -3 then + print( "You hit bedrock." ) + return + end + + room.exits["down"] = true + if y == 0 then + room.items[ "a cave entrance" ] = items[ "a cave entrance" ] + end + y = y - 1 + + room = getRoom( x, y, z ) + room.exits["up"] = true + if y == -1 then + room.items[ "an exit to the surface" ] = items[ "an exit to the surface" ] + end + + else + print( "I don't understand that direction." ) + return + end + + -- + if bActuallyDigging then + if _sDir == "down" and y == -1 or + _sDir == "up" and y == 0 then + inventory[ "some dirt" ] = items[ "some dirt" ] + inventory[ "some stone" ] = items[ "some stone" ] + print( "You dig ".._sDir.." using "..sTool.." and collect some dirt and stone." ) + else + inventory[ "some stone" ] = items[ "some stone" ] + print( "You dig ".._sDir.." using "..sTool.." and collect some stone." ) + end + end + + nTimeInRoom = 0 + doCommand( "look" ) +end + +function commands.inventory() + print( "You are carrying " .. itemize( inventory ) .. "." ) +end + +function commands.drop( _sItem ) + if _sItem == nil then + print( "Drop what?" ) + return + end + + local room = getRoom( x,y,z ) + local sItem = findItem( inventory, _sItem ) + if sItem then + local tItem = inventory[ sItem ] + if tItem.droppable == false then + print( "You can't drop that." ) + else + room.items[ sItem ] = tItem + inventory[ sItem ] = nil + print( "Dropped." ) + end + else + print( "You don't have a ".._sItem.."." ) + end +end + +function commands.place( _sItem ) + if _sItem == nil then + print( "Place what?" ) + return + end + + if _sItem == "torch" or _sItem == "a torch" then + local room = getRoom( x,y,z ) + if inventory["some torches"] or inventory["a torch"] then + inventory["a torch"] = nil + room.items["a torch"] = items["a torch"] + if room.dark then + print( "The cave lights up under the torchflame." ) + room.dark = false + elseif y == 0 and not isSunny() then + print( "The night gets a little brighter." ) + else + print( "Placed." ) + end + else + print( "You don't have torches." ) + end + return + end + + commands.drop( _sItem ) +end + +function commands.take( _sItem ) + if _sItem == nil then + print( "Take what?" ) + return + end + + local room = getRoom( x,y,z ) + local sItem = findItem( room.items, _sItem ) + if sItem then + local tItem = room.items[ sItem ] + if tItem.heavy == true then + print( "You can't carry "..sItem.."." ) + elseif tItem.ore == true then + print( "You need to mine this ore." ) + else + if tItem.infinite ~= true then + room.items[ sItem ] = nil + end + inventory[ sItem ] = tItem + + if inventory["some torches"] and inventory["a torch"] then + inventory["a torch"] = nil + end + if sItem == "a torch" and y < 0 then + room.dark = true + print( "The cave plunges into darkness." ) + else + print( "Taken." ) + end + end + else + print( "You don't see a ".._sItem.." here." ) + end +end + +function commands.mine( _sItem, _sTool ) + if _sItem == nil then + print( "Mine what?" ) + return + end + if _sTool == nil then + print( "Mine ".._sItem.." with what?" ) + return + end + commands.cbreak( _sItem, _sTool ) +end + +function commands.attack( _sItem, _sTool ) + if _sItem == nil then + print( "Attack what?" ) + return + end + commands.cbreak( _sItem, _sTool ) +end + +function commands.cbreak( _sItem, _sTool ) + if _sItem == nil then + print( "Break what?" ) + return + end + + local sTool = nil + if _sTool ~= nil then + sTool = findItem( inventory, _sTool ) + if sTool == nil then + print( "You're not carrying a ".._sTool.."." ) + return + end + end + + local room = getRoom( x,y,z ) + if _sItem == "tree" or _sItem == "trees" or _sItem == "a tree" then + print( "The tree breaks into blocks of wood, which you pick up." ) + inventory[ "some wood" ] = items[ "some wood" ] + return + elseif _sItem == "self" or _sItem == "myself" then + if term.isColour() then + term.setTextColour( colours.red ) + end + print( "You have died." ) + print( "Score: &e0" ) + term.setTextColour( colours.white ) + bRunning = false + return + end + + local sItem = findItem( room.items, _sItem ) + if sItem then + local tItem = room.items[ sItem ] + if tItem.ore == true then + -- Breaking ore + if not sTool then + print( "You need a tool to break this ore." ) + return + end + local tTool = inventory[ sTool ] + if tTool.tool then + if tTool.toolLevel < tItem.toolLevel then + print( sTool .." is not strong enough to break this ore." ) + elseif tTool.toolType ~= tItem.toolType then + print( "You need a different kind of tool to break this ore." ) + else + print( "The ore breaks, dropping "..sItem..", which you pick up." ) + inventory[ sItem ] = items[ sItem ] + if tItem.infinite ~= true then + room.items[ sItem ] = nil + end + end + else + print( "You can't break "..sItem.." with "..sTool..".") + end + + elseif tItem.creature == true then + -- Fighting monsters (or pigs) + local toolLevel = 0 + local tTool = nil + if sTool then + tTool = inventory[ sTool ] + if tTool.toolType == "sword" then + toolLevel = tTool.toolLevel + end + end + + local tChances = { 0.2, 0.4, 0.55, 0.8, 1 } + if math.random() <= tChances[ toolLevel + 1 ] then + room.items[ sItem ] = nil + print( "The "..tItem.aliases[1].." dies." ) + + if tItem.drops then + for n, sDrop in pairs( tItem.drops ) do + if not room.items[sDrop] then + print( "The "..tItem.aliases[1].." dropped "..sDrop.."." ) + room.items[sDrop] = items[sDrop] + end + end + end + + if tItem.monster then + room.nMonsters = room.nMonsters - 1 + end + else + print( "The "..tItem.aliases[1].." is injured by your blow." ) + end + + if tItem.hitDrops then + for n, sDrop in pairs( tItem.hitDrops ) do + if not room.items[sDrop] then + print( "The "..tItem.aliases[1].." dropped "..sDrop.."." ) + room.items[sDrop] = items[sDrop] + end + end + end + + else + print( "You can't break "..sItem.."." ) + end + else + print( "You don't see a ".._sItem.." here." ) + end +end + +function commands.craft( _sItem ) + if _sItem == nil then + print( "Craft what?" ) + return + end + + if _sItem == "computer" or _sItem == "a computer" then + print( "By creating a computer in a computer in a computer, you tear a hole in the spacetime continuum from which no mortal being can escape." ) + if term.isColour() then + term.setTextColour( colours.red ) + end + print( "You have died." ) + print( "Score: &e0" ) + term.setTextColour( colours.white ) + bRunning = false + return + end + + local room = getRoom( x,y,z ) + local sItem = findItem( items, _sItem ) + local tRecipe = (sItem and tRecipes[ sItem ]) or nil + if tRecipe then + for n,sReq in ipairs( tRecipe ) do + if inventory[sReq] == nil then + print( "You don't have the items you need to craft "..sItem.."." ) + return + end + end + + for n,sReq in ipairs( tRecipe ) do + inventory[sReq] = nil + end + inventory[ sItem ] = items[ sItem ] + if inventory["some torches"] and inventory["a torch"] then + inventory["a torch"] = nil + end + print( "Crafted." ) + else + print( "You don't know how to make "..(sItem or _sItem).."." ) + end +end + +function commands.build( _sThing, _sMaterial ) + if _sThing == nil then + print( "Build what?" ) + return + end + + local sMaterial = nil + if _sMaterial == nil then + for sItem, tItem in pairs( inventory ) do + if tItem.material then + sMaterial = sItem + break + end + end + if sMaterial == nil then + print( "You don't have any building materials." ) + return + end + else + sMaterial = findItem( inventory, _sMaterial ) + if not sMaterial then + print( "You don't have any ".._sMaterial ) + return + end + + if inventory[sMaterial].material ~= true then + print( sMaterial.." is not a good building material." ) + return + end + end + + local alias = nil + if string.sub(_sThing, 1, 1) == "a" then + alias = string.match( _sThing, "a ([%a ]+)" ) + end + + local room = getRoom( x,y,z ) + inventory[sMaterial] = nil + room.items[ _sThing ] = { + heavy = true, + aliases = { alias }, + desc = "As you look at your creation (made from "..sMaterial.."), you feel a swelling sense of pride.", + } + + print( "Your construction is complete." ) +end + +function commands.help() + local sText = + "Welcome to adventure, the greatest text adventure game on CraftOS. " .. + "To get around the world, type actions, and the adventure will " .. + "be read back to you. The actions availiable to you are go, look, inspect, inventory, " .. + "take, drop, place, punch, attack, mine, dig, craft, build, eat and exit." + print( sText ) +end + +function commands.eat( _sItem ) + if _sItem == nil then + print( "Eat what?" ) + return + end + + local sItem = findItem( inventory, _sItem ) + if not sItem then + print( "You don't have any ".._sItem.."." ) + return + end + + local tItem = inventory[sItem] + if tItem.food then + print( "That was delicious!" ) + inventory[sItem] = nil + + if bInjured then + print( "You are no longer injured." ) + bInjured = false + end + else + print( "You can't eat "..sItem.."." ) + end +end + +function commands.exit() + bRunning = false +end + +function commands.badinput() + local tResponses = { + "I don't understand.", + "I don't understand you.", + "You can't do that.", + "Nope.", + "Huh?", + "Say again?", + "That's crazy talk.", + "Speak clearly.", + "I'll think about it.", + "Let me get back to you on that one.", + "That doesn't make any sense.", + "What?", + } + print( tResponses[ math.random(1,#tResponses) ] ) +end + +function commands.noinput() + local tResponses = { + "Speak up.", + "Enunciate.", + "Project your voice.", + "Don't be shy.", + "Use your words.", + } + print( tResponses[ math.random(1,#tResponses) ] ) +end + +local function simulate() + local bNewMonstersThisRoom = false + + -- Spawn monsters in nearby rooms + for sx = -2,2 do + for sy = -1,1 do + for sz = -2,2 do + local h = y + sy + if h >= -3 and h <= 0 then + local room = getRoom( x + sx, h, z + sz ) + + -- Spawn monsters + if room.nMonsters < 2 and + ((h == 0 and not isSunny() and not room.items["a torch"]) or room.dark) and + math.random(1,6) == 1 then + + local sMonster = tMonsters[ math.random(1,#tMonsters) ] + if room.items[ sMonster ] == nil then + room.items[ sMonster ] = items[ sMonster ] + room.nMonsters = room.nMonsters + 1 + + if sx == 0 and sy == 0 and sz == 0 and not room.dark then + print( "From the shadows, "..sMonster.." appears." ) + bNewMonstersThisRoom = true + end + end + end + + -- Burn monsters + if h == 0 and isSunny() then + for n,sMonster in ipairs( tMonsters ) do + if room.items[sMonster] and items[sMonster].nocturnal then + room.items[sMonster] = nil + if sx == 0 and sy == 0 and sz == 0 and not room.dark then + print( "With the sun high in the sky, the "..items[sMonster].aliases[1].." bursts into flame and dies." ) + end + room.nMonsters = room.nMonsters - 1 + end + end + end + end + end + end + end + + -- Make monsters attack + local room = getRoom( x, y, z ) + if nTimeInRoom >= 2 and not bNewMonstersThisRoom then + for n,sMonster in ipairs( tMonsters ) do + if room.items[sMonster] then + if math.random(1,4) == 1 and + not (y == 0 and isSunny() and (sMonster == "a spider")) then + if sMonster == "a creeper" then + if room.dark then + print( "A creeper explodes." ) + else + print( "The creeper explodes." ) + end + room.items[sMonster] = nil + room.nMonsters = room.nMonsters - 1 + else + if room.dark then + print( "A "..items[sMonster].aliases[1].." attacks you." ) + else + print( "The "..items[sMonster].aliases[1].." attacks you." ) + end + end + + if bInjured then + if term.isColour() then + term.setTextColour( colours.red ) + end + print( "You have died." ) + print( "Score: &e0" ) + term.setTextColour( colours.white ) + bRunning = false + return + else + bInjured = true + end + + break + end + end + end + end + + -- Always print this + if bInjured then + if term.isColour() then + term.setTextColour( colours.red ) + end + print( "You are injured." ) + term.setTextColour( colours.white ) + end + + -- Advance time + nTurn = nTurn + 1 + nTimeInRoom = nTimeInRoom + 1 +end + +doCommand( "look" ) +simulate() + +local tCommandHistory = {} +while bRunning do + if term.isColour() then + term.setTextColour( colours.yellow ) + end + write( "? " ) + term.setTextColour( colours.white ) + + local sRawLine = read( nil, tCommandHistory ) + table.insert( tCommandHistory, sRawLine ) + + local sLine = nil + for match in string.gmatch(sRawLine, "%a+") do + if sLine then + sLine = sLine .. " " .. string.lower(match) + else + sLine = string.lower(match) + end + end + + doCommand( sLine or "" ) + if bRunning then + simulate() + end +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/fun/dj b/src/main/resources/assets/computercraft/lua/rom/programs/fun/dj new file mode 100644 index 0000000000..c120d5f835 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/fun/dj @@ -0,0 +1,50 @@ +local tArgs = { ... } + +local function printUsage() + print( "Usages:") + print( "dj play" ) + print( "dj play " ) + print( "dj stop" ) +end + +if #tArgs > 2 then + printUsage() + return +end + +local sCommand = tArgs[1] +if sCommand == "stop" then + -- Stop audio + disk.stopAudio() + +elseif sCommand == "play" or sCommand == nil then + -- Play audio + local sName = tArgs[2] + if sName == nil then + -- No disc specified, pick one at random + local tNames = {} + for n,sName in ipairs( peripheral.getNames() ) do + if disk.isPresent( sName ) and disk.hasAudio( sName ) then + table.insert( tNames, sName ) + end + end + if #tNames == 0 then + print( "No Music Discs in attached disk drives" ) + return + end + sName = tNames[ math.random(1,#tNames) ] + end + + -- Play the disc + if disk.isPresent( sName ) and disk.hasAudio( sName ) then + print( "Playing "..disk.getAudioTitle( sName ) ) + disk.playAudio( sName ) + else + print( "No Music Disc in disk drive: "..sName ) + return + end + +else + printUsage() + +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/fun/hello b/src/main/resources/assets/computercraft/lua/rom/programs/fun/hello new file mode 100644 index 0000000000..00e2c43a6a --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/fun/hello @@ -0,0 +1,5 @@ +if term.isColour() then + term.setTextColour( 2^math.random(0,15) ) +end +textutils.slowPrint( "Hello World!" ) +term.setTextColour( colours.white ) diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/fun/worm b/src/main/resources/assets/computercraft/lua/rom/programs/fun/worm new file mode 100644 index 0000000000..d358470151 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/fun/worm @@ -0,0 +1,291 @@ + +-- Display the start screen +local w,h = term.getSize() + +local titleColour, headingColour, textColour, wormColour, fruitColour +if term.isColour() then + titleColour = colours.red + headingColour = colours.yellow + textColour = colours.white + wormColour = colours.green + fruitColour = colours.red +else + titleColour = colours.white + headingColour = colours.white + textColour = colours.white + wormColour = colours.white + fruitColour = colours.white +end + +local function printCentred( y, s ) + local x = math.floor((w - string.len(s)) / 2) + term.setCursorPos(x,y) + --term.clearLine() + term.write( s ) +end + +local xVel,yVel = 1,0 +local xPos, yPos = math.floor(w/2), math.floor(h/2) +local pxVel, pyVel = nil, nil + +local nLength = 1 +local nExtraLength = 6 +local bRunning = true + +local tailX,tailY = xPos,yPos +local nScore = 0 +local nDifficulty = 2 +local nSpeed, nInterval + +-- Setup the screen +local screen = {} +for x=1,w do + screen[x] = {} + for y=1,h do + screen[x][y] = {} + end +end +screen[xPos][yPos] = { snake = true } + +local nFruit = 1 +local tFruits = { + "A", "B", "C", "D", "E", "F", "G", "H", + "I", "J", "K", "L", "M", "N", "O", "P", + "Q", "R", "S", "T", "U", "V", "W", "X", + "Y", "Z", + "a", "b", "c", "d", "e", "f", "g", "h", + "i", "j", "k", "l", "m", "n", "o", "p", + "q", "r", "s", "t", "u", "v", "w", "x", + "y", "z", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", + "@", "$", "%", "#", "&", "!", "?", "+", "*", "~" +} + +local function addFruit() + while true do + local x = math.random(1,w) + local y = math.random(2,h) + local fruit = screen[x][y] + if fruit.snake == nil and fruit.wall == nil and fruit.fruit == nil then + screen[x][y] = { fruit = true } + term.setCursorPos(x,y) + term.setBackgroundColour( fruitColour ) + term.write(" ") + term.setBackgroundColour( colours.black ) + break + end + end + + nFruit = nFruit + 1 + if nFruit > #tFruits then + nFruit = 1 + end +end + +local function drawMenu() + term.setTextColour( headingColour ) + term.setCursorPos(1,1) + term.write( "SCORE " ) + + term.setTextColour( textColour ) + term.setCursorPos(7,1) + term.write( tostring(nScore) ) + + term.setTextColour( headingColour ) + term.setCursorPos(w-11,1) + term.write( "DIFFICULTY ") + + term.setTextColour( textColour ) + term.setCursorPos(w,1) + term.write( tostring(nDifficulty or "?") ) + + term.setTextColour( colours.white ) +end + +local function update( ) + local x,y = xPos,yPos + if pxVel and pyVel then + xVel, yVel = pxVel, pyVel + pxVel, pyVel = nil, nil + end + + -- Remove the tail + if nExtraLength == 0 then + local tail = screen[tailX][tailY] + screen[tailX][tailY] = {} + term.setCursorPos(tailX,tailY) + term.write(" ") + tailX = tail.nextX + tailY = tail.nextY + else + nExtraLength = nExtraLength - 1 + end + + -- Update the head + local head = screen[xPos][yPos] + local newXPos = xPos + xVel + local newYPos = yPos + yVel + if newXPos < 1 then + newXPos = w + elseif newXPos > w then + newXPos = 1 + end + if newYPos < 2 then + newYPos = h + elseif newYPos > h then + newYPos = 2 + end + + local newHead = screen[newXPos][newYPos] + term.setCursorPos(1,1); + print( newHead.snake ) + if newHead.snake == true or newHead.wall == true then + bRunning = false + + else + if newHead.fruit == true then + nScore = nScore + 10 + nExtraLength = nExtraLength + 1 + addFruit() + end + xPos = newXPos + yPos = newYPos + head.nextX = newXPos + head.nextY = newYPos + screen[newXPos][newYPos] = { snake = true } + + end + + term.setCursorPos(xPos,yPos) + term.setBackgroundColour( wormColour ) + term.write(" ") + term.setBackgroundColour( colours.black ) + + drawMenu() +end + +-- Display the frontend +term.clear() +local function drawFrontend() + --term.setTextColour( titleColour ) + --printCentred( math.floor(h/2) - 4, " W O R M " ) + + term.setTextColour( headingColour ) + printCentred( math.floor(h/2) - 3, "" ) + printCentred( math.floor(h/2) - 2, " SELECT DIFFICULTY " ) + printCentred( math.floor(h/2) - 1, "" ) + + printCentred( math.floor(h/2) + 0, " " ) + printCentred( math.floor(h/2) + 1, " " ) + printCentred( math.floor(h/2) + 2, " " ) + printCentred( math.floor(h/2) - 1 + nDifficulty, " [ ] " ) + + term.setTextColour( textColour ) + printCentred( math.floor(h/2) + 0, "EASY" ) + printCentred( math.floor(h/2) + 1, "MEDIUM" ) + printCentred( math.floor(h/2) + 2, "HARD" ) + printCentred( math.floor(h/2) + 3, "" ) + + term.setTextColour( colours.white ) +end + +drawMenu() +drawFrontend() +while true do + local e,key = os.pullEvent( "key" ) + if key == keys.up or key == keys.w then + -- Up + if nDifficulty > 1 then + nDifficulty = nDifficulty - 1 + drawMenu() + drawFrontend() + end + elseif key == keys.down or key == keys.s then + -- Down + if nDifficulty < 3 then + nDifficulty = nDifficulty + 1 + drawMenu() + drawFrontend() + end + elseif key == keys.enter then + -- Enter + break + end +end + +local tSpeeds = { 5, 10, 25 } +nSpeed = tSpeeds[nDifficulty] +nInterval = 1 / nSpeed + +-- Grow the snake to its intended size +term.clear() +drawMenu() +screen[tailX][tailY].snake = true +while nExtraLength > 0 do + update() +end +addFruit() +addFruit() + +-- Play the game +local timer = os.startTimer(0) +while bRunning do + local event, p1, p2 = os.pullEvent() + if event == "timer" and p1 == timer then + timer = os.startTimer(nInterval) + update( false ) + + elseif event == "key" then + local key = p1 + if key == keys.up or key == keys.w then + -- Up + if yVel == 0 then + pxVel,pyVel = 0,-1 + end + elseif key == keys.down or key == keys.s then + -- Down + if yVel == 0 then + pxVel,pyVel = 0,1 + end + elseif key == keys.left or key == keys.a then + -- Left + if xVel == 0 then + pxVel,pyVel = -1,0 + end + + elseif key == keys.right or key == keys.d then + -- Right + if xVel == 0 then + pxVel,pyVel = 1,0 + end + + end + end +end + +-- Display the gameover screen +term.setTextColour( headingColour ) +printCentred( math.floor(h/2) - 2, " " ) +printCentred( math.floor(h/2) - 1, " G A M E O V E R " ) + +term.setTextColour( textColour ) +printCentred( math.floor(h/2) + 0, " " ) +printCentred( math.floor(h/2) + 1, " FINAL SCORE "..nScore.." " ) +printCentred( math.floor(h/2) + 2, " " ) +term.setTextColour( colours.white ) + +local timer = os.startTimer(2.5) +repeat + local e,p = os.pullEvent() + if e == "timer" and p == timer then + term.setTextColour( textColour ) + printCentred( math.floor(h/2) + 2, " PRESS ANY KEY " ) + printCentred( math.floor(h/2) + 3, " " ) + term.setTextColour( colours.white ) + end +until e == "char" + +term.clear() +term.setCursorPos(1,1) + + \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/gps b/src/main/resources/assets/computercraft/lua/rom/programs/gps new file mode 100644 index 0000000000..d8ffd942b0 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/gps @@ -0,0 +1,104 @@ + +local function printUsage() + print( "Usages:" ) + print( "gps host" ) + print( "gps host " ) + print( "gps locate" ) +end + +local tArgs = { ... } +if #tArgs < 1 then + printUsage() + return +end + + local sCommand = tArgs[1] +if sCommand == "locate" then + -- "gps locate" + -- Just locate this computer (this will print the results) + gps.locate( 2, true ) + +elseif sCommand == "host" then + -- "gps host" + -- Act as a GPS host + if pocket then + print( "GPS Hosts must be stationary" ) + return + end + + -- Find a modem + local sModemSide = nil + for n,sSide in ipairs( rs.getSides() ) do + if peripheral.getType( sSide ) == "modem" and peripheral.call( sSide, "isWireless" ) then + sModemSide = sSide + break + end + end + + if sModemSide == nil then + print( "No wireless modems found. 1 required." ) + return + end + + -- Determine position + local x,y,z + if #tArgs >= 4 then + -- Position is manually specified + x = tonumber(tArgs[2]) + y = tonumber(tArgs[3]) + z = tonumber(tArgs[4]) + if x == nil or y == nil or z == nil then + printUsage() + return + end + print( "Position is "..x..","..y..","..z ) + else + -- Position is to be determined using locate + x,y,z = gps.locate( 2, true ) + if x == nil then + print( "Run \"gps host \" to set position manually" ) + if bCloseChannel then + print( "Closing GPS channel" ) + modem.close( gps.CHANNEL_GPS ) + end + return + end + end + + -- Open a channel + local modem = peripheral.wrap( sModemSide ) + print( "Opening channel on modem "..sModemSide ) + modem.open( gps.CHANNEL_GPS ) + + -- Serve requests indefinately + local nServed = 0 + while true do + local e, p1, p2, p3, p4, p5 = os.pullEvent( "modem_message" ) + if e == "modem_message" then + -- We received a message from a modem + local sSide, sChannel, sReplyChannel, sMessage, nDistance = p1, p2, p3, p4, p5 + if sSide == sModemSide and sChannel == gps.CHANNEL_GPS and sMessage == "PING" and nDistance then + -- We received a ping message on the GPS channel, send a response + modem.transmit( sReplyChannel, gps.CHANNEL_GPS, { x, y, z } ) + + -- Print the number of requests handled + nServed = nServed + 1 + if nServed > 1 then + local x,y = term.getCursorPos() + term.setCursorPos(1,y-1) + end + print( nServed.." GPS requests served" ) + end + end + end + + -- Close the channel + print( "Closing channel" ) + modem.close( gps.CHANNEL_GPS ) + +else + -- "gps somethingelse" + -- Error + printUsage() + +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/help b/src/main/resources/assets/computercraft/lua/rom/programs/help new file mode 100644 index 0000000000..8fd4a73ccd --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/help @@ -0,0 +1,29 @@ +local tArgs = { ... } +if #tArgs > 0 then + sTopic = tArgs[1] +else + sTopic = "intro" +end + +if sTopic == "index" then + print( "Help topics availiable:" ) + local tTopics = help.topics() + textutils.pagedTabulate( tTopics ) + return +end + +local w,h = term.getSize() +local sFile = help.lookup( sTopic ) +local file = ((sFile ~= nil) and io.open( sFile )) or nil +local nLinesPrinted = 0 +if file then + local sLine = file:read() + local nLines = 0 + while sLine do + nLines = nLines + textutils.pagedPrint( sLine, (h-3) - nLines ) + sLine = file:read() + end + file:close() +else + print( "No help available" ) +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/http/pastebin b/src/main/resources/assets/computercraft/lua/rom/programs/http/pastebin new file mode 100644 index 0000000000..1d48cbdc7d --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/http/pastebin @@ -0,0 +1,124 @@ + +local function printUsage() + print( "Usages:" ) + print( "pastebin put " ) + print( "pastebin get " ) + print( "pastebin run " ) +end + +local tArgs = { ... } +if #tArgs < 2 then + printUsage() + return +end + +if not http then + printError( "Pastebin requires http API" ) + printError( "Set http_enable to true in ComputerCraft.cfg" ) + return +end + +local function get(paste) + write( "Connecting to pastebin.com... " ) + local response = http.get( + "http://pastebin.com/raw/"..textutils.urlEncode( paste ) + ) + + if response then + print( "Success." ) + + local sResponse = response.readAll() + response.close() + return sResponse + else + print( "Failed." ) + end +end + +local sCommand = tArgs[1] +if sCommand == "put" then + -- Upload a file to pastebin.com + -- Determine file to upload + local sFile = tArgs[2] + local sPath = shell.resolve( sFile ) + if not fs.exists( sPath ) or fs.isDir( sPath ) then + print( "No such file" ) + return + end + + -- Read in the file + local sName = fs.getName( sPath ) + local file = fs.open( sPath, "r" ) + local sText = file.readAll() + file.close() + + -- POST the contents to pastebin + write( "Connecting to pastebin.com... " ) + local key = "0ec2eb25b6166c0c27a394ae118ad829" + local response = http.post( + "http://pastebin.com/api/api_post.php", + "api_option=paste&".. + "api_dev_key="..key.."&".. + "api_paste_format=lua&".. + "api_paste_name="..textutils.urlEncode(sName).."&".. + "api_paste_code="..textutils.urlEncode(sText) + ) + + if response then + print( "Success." ) + + local sResponse = response.readAll() + response.close() + + local sCode = string.match( sResponse, "[^/]+$" ) + print( "Uploaded as "..sResponse ) + print( "Run \"pastebin get "..sCode.."\" to download anywhere" ) + + else + print( "Failed." ) + end + +elseif sCommand == "get" then + -- Download a file from pastebin.com + if #tArgs < 3 then + printUsage() + return + end + + -- Determine file to download + local sCode = tArgs[2] + local sFile = tArgs[3] + local sPath = shell.resolve( sFile ) + if fs.exists( sPath ) then + print( "File already exists" ) + return + end + + -- GET the contents from pastebin + local res = get(sCode) + if res then + local file = fs.open( sPath, "w" ) + file.write( res ) + file.close() + + print( "Downloaded as "..sFile ) + end +elseif sCommand == "run" then + local sCode = tArgs[2] + + local res = get(sCode) + if res then + local func, err = load(res, sCode, "t", _ENV) + if not func then + printError( err ) + return + end + local success, msg = pcall(func, table.unpack(tArgs, 3)) + if not success then + printError( msg ) + end + end +else + printUsage() + return +end \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/http/wget b/src/main/resources/assets/computercraft/lua/rom/programs/http/wget new file mode 100644 index 0000000000..834e988d31 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/http/wget @@ -0,0 +1,61 @@ + +local function printUsage() + print( "Usage:" ) + print( "wget " ) +end + +local tArgs = { ... } +if #tArgs < 2 then + printUsage() + return +end + +if not http then + printError( "wget requires http API" ) + printError( "Set http_enable to true in ComputerCraft.cfg" ) + return +end + +local function get( sUrl ) + write( "Connecting to " .. sUrl .. "... " ) + + local ok, err = http.checkURL( sUrl ) + if not ok then + print( "Failed." ) + if err then + printError( err ) + end + return nil + end + + local response = http.get( sUrl ) + if not response then + print( "Failed." ) + return nil + end + + print( "Success." ) + + local sResponse = response.readAll() + response.close() + return sResponse +end + +-- Determine file to download +local sUrl = tArgs[1] +local sFile = tArgs[2] +local sPath = shell.resolve( sFile ) +if fs.exists( sPath ) then + print( "File already exists" ) + return +end + +-- Do the get +local res = get( sUrl ) +if res then + local file = fs.open( sPath, "w" ) + file.write( res ) + file.close() + + print( "Downloaded as "..sFile ) +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/id b/src/main/resources/assets/computercraft/lua/rom/programs/id new file mode 100644 index 0000000000..2efa47c78a --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/id @@ -0,0 +1,30 @@ + +local sDrive = nil +local tArgs = { ... } +if #tArgs > 0 then + sDrive = tostring( tArgs[1] ) +end + +if sDrive == nil then + print( "This is computer #"..os.getComputerID() ) + + local label = os.getComputerLabel() + if label then + print( "This computer is labelled \""..label.."\"" ) + end + +else + local bData = disk.hasData( sDrive ) + if not bData then + print( "No disk in drive "..sDrive ) + return + end + + print( "The disk is #"..disk.getID( sDrive ) ) + + local label = disk.getLabel( sDrive ) + if label then + print( "The disk is labelled \""..label.."\"" ) + end +end + diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/label b/src/main/resources/assets/computercraft/lua/rom/programs/label new file mode 100644 index 0000000000..c50ebc51f2 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/label @@ -0,0 +1,100 @@ + +local function printUsage() + print( "Usages:" ) + print( "label get" ) + print( "label get " ) + print( "label set " ) + print( "label set " ) + print( "label clear" ) + print( "label clear " ) +end + +local function checkDrive( sDrive ) + if peripheral.getType( sDrive ) == "drive" then + -- Check the disk exists + local bData = disk.hasData( sDrive ) + if not bData then + print( "No disk in "..sDrive.." drive" ) + return false + end + else + print( "No disk drive named "..sDrive ) + return false + end + return true +end + +local function get( sDrive ) + if sDrive ~= nil then + if checkDrive( sDrive ) then + local sLabel = disk.getLabel( sDrive ) + if sLabel then + print( "Disk label is \""..sLabel.."\"" ) + else + print( "No Disk label" ) + end + end + else + local sLabel = os.getComputerLabel() + if sLabel then + print( "Computer label is \""..sLabel.."\"" ) + else + print( "No Computer label" ) + end + end +end + +local function set( sDrive, sText ) + if sDrive ~= nil then + if checkDrive( sDrive ) then + disk.setLabel( sDrive, sText ) + local sLabel = disk.getLabel( sDrive ) + if sLabel then + print( "Disk label set to \""..sLabel.."\"" ) + else + print( "Disk label cleared" ) + end + end + else + os.setComputerLabel( sText ) + local sLabel = os.getComputerLabel() + if sLabel then + print( "Computer label set to \""..sLabel.."\"" ) + else + print( "Computer label cleared" ) + end + end +end + +local tArgs = { ... } +local sCommand = tArgs[1] +if sCommand == "get" then + -- Get a label + if #tArgs == 1 then + get( nil ) + elseif #tArgs == 2 then + get( tArgs[2] ) + else + printUsage() + end +elseif sCommand == "set" then + -- Set a label + if #tArgs == 2 then + set( nil, tArgs[2] ) + elseif #tArgs == 3 then + set( tArgs[2], tArgs[3] ) + else + printUsage() + end +elseif sCommand == "clear" then + -- Clear a label + if #tArgs == 1 then + set( nil, nil ) + elseif #tArgs == 2 then + set( tArgs[2], nil ) + else + printUsage() + end +else + printUsage() +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/list b/src/main/resources/assets/computercraft/lua/rom/programs/list new file mode 100644 index 0000000000..d6693f9531 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/list @@ -0,0 +1,33 @@ + +local tArgs = { ... } + +-- Get all the files in the directory +local sDir = shell.dir() +if tArgs[1] ~= nil then + sDir = shell.resolve( tArgs[1] ) +end + +-- Sort into dirs/files, and calculate column count +local tAll = fs.list( sDir ) +local tFiles = {} +local tDirs = {} + +local bShowHidden = settings.get( "list.show_hidden" ) +for n, sItem in pairs( tAll ) do + if bShowHidden or string.sub( sItem, 1, 1 ) ~= "." then + local sPath = fs.combine( sDir, sItem ) + if fs.isDir( sPath ) then + table.insert( tDirs, sItem ) + else + table.insert( tFiles, sItem ) + end + end +end +table.sort( tDirs ) +table.sort( tFiles ) + +if term.isColour() then + textutils.pagedTabulate( colors.green, tDirs, colors.white, tFiles ) +else + textutils.pagedTabulate( tDirs, tFiles ) +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/lua b/src/main/resources/assets/computercraft/lua/rom/programs/lua new file mode 100644 index 0000000000..edff066c09 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/lua @@ -0,0 +1,94 @@ + +local tArgs = { ... } +if #tArgs > 0 then + print( "This is an interactive Lua prompt." ) + print( "To run a lua program, just type its name." ) + return +end + +local bRunning = true +local tCommandHistory = {} +local tEnv = { + ["exit"] = function() + bRunning = false + end, + ["_echo"] = function( ... ) + return ... + end, +} +setmetatable( tEnv, { __index = _ENV } ) + +if term.isColour() then + term.setTextColour( colours.yellow ) +end +print( "Interactive Lua prompt." ) +print( "Call exit() to exit." ) +term.setTextColour( colours.white ) + +while bRunning do + --if term.isColour() then + -- term.setTextColour( colours.yellow ) + --end + write( "lua> " ) + --term.setTextColour( colours.white ) + + local s = read( nil, tCommandHistory, function( sLine ) + if settings.get( "lua.autocomplete" ) then + local nStartPos = string.find( sLine, "[a-zA-Z0-9_%.]+$" ) + if nStartPos then + sLine = string.sub( sLine, nStartPos ) + end + if #sLine > 0 then + return textutils.complete( sLine, tEnv ) + end + end + return nil + end ) + table.insert( tCommandHistory, s ) + + local nForcePrint = 0 + local func, e = load( s, "lua", "t", tEnv ) + local func2, e2 = load( "return _echo("..s..");", "lua", "t", tEnv ) + if not func then + if func2 then + func = func2 + e = nil + nForcePrint = 1 + end + else + if func2 then + func = func2 + end + end + + if func then + local tResults = { pcall( func ) } + if tResults[1] then + local n = 1 + while (tResults[n + 1] ~= nil) or (n <= nForcePrint) do + local value = tResults[ n + 1 ] + if type( value ) == "table" then + local metatable = getmetatable( value ) + if type(metatable) == "table" and type(metatable.__tostring) == "function" then + print( tostring( value ) ) + else + local ok, serialised = pcall( textutils.serialise, value ) + if ok then + print( serialised ) + else + print( tostring( value ) ) + end + end + else + print( tostring( value ) ) + end + n = n + 1 + end + else + printError( tResults[2] ) + end + else + printError( e ) + end + +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/mkdir b/src/main/resources/assets/computercraft/lua/rom/programs/mkdir new file mode 100644 index 0000000000..584bbdc2d9 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/mkdir @@ -0,0 +1,9 @@ +local tArgs = { ... } +if #tArgs < 1 then + print( "Usage: mkdir " ) + return +end + +local sNewDir = shell.resolve( tArgs[1] ) +fs.makeDir( sNewDir ) + diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/monitor b/src/main/resources/assets/computercraft/lua/rom/programs/monitor new file mode 100644 index 0000000000..bf123516d4 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/monitor @@ -0,0 +1,67 @@ + +local function printUsage() + print( "Usage: monitor " ) + return +end + +local tArgs = { ... } +if #tArgs < 2 then + printUsage() + return +end + +local sName = tArgs[1] +if peripheral.getType( sName ) ~= "monitor" then + print( "No monitor named ".. sName ) + return +end + +local sProgram = tArgs[2] +local sPath = shell.resolveProgram( sProgram ) +if sPath == nil then + print( "No such program: "..sProgram ) + return +end + +print( "Running "..sProgram.." on monitor "..sName ) + +local monitor = peripheral.wrap( sName ) +local previousTerm = term.redirect( monitor ) + +local co = coroutine.create( function() + shell.run( sProgram, table.unpack( tArgs, 3 ) ) +end ) + +local function resume( ... ) + local ok, param = coroutine.resume( co, ... ) + if not ok then + printError( param ) + end + return param +end + +local ok, param = pcall( function() + local sFilter = resume() + while coroutine.status( co ) ~= "dead" do + local tEvent = { os.pullEventRaw() } + if sFilter == nil or tEvent[1] == sFilter or tEvent[1] == "terminate" then + sFilter = resume( table.unpack( tEvent ) ) + end + if coroutine.status( co ) ~= "dead" and (sFilter == nil or sFilter == "mouse_click") then + if tEvent[1] == "monitor_touch" and tEvent[2] == sName then + sFilter = resume( "mouse_click", 1, table.unpack( tEvent, 3 ) ) + end + end + if coroutine.status( co ) ~= "dead" and (sFilter == nil or sFilter == "term_resize") then + if tEvent[1] == "monitor_resize" and tEvent[2] == sName then + sFilter = resume( "term_resize" ) + end + end + end +end ) + +term.redirect( previousTerm ) +if not ok then + printError( param ) +end + diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/move b/src/main/resources/assets/computercraft/lua/rom/programs/move new file mode 100644 index 0000000000..7a0f0c8300 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/move @@ -0,0 +1,24 @@ + +local tArgs = { ... } +if #tArgs < 2 then + print( "Usage: mv " ) + return +end + +local sSource = shell.resolve( tArgs[1] ) +local sDest = shell.resolve( tArgs[2] ) +local tFiles = fs.find( sSource ) +if #tFiles > 0 then + for n,sFile in ipairs( tFiles ) do + if fs.isDir( sDest ) then + fs.move( sFile, fs.combine( sDest, fs.getName(sFile) ) ) + elseif #tFiles == 1 then + fs.move( sFile, sDest ) + else + printError( "Cannot overwrite file multiple times" ) + return + end + end +else + printError( "No matching files" ) +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/peripherals b/src/main/resources/assets/computercraft/lua/rom/programs/peripherals new file mode 100644 index 0000000000..9f40112208 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/peripherals @@ -0,0 +1,10 @@ +local tPeripherals = peripheral.getNames() +print( "Attached Peripherals:" ) +if #tPeripherals > 0 then + for n=1,#tPeripherals do + local sPeripheral = tPeripherals[n] + print( sPeripheral .. " (" .. peripheral.getType( sPeripheral ) .. ")" ) + end +else + print( "None" ) +end \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/pocket/falling b/src/main/resources/assets/computercraft/lua/rom/programs/pocket/falling new file mode 100644 index 0000000000..2028debb07 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/pocket/falling @@ -0,0 +1,651 @@ +--[[ +Falling - Based on Tetris by Alexey Pajitnov +This version written by Gopher, at the request of Dan200, for +ComputerCraft v1.6. No particular rights are reserved. +--]] + +local function colorass(c,bw) + return term.isColor() and c or bw +end + +local block_s1= { + { + { 1,0,0,0, }, + { 1,1,0,0, }, + { 0,1,0,0, }, + { 0,0,0,0, }, + }, + { + { 0,0,0,0, }, + { 0,1,1,0, }, + { 1,1,0,0, }, + { 0,0,0,0, }, + }, + ch=colorass(" ","{}"), + fg=colorass(colors.blue,colors.black), + bg=colorass(colors.cyan,colors.white), + } +local block_s2= { + { + { 0,1,0,0, }, + { 1,1,0,0, }, + { 1,0,0,0, }, + { 0,0,0,0, }, + }, + { + { 0,0,0,0, }, + { 1,1,0,0, }, + { 0,1,1,0, }, + { 0,0,0,0, }, + }, + ch=colorass(" ","{}"), + fg=colorass(colors.green,colors.black), + bg=colorass(colors.lime,colors.white), + } +local block_line = { + { + { 0,1,0,0, }, + { 0,1,0,0, }, + { 0,1,0,0, }, + { 0,1,0,0, }, + }, + { + { 0,0,0,0, }, + { 1,1,1,1, }, + { 0,0,0,0, }, + { 0,0,0,0, }, + }, + ch=colorass(" ","[]"), + fg=colorass(colors.pink,colors.black), + bg=colorass(colors.red,colors.white), + } +local block_square = { + { + { 1,1,0,0, }, + { 1,1,0,0, }, + { 0,0,0,0, }, + { 0,0,0,0, }, + }, + ch=colorass(" ","[]"), + fg=colorass(colors.lightBlue,colors.black), + bg=colorass(colors.blue,colors.white), + } +local block_L1 = { + { + { 1,1,0,0, }, + { 0,1,0,0, }, + { 0,1,0,0, }, + { 0,0,0,0, }, + }, + { + { 0,0,0,0, }, + { 1,1,1,0, }, + { 1,0,0,0, }, + { 0,0,0,0, }, + }, + { + { 0,1,0,0, }, + { 0,1,0,0, }, + { 0,1,1,0, }, + { 0,0,0,0, }, + }, + { + { 0,0,1,0, }, + { 1,1,1,0, }, + { 0,0,0,0, }, + { 0,0,0,0, }, + }, + ch=colorass(" ","()"), + fg=colorass(colors.orange,colors.black), + bg=colorass(colors.yellow,colors.white), + } +local block_L2 = { + { + { 0,1,0,0, }, + { 0,1,0,0, }, + { 1,1,0,0, }, + { 0,0,0,0, }, + }, + { + { 0,0,0,0, }, + { 1,1,1,0, }, + { 0,0,1,0, }, + { 0,0,0,0, }, + }, + { + { 0,1,1,0, }, + { 0,1,0,0, }, + { 0,1,0,0, }, + { 0,0,0,0, }, + }, + { + { 1,0,0,0, }, + { 1,1,1,0, }, + { 0,0,0,0, }, + { 0,0,0,0, }, + }, + ch=colorass(" ","()"), + fg=colorass(colors.brown,colors.black), + bg=colorass(colors.orange,colors.white), + } +local block_T = { + { + { 0,1,0,0, }, + { 1,1,0,0, }, + { 0,1,0,0, }, + { 0,0,0,0, }, + }, + { + { 0,0,0,0, }, + { 1,1,1,0, }, + { 0,1,0,0, }, + { 0,0,0,0, }, + }, + { + { 0,1,0,0, }, + { 0,1,1,0, }, + { 0,1,0,0, }, + { 0,0,0,0, }, + }, + { + { 0,1,0,0, }, + { 1,1,1,0, }, + { 0,0,0,0, }, + { 0,0,0,0, }, + }, + ch=colorass(" ","<>"), + fg=colorass(colors.cyan,colors.black), + bg=colorass(colors.purple,colors.white), + } + +local blocks={ block_line, block_square, block_s1, block_s2, block_L1, block_L2, block_T} + +local points={4,10,30,120} + +local function lpad(text,amt) + text=tostring(text) + return string.rep(" ",amt-#text)..text +end + +local width,height=term.getSize() + +if height<19 or width<26 then + print("Your screen is too small to play :(") + return +end + + +local speedsByLevel={ + 1.2, + 1.0, + .8, + .65, + .5, + .4, + .3, + .25, + .2, + .15, + .1, + .05,} + +local level=1 + +local function playGame() + local score=0 + local lines=0 + local initialLevel=level + local next=blocks[math.random(1,#blocks)] + + local pit={} + + + local heightAdjust=0 + + if height<=19 then + heightAdjust=1 + end + + + + local function drawScreen() + term.setTextColor(colors.white) + term.setBackgroundColor(colors.black) + term.clear() + + term.setTextColor(colors.black) + term.setBackgroundColor(colorass(colors.lightGray, colors.white)) + term.setCursorPos(22,2) + term.write("Score") --score + term.setCursorPos(22,5) + term.write("Level") --level + term.setCursorPos(22,8) + term.write("Lines") --lines + term.setCursorPos(22,12) + term.write("Next") --next + + term.setCursorPos(21,1) + term.write(" ") + term.setCursorPos(21,2) + term.write(" ") --score + term.setCursorPos(21,3) + term.write(" ") + term.setCursorPos(21,4) + term.write(" ") + term.setCursorPos(21,5) + term.write(" ") --level + term.setCursorPos(21,6) + term.write(" ") + term.setCursorPos(21,7) + term.write(" ") + term.setCursorPos(21,8) + term.write(" ") --lines + term.setCursorPos(21,9) + term.write(" ") + term.setCursorPos(21,10) + term.write(" ") + term.setCursorPos(21,11) + term.write(" ") + term.setCursorPos(21,12) + term.write(" ") --next + term.setCursorPos(26,12) + term.write(" ") --next + term.setCursorPos(21,13) + term.write(" ") + term.setCursorPos(21,14) + term.write(" ") + term.setCursorPos(21,15) + term.write(" ") + term.setCursorPos(21,16) + term.write(" ") + term.setCursorPos(21,17) + term.write(" ") + term.setCursorPos(21,18) + term.write(" ") + term.setCursorPos(21,19) + term.write(" ") + term.setCursorPos(21,20) + term.write(" ") + end + + local function updateNumbers() + term.setTextColor(colors.white) + term.setBackgroundColor(colors.black) + + term.setCursorPos(22,3) + term.write(lpad(score,5)) --score + term.setCursorPos(22,6) + term.write(lpad(level,5)) --level + term.setCursorPos(22,9) + term.write(lpad(lines,5)) --lines + end + + local function drawBlockAt(block,xp,yp,rot) + term.setTextColor(block.fg) + term.setBackgroundColor(block.bg) + for y=1,4 do + for x=1,4 do + if block[rot][y][x]==1 then + term.setCursorPos((xp+x)*2-3,yp+y-1-heightAdjust) + term.write(block.ch) + end + end + end + end + + local function eraseBlockAt(block,xp,yp,rot) + term.setTextColor(colors.white) + term.setBackgroundColor(colors.black) + for y=1,4 do + for x=1,4 do + if block[rot][y][x]==1 then + term.setCursorPos((xp+x)*2-3,yp+y-1-heightAdjust) + term.write(" ") + end + end + end + end + + local function testBlockAt(block,xp,yp,rot) + for y=1,4 do + local ty=yp+y-1 + for x=1,4 do + local tx=xp+x-1 + if block[rot][y][x]==1 then + if tx>10 or tx<1 or ty>20 or pit[ty][tx]~=0 then + return true + end + end + end + end + end + + local function pitBlock(block,xp,yp,rot) + for y=1,4 do + for x=1,4 do + if block[rot][y][x]==1 then + pit[yp+y-1][xp+x-1]=block + end + end + end + end + + + local function clearPit() + for row=1,20 do + pit[row]={} + for col=1,10 do + pit[row][col]=0 + end + end + end + + + + drawScreen() + updateNumbers() + + --declare & init the pit + clearPit() + + + + local halt=false + local dropSpeed=speedsByLevel[math.min(level,12)] + + + local curBlock=next + next=blocks[math.random(1,7)] + + local curX, curY, curRot=4, 1, 1 + local dropTimer=os.startTimer(dropSpeed) + + drawBlockAt(next,11.5,15+heightAdjust,1) + drawBlockAt(curBlock,curX,curY,curRot) + + local function redrawPit() + for r=1+heightAdjust,20 do + term.setCursorPos(1,r-heightAdjust) + for c=1,10 do + if pit[r][c]==0 then + term.setTextColor(colors.black) + term.setBackgroundColor(colors.black) + term.write(" ") + else + term.setTextColor(pit[r][c].fg) + term.setBackgroundColor(pit[r][c].bg) + term.write(pit[r][c].ch) + end + end + end + end + + local function hidePit() + for r=1+heightAdjust,20 do + term.setCursorPos(1,r-heightAdjust) + term.setTextColor(colors.black) + term.setBackgroundColor(colors.black) + term.write(" ") + end + end + + local function msgBox(message) + local x=math.floor((17-#message)/2) + term.setBackgroundColor(colorass(colors.lightGray,colors.white)) + term.setTextColor(colors.black) + term.setCursorPos(x,9) + term.write("+"..string.rep("-",#message+2).."+") + term.setCursorPos(x,10) + term.write("|") + term.setCursorPos(x+#message+3,10) + term.write("|") + term.setCursorPos(x,11) + term.write("+"..string.rep("-",#message+2).."+") + term.setTextColor(colors.white) + term.setBackgroundColor(colors.black) + term.setCursorPos(x+1,10) + term.write(" "..message.." ") + end + + local function clearRows() + local rows={} + for r=1,20 do + local count=0 + for c=1,10 do + if pit[r][c]~=0 then + count=count+1 + else + break + end + end + if count==10 then + rows[#rows+1]=r + end + end + + if #rows>0 then + for i=1,4 do + sleep(.1) + for r=1,#rows do + r=rows[r] + term.setCursorPos(1,r-heightAdjust) + for c=1,10 do + term.setTextColor(pit[r][c].bg) + term.setBackgroundColor(pit[r][c].fg) + term.write(pit[r][c].ch) + end + end + sleep(.1) + for r=1,#rows do + r=rows[r] + term.setCursorPos(1,r-heightAdjust) + for c=1,10 do + term.setTextColor(pit[r][c].fg) + term.setBackgroundColor(pit[r][c].bg) + term.write(pit[r][c].ch) + end + end + end + --now remove the rows and drop everythign else + term.setBackgroundColor(colors.black) + for r=1,#rows do + r=rows[r] + term.setCursorPos(1,r-heightAdjust) + term.write(" ") + end + sleep(.25) + for r=1,#rows do + table.remove(pit,rows[r]) + table.insert(pit,1,{0,0,0,0,0,0,0,0,0,0}) + end + redrawPit() + lines=lines+#rows + score=score+points[#rows]*math.min(level,20) + level=math.floor(lines/10)+initialLevel + dropSpeed=speedsByLevel[math.min(level,12)] + updateNumbers() + end + sleep(.25) + end + + local function blockFall() + local result = false + if testBlockAt(curBlock,curX,curY+1,curRot) then + pitBlock(curBlock,curX,curY,curRot) + --detect rows that clear + clearRows(rows) + + curBlock=next + curX=4 + curY=1 + curRot=1 + if testBlockAt(curBlock,curX,curY,curRot) then + halt=true + end + drawBlockAt(curBlock,curX,curY,curRot) + eraseBlockAt(next,11.5,15+heightAdjust,1) + next=blocks[math.random(1,7)] + drawBlockAt(next,11.5,15+heightAdjust,1) + return true + else + eraseBlockAt(curBlock,curX,curY,curRot) + curY=curY+1 + drawBlockAt(curBlock,curX,curY,curRot) + return false + end + end + + + while not halt do + local e={os.pullEvent()} + if e[1]=="timer" then + if e[2]==dropTimer then + blockFall() + dropTimer=os.startTimer(dropSpeed) + end + elseif e[1]=="key" then + local key=e[2] + local dx,dy,dr=0,0,0 + if key==keys.left or key==keys.a then + dx=-1 + elseif key==keys.right or key==keys.d then + dx=1 + elseif key==keys.up or key==keys.w then + dr=1 + elseif key==keys.down or key==keys.s then + while not blockFall() do end + dropTimer=os.startTimer(dropSpeed) + elseif key==keys.space then + hidePit() + msgBox("Paused") + while ({os.pullEvent("key")})[2]~=keys.space do end + redrawPit() + drawBlockAt(curBlock,curX,curY,curRot) + dropTimer=os.startTimer(dropSpeed) + end + if dx+dr~=0 then + if not testBlockAt(curBlock,curX+dx,curY+dy,(dr>0 and curRot%#curBlock+dr or curRot)) then + eraseBlockAt(curBlock,curX,curY,curRot) + curX=curX+dx + curY=curY+dy + curRot=dr==0 and curRot or (curRot%#curBlock+dr) + drawBlockAt(curBlock,curX,curY,curRot) + end + end + elseif e[1]=="term_resize" then + local w,h=term.getSize() + if h==20 then + heightAdjust=0 + else + heightAdjust=1 + end + redrawPit() + drawBlockAt(curBlock,curX,curY,curRot) + end + end + + msgBox("Game Over!") + while true do + local _,k=os.pullEvent("key") + if k==keys.space or k==keys.enter then + break + end + end + + level = math.min(level,9) +end + + +local selected=1 +local playersDetected=false + +local function drawMenu() + term.setBackgroundColor(colors.black) + term.setTextColor(colorass(colors.red,colors.white)) + term.clear() + + local cx,cy=math.floor(width/2),math.floor(height/2) + + term.setCursorPos(cx-6,cy-2) + term.write("F A L L I N G") + + if playersDetected then + if selected==0 then + term.setTextColor(colorass(colors.blue,colors.black)) + term.setBackgroundColor(colorass(colors.gray,colors.white)) + else + term.setTextColor(colorass(colors.lightBlue,colors.white)) + term.setBackgroundColor(colors.black) + end + term.setCursorPos(cx-12,cy) + term.write(" Play head-to-head game! ") + end + + term.setCursorPos(cx-10,cy+1) + if selected==1 then + term.setTextColor(colorass(colors.blue,colors.black)) + term.setBackgroundColor(colorass(colors.lightGray,colors.white)) + else + term.setTextColor(colorass(colors.lightBlue,colors.white)) + term.setBackgroundColor(colors.black) + end + term.write(" Play from level: <" .. level .. "> ") + + term.setCursorPos(cx-3,cy+3) + if selected==2 then + term.setTextColor(colorass(colors.blue,colors.black)) + term.setBackgroundColor(colorass(colors.lightGray,colors.white)) + else + term.setTextColor(colorass(colors.lightBlue,colors.white)) + term.setBackgroundColor(colors.black) + end + term.write(" Quit ") +end + + +local function runMenu() + drawMenu() + + while true do + local event={os.pullEvent()} + if event[1]=="key" then + local key=event[2] + if key==keys.right or key==keys.d and selected==1 then + level=math.min(level+1,9) + drawMenu() + elseif key==keys.left or key==keys.a and selected==1 then + level=math.max(level-1,1) + drawMenu() + elseif key>=keys.one and key<=keys.nine and selected==1 then + level=(key-keys.one) + 1 + drawMenu() + elseif key==keys.up or key==keys.w then + selected=selected-1 + if selected==0 then + selected=2 + end + drawMenu() + elseif key==keys.down or key==keys.s then + selected=selected%2+1 + drawMenu() + elseif key==keys.enter or key==keys.space then + break --begin play! + end + end + end +end + +while true do + runMenu() + if selected==2 then + break + end + + playGame() +end + + +term.setTextColor(colors.white) +term.setBackgroundColor(colors.black) +term.clear() +term.setCursorPos(1,1) \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/programs b/src/main/resources/assets/computercraft/lua/rom/programs/programs new file mode 100644 index 0000000000..3ef53caa5b --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/programs @@ -0,0 +1,9 @@ + +local bAll = false +local tArgs = { ... } +if #tArgs > 0 and tArgs[1] == "all" then + bAll = true +end + +local tPrograms = shell.programs( bAll ) +textutils.pagedTabulate( tPrograms ) diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/reboot b/src/main/resources/assets/computercraft/lua/rom/programs/reboot new file mode 100644 index 0000000000..5fd4fecf37 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/reboot @@ -0,0 +1,8 @@ +if term.isColour() then + term.setTextColour( colours.yellow ) +end +print( "Goodbye" ) +term.setTextColour( colours.white ) + +sleep( 1 ) +os.reboot() diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/rednet/chat b/src/main/resources/assets/computercraft/lua/rom/programs/rednet/chat new file mode 100644 index 0000000000..0552142c57 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/rednet/chat @@ -0,0 +1,435 @@ + +local tArgs = { ... } + +local function printUsage() + print( "Usages:" ) + print( "chat host " ) + print( "chat join " ) +end + +local sOpenedModem = nil +local function openModem() + for n,sModem in ipairs( peripheral.getNames() ) do + if peripheral.getType( sModem ) == "modem" then + if not rednet.isOpen( sModem ) then + rednet.open( sModem ) + sOpenedModem = sModem + end + return true + end + end + print( "No modems found." ) + return false +end + +local function closeModem() + if sOpenedModem ~= nil then + rednet.close( sOpenedModem ) + sOpenedModem = nil + end +end + +-- Colours +local highlightColour, textColour +if term.isColour() then + textColour = colours.white + highlightColour = colours.yellow +else + textColour = colours.white + highlightColour = colours.white +end + +local sCommand = tArgs[1] +if sCommand == "host" then + -- "chat host" + -- Get hostname + local sHostname = tArgs[2] + if sHostname == nil then + printUsage() + return + end + + -- Host server + if not openModem() then + return + end + rednet.host( "chat", sHostname ) + print( "0 users connected." ) + + local tUsers = {} + local nUsers = 0 + function send( sText, nUserID ) + if nUserID then + local tUser = tUsers[ nUserID ] + if tUser then + rednet.send( tUser.nID, { + sType = "text", + nUserID = nUserID, + sText = sText, + }, "chat" ) + end + else + for nUserID, tUser in pairs( tUsers ) do + rednet.send( tUser.nID, { + sType = "text", + nUserID = nUserID, + sText = sText, + }, "chat" ) + end + end + end + + -- Setup ping pong + local tPingPongTimer = {} + function ping( nUserID ) + local tUser = tUsers[ nUserID ] + rednet.send( tUser.nID, { + sType = "ping to client", + nUserID = nUserID, + }, "chat" ) + + local timer = os.startTimer( 15 ) + tUser.bPingPonged = false + tPingPongTimer[ timer ] = nUserID + end + + function printUsers() + local x,y = term.getCursorPos() + term.setCursorPos( 1, y - 1 ) + term.clearLine() + if nUsers == 1 then + print( nUsers .. " user connected." ) + else + print( nUsers .. " users connected." ) + end + end + + -- Handle messages + local ok, error = pcall( function() + parallel.waitForAny( function() + while true do + local sEvent, timer = os.pullEvent( "timer" ) + local nUserID = tPingPongTimer[ timer ] + if nUserID and tUsers[ nUserID ] then + local tUser = tUsers[ nUserID ] + if tUser then + if not tUser.bPingPonged then + send( "* "..tUser.sUsername.." has timed out" ) + tUsers[ nUserID ] = nil + nUsers = nUsers - 1 + printUsers() + else + ping( nUserID ) + end + end + end + end + end, + function() + while true do + local tCommands + tCommands = { + ["me"] = function( tUser, sContent ) + if string.len(sContent) > 0 then + send( "* "..tUser.sUsername.." "..sContent ) + else + send( "* Usage: /me [words]", tUser.nUserID ) + end + end, + ["nick"] = function( tUser, sContent ) + if string.len(sContent) > 0 then + local sOldName = tUser.sUsername + tUser.sUsername = sContent + send( "* "..sOldName.." is now known as "..tUser.sUsername ) + else + send( "* Usage: /nick [nickname]", tUser.nUserID ) + end + end, + ["users"] = function( tUser, sContent ) + send( "* Connected Users:", tUser.nUserID ) + local sUsers = "*" + for nUserID, tUser in pairs( tUsers ) do + sUsers = sUsers .. " " .. tUser.sUsername + end + send( sUsers, tUser.nUserID ) + end, + ["help"] = function( tUser, sContent ) + send( "* Available commands:", tUser.nUserID ) + local sCommands = "*" + for sCommand, fnCommand in pairs( tCommands ) do + sCommands = sCommands .. " /" .. sCommand + end + send( sCommands.." /logout", tUser.nUserID ) + end, + } + + local nSenderID, tMessage = rednet.receive( "chat" ) + if type( tMessage ) == "table" then + if tMessage.sType == "login" then + -- Login from new client + local nUserID = tMessage.nUserID + local sUsername = tMessage.sUsername + if nUserID and sUsername then + tUsers[ nUserID ] = { + nID = nSenderID, + nUserID = nUserID, + sUsername = sUsername, + } + nUsers = nUsers + 1 + printUsers() + send( "* "..sUsername.." has joined the chat" ) + ping( nUserID ) + end + + else + -- Something else from existing client + local nUserID = tMessage.nUserID + local tUser = tUsers[ nUserID ] + if tUser and tUser.nID == nSenderID then + if tMessage.sType == "logout" then + send( "* "..tUser.sUsername.." has left the chat" ) + tUsers[ nUserID ] = nil + nUsers = nUsers - 1 + printUsers() + + elseif tMessage.sType == "chat" then + local sMessage = tMessage.sText + if sMessage then + local sCommand = string.match( sMessage, "^/([a-z]+)" ) + if sCommand then + local fnCommand = tCommands[ sCommand ] + if fnCommand then + local sContent = string.sub( sMessage, string.len(sCommand)+3 ) + fnCommand( tUser, sContent ) + else + send( "* Unrecognised command: /"..sCommand, tUser.nUserID ) + end + else + send( "<"..tUser.sUsername.."> "..tMessage.sText ) + end + end + + elseif tMessage.sType == "ping to server" then + rednet.send( tUser.nID, { + sType = "pong to client", + nUserID = nUserID, + }, "chat" ) + + elseif tMessage.sType == "pong to server" then + tUser.bPingPonged = true + + end + end + end + end + end + end ) + end ) + if not ok then + printError( error ) + end + + -- Unhost server + for nUserID, tUser in pairs( tUsers ) do + rednet.send( tUser.nID, { + sType = "kick", + nUserID = nUserID, + }, "chat" ) + end + rednet.unhost( "chat" ) + closeModem() + +elseif sCommand == "join" then + -- "chat join" + -- Get hostname and username + local sHostname = tArgs[2] + local sUsername = tArgs[3] + if sHostname == nil or sUsername == nil then + printUsage() + return + end + + -- Connect + if not openModem() then + return + end + write( "Looking up " .. sHostname .. "... " ) + local nHostID = rednet.lookup( "chat", sHostname ) + if nHostID == nil then + print( "Failed." ) + return + else + print( "Success." ) + end + + -- Login + local nUserID = math.random( 1, 2147483647 ) + rednet.send( nHostID, { + sType = "login", + nUserID = nUserID, + sUsername = sUsername, + }, "chat" ) + + -- Setup ping pong + local bPingPonged = true + local pingPongTimer = os.startTimer( 0 ) + + function ping() + rednet.send( nHostID, { + sType = "ping to server", + nUserID = nUserID, + }, "chat" ) + bPingPonged = false + pingPongTimer = os.startTimer( 15 ) + end + + -- Handle messages + local w,h = term.getSize() + local parentTerm = term.current() + local titleWindow = window.create( parentTerm, 1, 1, w, 1, true ) + local historyWindow = window.create( parentTerm, 1, 2, w, h-2, true ) + local promptWindow = window.create( parentTerm, 1, h, w, 1, true ) + historyWindow.setCursorPos( 1, h-2 ) + + term.clear() + term.setTextColour( textColour ) + term.redirect( promptWindow ) + promptWindow.restoreCursor() + + function drawTitle() + local x,y = titleWindow.getCursorPos() + local w,h = titleWindow.getSize() + local sTitle = sUsername.." on "..sHostname + titleWindow.setTextColour( highlightColour ) + titleWindow.setCursorPos( math.floor( w/2 - string.len(sTitle)/2 ), 1 ) + titleWindow.clearLine() + titleWindow.write( sTitle ) + promptWindow.restoreCursor() + end + + function printMessage( sMessage ) + term.redirect( historyWindow ) + print() + if string.match( sMessage, "^\*" ) then + -- Information + term.setTextColour( highlightColour ) + write( sMessage ) + term.setTextColour( textColour ) + else + -- Chat + local sUsernameBit = string.match( sMessage, "^\<[^\>]*\>" ) + if sUsernameBit then + term.setTextColour( highlightColour ) + write( sUsernameBit ) + term.setTextColour( textColour ) + write( string.sub( sMessage, string.len( sUsernameBit ) + 1 ) ) + else + write( sMessage ) + end + end + term.redirect( promptWindow ) + promptWindow.restoreCursor() + end + + drawTitle() + + local ok, error = pcall( function() + parallel.waitForAny( function() + while true do + local sEvent, timer = os.pullEvent() + if sEvent == "timer" then + if timer == pingPongTimer then + if not bPingPonged then + printMessage( "Server timeout." ) + return + else + ping() + end + end + + elseif sEvent == "term_resize" then + local w,h = parentTerm.getSize() + titleWindow.reposition( 1, 1, w, 1 ) + historyWindow.reposition( 1, 2, w, h-2 ) + promptWindow.reposition( 1, h, w, 1 ) + + end + end + end, + function() + while true do + local nSenderID, tMessage = rednet.receive( "chat" ) + if nSenderID == nHostID and type( tMessage ) == "table" and tMessage.nUserID == nUserID then + if tMessage.sType == "text" then + local sText = tMessage.sText + if sText then + printMessage( sText ) + end + + elseif tMessage.sType == "ping to client" then + rednet.send( nSenderID, { + sType = "pong to server", + nUserID = nUserID, + }, "chat" ) + + elseif tMessage.sType == "pong to client" then + bPingPonged = true + + elseif tMessage.sType == "kick" then + return + + end + end + end + end, + function() + local tSendHistory = {} + while true do + promptWindow.setCursorPos( 1,1 ) + promptWindow.clearLine() + promptWindow.setTextColor( highlightColour ) + promptWindow.write( ": ") + promptWindow.setTextColor( textColour ) + + local sChat = read( nil, tSendHistory ) + if string.match( sChat, "^/logout" ) then + break + else + rednet.send( nHostID, { + sType = "chat", + nUserID = nUserID, + sText = sChat, + }, "chat" ) + table.insert( tSendHistory, sChat ) + end + end + end ) + end ) + + -- Close the windows + term.redirect( parentTerm ) + + -- Print error notice + local w,h = term.getSize() + term.setCursorPos( 1, h ) + term.clearLine() + term.setCursorBlink( false ) + if not ok then + printError( error ) + end + + -- Logout + rednet.send( nHostID, { + sType = "logout", + nUserID = nUserID, + }, "chat" ) + closeModem() + + -- Print disconnection notice + print( "Disconnected." ) + +else + -- "chat somethingelse" + printUsage() + +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/rednet/repeat b/src/main/resources/assets/computercraft/lua/rom/programs/rednet/repeat new file mode 100644 index 0000000000..653b398f4a --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/rednet/repeat @@ -0,0 +1,91 @@ + +-- Find modems +local tModems = {} +for n,sModem in ipairs( peripheral.getNames() ) do + if peripheral.getType( sModem ) == "modem" then + table.insert( tModems, sModem ) + end +end +if #tModems == 0 then + print( "No modems found." ) + return +elseif #tModems == 1 then + print( "1 modem found." ) +else + print( #tModems .. " modems found." ) +end + +function open( nChannel ) + for n=1,#tModems do + local sModem = tModems[n] + peripheral.call( sModem, "open", nChannel ) + end +end + +function close( nChannel ) + for n=1,#tModems do + local sModem = tModems[n] + peripheral.call( sModem, "close", nChannel ) + end +end + +-- Open channels +print( "0 messages repeated." ) +open( rednet.CHANNEL_REPEAT ) + +-- Main loop (terminate to break) +local ok, error = pcall( function() + local tReceivedMessages = {} + local tReceivedMessageTimeouts = {} + local nTransmittedMessages = 0 + + while true do + local sEvent, sModem, nChannel, nReplyChannel, tMessage = os.pullEvent() + if sEvent == "modem_message" then + -- Got a modem message, rebroadcast it if it's a rednet thing + if nChannel == rednet.CHANNEL_REPEAT then + if type( tMessage ) == "table" and tMessage.nMessageID and tMessage.nRecipient then + if not tReceivedMessages[ tMessage.nMessageID ] then + -- Ensure we only repeat a message once + tReceivedMessages[ tMessage.nMessageID ] = true + tReceivedMessageTimeouts[ os.startTimer( 30 ) ] = tMessage.nMessageID + + -- Send on all other open modems, to the target and to other repeaters + for n=1,#tModems do + local sOtherModem = tModems[n] + peripheral.call( sOtherModem, "transmit", rednet.CHANNEL_REPEAT, nReplyChannel, tMessage ) + peripheral.call( sOtherModem, "transmit", tMessage.nRecipient, nReplyChannel, tMessage ) + end + + -- Log the event + nTransmittedMessages = nTransmittedMessages + 1 + local x,y = term.getCursorPos() + term.setCursorPos( 1, y - 1 ) + term.clearLine() + if nTransmittedMessages == 1 then + print( nTransmittedMessages .. " message repeated." ) + else + print( nTransmittedMessages .. " messages repeated." ) + end + end + end + end + + elseif sEvent == "timer" then + -- Got a timer event, use it to clear the message history + local nTimer = sModem + local nMessageID = tReceivedMessageTimeouts[ nTimer ] + if nMessageID then + tReceivedMessageTimeouts[ nTimer ] = nil + tReceivedMessages[ nMessageID ] = nil + end + + end + end +end ) +if not ok then + printError( error ) +end + +-- Close channels +close( rednet.CHANNEL_REPEAT ) diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/redstone b/src/main/resources/assets/computercraft/lua/rom/programs/redstone new file mode 100644 index 0000000000..8a6d2db862 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/redstone @@ -0,0 +1,118 @@ + +local tArgs = { ... } + +local function printUsage() + print( "Usages:" ) + print( "redstone probe" ) + print( "redstone set " ) + print( "redstone set " ) + print( "redstone pulse " ) +end + +local sCommand = tArgs[1] +if sCommand == "probe" then + -- "redstone probe" + -- Regular input + print( "Redstone inputs: " ) + + local count = 0 + local bundledCount = 0 + for n,sSide in ipairs( redstone.getSides() ) do + if redstone.getBundledInput( sSide ) > 0 then + bundledCount = bundledCount + 1 + end + if redstone.getInput( sSide ) then + if count > 0 then + io.write( ", " ) + end + io.write( sSide ) + count = count + 1 + end + end + if count > 0 then + print( "." ) + else + print( "None." ) + end + + -- Bundled input + if bundledCount > 0 then + print() + print( "Bundled inputs:" ) + for i,sSide in ipairs( redstone.getSides() ) do + local nInput = redstone.getBundledInput( sSide ) + if nInput ~= 0 then + write( sSide..": " ) + local count = 0 + for sColour,nColour in pairs( colors ) do + if type( nColour ) == "number" and colors.test( nInput, nColour ) then + if count > 0 then + write( ", " ) + end + if term.isColour() then + term.setTextColour( nColour ) + end + write( sColour ) + if term.isColour() then + term.setTextColour( colours.white ) + end + count = count + 1 + end + end + print( "." ) + end + end + end + +elseif sCommand == "pulse" then + -- "redstone pulse" + local sSide = tArgs[2] + local nCount = tonumber( tArgs[3] ) or 1 + local nPeriod = tonumber( tArgs[4] ) or 0.5 + for n=1,nCount do + redstone.setOutput( sSide, true ) + sleep( nPeriod / 2 ) + redstone.setOutput( sSide, false ) + sleep( nPeriod / 2 ) + end + +elseif sCommand == "set" then + -- "redstone set" + local sSide = tArgs[2] + if #tArgs > 3 then + -- Bundled cable output + local sColour = tArgs[3] + local nColour = colors[sColour] or colours[sColour] + if type(nColour) ~= "number" then + printError( "No such color" ) + return + end + + local sValue = tArgs[4] + if sValue == "true" then + rs.setBundledOutput( sSide, colors.combine( rs.getBundledOutput( sSide ), nColour ) ) + elseif sValue == "false" then + rs.setBundledOutput( sSide, colors.subtract( rs.getBundledOutput( sSide ), nColour ) ) + else + print( "Value must be boolean" ) + end + else + -- Regular output + local sValue = tArgs[3] + local nValue = tonumber(sValue) + if sValue == "true" then + rs.setOutput( sSide, true ) + elseif sValue == "false" then + rs.setOutput( sSide, false ) + elseif nValue and nValue >= 0 and nValue <= 15 then + rs.setAnalogOutput( sSide, nValue ) + else + print( "Value must be boolean or 0-15" ) + end + end + +else + -- Something else + printUsage() + +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/rename b/src/main/resources/assets/computercraft/lua/rom/programs/rename new file mode 100644 index 0000000000..2df4fd0efa --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/rename @@ -0,0 +1,9 @@ +local tArgs = { ... } +if #tArgs < 2 then + print( "Usage: rename " ) + return +end + +local sSource = shell.resolve( tArgs[1] ) +local sDest = shell.resolve( tArgs[2] ) +fs.move( sSource, sDest ) diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/set b/src/main/resources/assets/computercraft/lua/rom/programs/set new file mode 100644 index 0000000000..f4e26bc5b5 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/set @@ -0,0 +1,42 @@ + +local tArgs = { ... } +if #tArgs == 0 then + -- "set" + for n,sName in ipairs( settings.getNames() ) do + print( textutils.serialize(sName) .. " is " .. textutils.serialize(settings.get(sName)) ) + end + +elseif #tArgs == 1 then + -- "set foo" + local sName = tArgs[1] + print( textutils.serialize(sName) .. " is " .. textutils.serialize(settings.get(sName)) ) + +else + -- "set foo bar" + local sName = tArgs[1] + local sValue = tArgs[2] + local value + if sValue == "true" then + value = true + elseif sValue == "false" then + value = false + elseif sValue == "nil" then + value = nil + elseif tonumber(sValue) then + value = tonumber(sValue) + else + value = sValue + end + + local oldValue = settings.get( sValue ) + if value ~= nil then + settings.set( sName, value ) + print( textutils.serialize(sName) .. " set to " .. textutils.serialize(value) ) + else + settings.unset( sName ) + print( textutils.serialize(sName) .. " unset" ) + end + if value ~= oldValue then + settings.save( ".settings" ) + end +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/shell b/src/main/resources/assets/computercraft/lua/rom/programs/shell new file mode 100644 index 0000000000..f5fcf22eb8 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/shell @@ -0,0 +1,349 @@ + +local multishell = multishell +local parentShell = shell +local parentTerm = term.current() + +if multishell then + multishell.setTitle( multishell.getCurrent(), "shell" ) +end + +local bExit = false +local sDir = (parentShell and parentShell.dir()) or "" +local sPath = (parentShell and parentShell.path()) or ".:/rom/programs" +local tAliases = (parentShell and parentShell.aliases()) or {} +local tCompletionInfo = (parentShell and parentShell.getCompletionInfo()) or {} +local tProgramStack = {} + +local shell = {} +local tEnv = { + [ "shell" ] = shell, + [ "multishell" ] = multishell, +} + +-- Colours +local promptColour, textColour, bgColour +if term.isColour() then + promptColour = colours.yellow + textColour = colours.white + bgColour = colours.black +else + promptColour = colours.white + textColour = colours.white + bgColour = colours.black +end + +local function run( _sCommand, ... ) + local sPath = shell.resolveProgram( _sCommand ) + if sPath ~= nil then + tProgramStack[#tProgramStack + 1] = sPath + if multishell then + multishell.setTitle( multishell.getCurrent(), fs.getName( sPath ) ) + end + local result = os.run( tEnv, sPath, ... ) + tProgramStack[#tProgramStack] = nil + if multishell then + if #tProgramStack > 0 then + multishell.setTitle( multishell.getCurrent(), fs.getName( tProgramStack[#tProgramStack] ) ) + else + multishell.setTitle( multishell.getCurrent(), "shell" ) + end + end + return result + else + printError( "No such program" ) + return false + end +end + +local function tokenise( ... ) + local sLine = table.concat( { ... }, " " ) + local tWords = {} + local bQuoted = false + for match in string.gmatch( sLine .. "\"", "(.-)\"" ) do + if bQuoted then + table.insert( tWords, match ) + else + for m in string.gmatch( match, "[^ \t]+" ) do + table.insert( tWords, m ) + end + end + bQuoted = not bQuoted + end + return tWords +end + +-- Install shell API +function shell.run( ... ) + local tWords = tokenise( ... ) + local sCommand = tWords[1] + if sCommand then + return run( sCommand, table.unpack( tWords, 2 ) ) + end + return false +end + +function shell.exit() + bExit = true +end + +function shell.dir() + return sDir +end + +function shell.setDir( _sDir ) + sDir = _sDir +end + +function shell.path() + return sPath +end + +function shell.setPath( _sPath ) + sPath = _sPath +end + +function shell.resolve( _sPath ) + local sStartChar = string.sub( _sPath, 1, 1 ) + if sStartChar == "/" or sStartChar == "\\" then + return fs.combine( "", _sPath ) + else + return fs.combine( sDir, _sPath ) + end +end + +function shell.resolveProgram( _sCommand ) + -- Substitute aliases firsts + if tAliases[ _sCommand ] ~= nil then + _sCommand = tAliases[ _sCommand ] + end + + -- If the path is a global path, use it directly + local sStartChar = string.sub( _sCommand, 1, 1 ) + if sStartChar == "/" or sStartChar == "\\" then + local sPath = fs.combine( "", _sCommand ) + if fs.exists( sPath ) and not fs.isDir( sPath ) then + return sPath + end + return nil + end + + -- Otherwise, look on the path variable + for sPath in string.gmatch(sPath, "[^:]+") do + sPath = fs.combine( shell.resolve( sPath ), _sCommand ) + if fs.exists( sPath ) and not fs.isDir( sPath ) then + return sPath + end + end + + -- Not found + return nil +end + +function shell.programs( _bIncludeHidden ) + local tItems = {} + + -- Add programs from the path + for sPath in string.gmatch(sPath, "[^:]+") do + sPath = shell.resolve( sPath ) + if fs.isDir( sPath ) then + local tList = fs.list( sPath ) + for n=1,#tList do + local sFile = tList[n] + if not fs.isDir( fs.combine( sPath, sFile ) ) and + (_bIncludeHidden or string.sub( sFile, 1, 1 ) ~= ".") then + tItems[ sFile ] = true + end + end + end + end + + -- Sort and return + local tItemList = {} + for sItem, b in pairs( tItems ) do + table.insert( tItemList, sItem ) + end + table.sort( tItemList ) + return tItemList +end + +local function completeProgram( sLine ) + if #sLine > 0 and string.sub( sLine, 1, 1 ) == "/" then + -- Add programs from the root + return fs.complete( sLine, "", true, false ) + + else + local tResults = {} + local tSeen = {} + + -- Add aliases + for sAlias, sCommand in pairs( tAliases ) do + if #sAlias > #sLine and string.sub( sAlias, 1, #sLine ) == sLine then + local sResult = string.sub( sAlias, #sLine + 1 ) + if not tSeen[ sResult ] then + table.insert( tResults, sResult ) + tSeen[ sResult ] = true + end + end + end + + -- Add programs from the path + local tPrograms = shell.programs() + for n=1,#tPrograms do + local sProgram = tPrograms[n] + if #sProgram > #sLine and string.sub( sProgram, 1, #sLine ) == sLine then + local sResult = string.sub( sProgram, #sLine + 1 ) + if not tSeen[ sResult ] then + table.insert( tResults, sResult ) + tSeen[ sResult ] = true + end + end + end + + -- Sort and return + table.sort( tResults ) + return tResults + end +end + +local function completeProgramArgument( sProgram, nArgument, sPart, tPreviousParts ) + local tInfo = tCompletionInfo[ sProgram ] + if tInfo then + return tInfo.fnComplete( shell, nArgument, sPart, tPreviousParts ) + end + return nil +end + +function shell.complete( sLine ) + if #sLine > 0 then + local tWords = tokenise( sLine ) + local nIndex = #tWords + if string.sub( sLine, #sLine, #sLine ) == " " then + nIndex = nIndex + 1 + end + if nIndex == 1 then + local sBit = tWords[1] or "" + local sPath = shell.resolveProgram( sBit ) + if tCompletionInfo[ sPath ] then + return { " " } + else + local tResults = completeProgram( sBit ) + for n=1,#tResults do + local sResult = tResults[n] + local sPath = shell.resolveProgram( sBit .. sResult ) + if tCompletionInfo[ sPath ] then + tResults[n] = sResult .. " " + end + end + return tResults + end + + elseif nIndex > 1 then + local sPath = shell.resolveProgram( tWords[1] ) + local sPart = tWords[nIndex] or "" + local tPreviousParts = tWords + tPreviousParts[nIndex] = nil + return completeProgramArgument( sPath , nIndex - 1, sPart, tPreviousParts ) + + end + end + return nil +end + +function shell.completeProgram( sProgram ) + return completeProgram( sProgram ) +end + +function shell.setCompletionFunction( sProgram, fnComplete ) + tCompletionInfo[ sProgram ] = { + fnComplete = fnComplete + } +end + +function shell.getCompletionInfo() + return tCompletionInfo +end + +function shell.getRunningProgram() + if #tProgramStack > 0 then + return tProgramStack[#tProgramStack] + end + return nil +end + +function shell.setAlias( _sCommand, _sProgram ) + tAliases[ _sCommand ] = _sProgram +end + +function shell.clearAlias( _sCommand ) + tAliases[ _sCommand ] = nil +end + +function shell.aliases() + -- Copy aliases + local tCopy = {} + for sAlias, sCommand in pairs( tAliases ) do + tCopy[sAlias] = sCommand + end + return tCopy +end + +if multishell then + function shell.openTab( ... ) + local tWords = tokenise( ... ) + local sCommand = tWords[1] + if sCommand then + local sPath = shell.resolveProgram( sCommand ) + if sPath == "rom/programs/shell" then + return multishell.launch( tEnv, sPath, table.unpack( tWords, 2 ) ) + elseif sPath ~= nil then + return multishell.launch( tEnv, "rom/programs/shell", sCommand, table.unpack( tWords, 2 ) ) + else + printError( "No such program" ) + end + end + end + + function shell.switchTab( nID ) + multishell.setFocus( nID ) + end +end + +local tArgs = { ... } +if #tArgs > 0 then + -- "shell x y z" + -- Run the program specified on the commandline + shell.run( ... ) + +else + -- "shell" + -- Print the header + term.setBackgroundColor( bgColour ) + term.setTextColour( promptColour ) + print( os.version() ) + term.setTextColour( textColour ) + + -- Run the startup program + if parentShell == nil then + shell.run( "/rom/startup" ) + end + + -- Read commands and execute them + local tCommandHistory = {} + while not bExit do + term.redirect( parentTerm ) + term.setBackgroundColor( bgColour ) + term.setTextColour( promptColour ) + write( shell.dir() .. "> " ) + term.setTextColour( textColour ) + + + local sLine + if settings.get( "shell.autocomplete" ) then + sLine = read( nil, tCommandHistory, shell.complete ) + else + sLine = read( nil, tCommandHistory ) + end + table.insert( tCommandHistory, sLine ) + shell.run( sLine ) + end +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/shutdown b/src/main/resources/assets/computercraft/lua/rom/programs/shutdown new file mode 100644 index 0000000000..9bad67272e --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/shutdown @@ -0,0 +1,8 @@ +if term.isColour() then + term.setTextColour( colours.yellow ) +end +print( "Goodbye" ) +term.setTextColour( colours.white ) + +sleep( 1 ) +os.shutdown() diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/time b/src/main/resources/assets/computercraft/lua/rom/programs/time new file mode 100644 index 0000000000..ff5fac8f25 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/time @@ -0,0 +1,3 @@ +local nTime = os.time() +local nDay = os.day() +print( "The time is "..textutils.formatTime( nTime, false ).." on Day "..nDay ) diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/turtle/craft b/src/main/resources/assets/computercraft/lua/rom/programs/turtle/craft new file mode 100644 index 0000000000..c9e90adfd2 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/turtle/craft @@ -0,0 +1,33 @@ + +if not turtle.craft then + print( "Requires a Crafty Turtle" ) + return +end + +local tArgs = { ... } +local nLimit = nil +if #tArgs < 1 then + print( "Usage: craft [number]" ) + return +else + nLimit = tonumber( tArgs[1] ) +end + +local nCrafted = 0 +local nOldCount = turtle.getItemCount( turtle.getSelectedSlot() ) +if turtle.craft( nLimit ) then + local nNewCount = turtle.getItemCount( turtle.getSelectedSlot() ) + if nOldCount <= nLimit then + nCrafted = nNewCount + else + nCrafted = nOldCount - nNewCount + end +end + +if nCrafted > 1 then + print( nCrafted.." items crafted" ) +elseif nCrafted == 1 then + print( "1 item crafted" ) +else + print( "No items crafted" ) +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/turtle/dance b/src/main/resources/assets/computercraft/lua/rom/programs/turtle/dance new file mode 100644 index 0000000000..0ebc7f9c25 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/turtle/dance @@ -0,0 +1,112 @@ + +local tMoves = { + function() + turtle.up() + turtle.down() + end, + function() + turtle.up() + turtle.turnLeft() + turtle.turnLeft() + turtle.turnLeft() + turtle.turnLeft() + turtle.down() + end, + function() + turtle.up() + turtle.turnRight() + turtle.turnRight() + turtle.turnRight() + turtle.turnRight() + turtle.down() + end, + function() + turtle.turnLeft() + turtle.turnLeft() + turtle.turnLeft() + turtle.turnLeft() + end, + function() + turtle.turnRight() + turtle.turnRight() + turtle.turnRight() + turtle.turnRight() + end, + function() + turtle.turnLeft() + turtle.back() + turtle.back() + turtle.turnRight() + turtle.turnRight() + turtle.back() + turtle.back() + turtle.turnLeft() + end, + function() + turtle.turnRight() + turtle.back() + turtle.back() + turtle.turnLeft() + turtle.turnLeft() + turtle.back() + turtle.back() + turtle.turnRight() + end, + function() + turtle.back() + turtle.turnLeft() + turtle.back() + turtle.turnLeft() + turtle.back() + turtle.turnLeft() + turtle.back() + turtle.turnLeft() + end, + function() + turtle.back() + turtle.turnRight() + turtle.back() + turtle.turnRight() + turtle.back() + turtle.turnRight() + turtle.back() + turtle.turnRight() + end, +} + +textutils.slowWrite( "Preparing to get down." ) +textutils.slowPrint( "..", 0.75 ) + +local sAudio = nil +for n,sName in pairs( peripheral.getNames() ) do + if disk.hasAudio( sName ) then + disk.playAudio( sName ) + print( "Jamming to "..disk.getAudioTitle( sName ) ) + sAudio = sName + break + end +end + +print( "Press any key to stop the groove" ) + +local bEnd = false +parallel.waitForAll( + function() + while not bEnd do + local event, key = os.pullEvent("key") + if key ~= keys.escape then + bEnd = true + end + end + end, + function() + while not bEnd do + local fnMove = tMoves[math.random(1,#tMoves)] + fnMove() + end + end +) + +if sAudio then + disk.stopAudio( sAudio ) +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/turtle/equip b/src/main/resources/assets/computercraft/lua/rom/programs/turtle/equip new file mode 100644 index 0000000000..4ae9af584f --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/turtle/equip @@ -0,0 +1,38 @@ + +local tArgs = { ... } +local function printUsage() + print( "Usage: equip " ) +end + +if #tArgs ~= 2 then + printUsage() + return +end + +local function equip( nSlot, fnEquipFunction ) + turtle.select( nSlot ) + local nOldCount = turtle.getItemCount( nSlot ) + if nOldCount == 0 then + print( "Nothing to equip" ) + elseif fnEquipFunction() then + local nNewCount = turtle.getItemCount( nSlot ) + if nNewCount > 0 then + print( "Items swapped" ) + else + print( "Item equipped" ) + end + else + print( "Item not equippable" ) + end +end + +local nSlot = tonumber( tArgs[1] ) +local sSide = tArgs[2] +if sSide == "left" then + equip( nSlot, turtle.equipLeft ) +elseif sSide == "right" then + equip( nSlot, turtle.equipRight ) +else + printUsage() + return +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/turtle/excavate b/src/main/resources/assets/computercraft/lua/rom/programs/turtle/excavate new file mode 100644 index 0000000000..2565cfa0fa --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/turtle/excavate @@ -0,0 +1,353 @@ + +local tArgs = { ... } +if #tArgs ~= 1 then + print( "Usage: excavate " ) + return +end + +-- Mine in a quarry pattern until we hit something we can't dig +local size = tonumber( tArgs[1] ) +if size < 1 then + print( "Excavate diameter must be positive" ) + return +end + +local depth = 0 +local unloaded = 0 +local collected = 0 + +local xPos,zPos = 0,0 +local xDir,zDir = 0,1 + +local goTo -- Filled in further down +local refuel -- Filled in further down + +local function unload( _bKeepOneFuelStack ) + print( "Unloading items..." ) + for n=1,16 do + local nCount = turtle.getItemCount(n) + if nCount > 0 then + turtle.select(n) + local bDrop = true + if _bKeepOneFuelStack and turtle.refuel(0) then + bDrop = false + _bKeepOneFuelStack = false + end + if bDrop then + turtle.drop() + unloaded = unloaded + nCount + end + end + end + collected = 0 + turtle.select(1) +end + +local function returnSupplies() + local x,y,z,xd,zd = xPos,depth,zPos,xDir,zDir + print( "Returning to surface..." ) + goTo( 0,0,0,0,-1 ) + + local fuelNeeded = 2*(x+y+z) + 1 + if not refuel( fuelNeeded ) then + unload( true ) + print( "Waiting for fuel" ) + while not refuel( fuelNeeded ) do + os.pullEvent( "turtle_inventory" ) + end + else + unload( true ) + end + + print( "Resuming mining..." ) + goTo( x,y,z,xd,zd ) +end + +local function collect() + local bFull = true + local nTotalItems = 0 + for n=1,16 do + local nCount = turtle.getItemCount(n) + if nCount == 0 then + bFull = false + end + nTotalItems = nTotalItems + nCount + end + + if nTotalItems > collected then + collected = nTotalItems + if math.fmod(collected + unloaded, 50) == 0 then + print( "Mined "..(collected + unloaded).." items." ) + end + end + + if bFull then + print( "No empty slots left." ) + return false + end + return true +end + +function refuel( ammount ) + local fuelLevel = turtle.getFuelLevel() + if fuelLevel == "unlimited" then + return true + end + + local needed = ammount or (xPos + zPos + depth + 2) + if turtle.getFuelLevel() < needed then + local fueled = false + for n=1,16 do + if turtle.getItemCount(n) > 0 then + turtle.select(n) + if turtle.refuel(1) then + while turtle.getItemCount(n) > 0 and turtle.getFuelLevel() < needed do + turtle.refuel(1) + end + if turtle.getFuelLevel() >= needed then + turtle.select(1) + return true + end + end + end + end + turtle.select(1) + return false + end + + return true +end + +local function tryForwards() + if not refuel() then + print( "Not enough Fuel" ) + returnSupplies() + end + + while not turtle.forward() do + if turtle.detect() then + if turtle.dig() then + if not collect() then + returnSupplies() + end + else + return false + end + elseif turtle.attack() then + if not collect() then + returnSupplies() + end + else + sleep( 0.5 ) + end + end + + xPos = xPos + xDir + zPos = zPos + zDir + return true +end + +local function tryDown() + if not refuel() then + print( "Not enough Fuel" ) + returnSupplies() + end + + while not turtle.down() do + if turtle.detectDown() then + if turtle.digDown() then + if not collect() then + returnSupplies() + end + else + return false + end + elseif turtle.attackDown() then + if not collect() then + returnSupplies() + end + else + sleep( 0.5 ) + end + end + + depth = depth + 1 + if math.fmod( depth, 10 ) == 0 then + print( "Descended "..depth.." metres." ) + end + + return true +end + +local function turnLeft() + turtle.turnLeft() + xDir, zDir = -zDir, xDir +end + +local function turnRight() + turtle.turnRight() + xDir, zDir = zDir, -xDir +end + +function goTo( x, y, z, xd, zd ) + while depth > y do + if turtle.up() then + depth = depth - 1 + elseif turtle.digUp() or turtle.attackUp() then + collect() + else + sleep( 0.5 ) + end + end + + if xPos > x then + while xDir ~= -1 do + turnLeft() + end + while xPos > x do + if turtle.forward() then + xPos = xPos - 1 + elseif turtle.dig() or turtle.attack() then + collect() + else + sleep( 0.5 ) + end + end + elseif xPos < x then + while xDir ~= 1 do + turnLeft() + end + while xPos < x do + if turtle.forward() then + xPos = xPos + 1 + elseif turtle.dig() or turtle.attack() then + collect() + else + sleep( 0.5 ) + end + end + end + + if zPos > z then + while zDir ~= -1 do + turnLeft() + end + while zPos > z do + if turtle.forward() then + zPos = zPos - 1 + elseif turtle.dig() or turtle.attack() then + collect() + else + sleep( 0.5 ) + end + end + elseif zPos < z then + while zDir ~= 1 do + turnLeft() + end + while zPos < z do + if turtle.forward() then + zPos = zPos + 1 + elseif turtle.dig() or turtle.attack() then + collect() + else + sleep( 0.5 ) + end + end + end + + while depth < y do + if turtle.down() then + depth = depth + 1 + elseif turtle.digDown() or turtle.attackDown() then + collect() + else + sleep( 0.5 ) + end + end + + while zDir ~= zd or xDir ~= xd do + turnLeft() + end +end + +if not refuel() then + print( "Out of Fuel" ) + return +end + +print( "Excavating..." ) + +local reseal = false +turtle.select(1) +if turtle.digDown() then + reseal = true +end + +local alternate = 0 +local done = false +while not done do + for n=1,size do + for m=1,size-1 do + if not tryForwards() then + done = true + break + end + end + if done then + break + end + if n 1 then + if math.fmod(size,2) == 0 then + turnRight() + else + if alternate == 0 then + turnLeft() + else + turnRight() + end + alternate = 1 - alternate + end + end + + if not tryDown() then + done = true + break + end +end + +print( "Returning to surface..." ) + +-- Return to where we started +goTo( 0,0,0,0,-1 ) +unload( false ) +goTo( 0,0,0,0,1 ) + +-- Seal the hole +if reseal then + turtle.placeDown() +end + +print( "Mined "..(collected + unloaded).." items total." ) diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/turtle/go b/src/main/resources/assets/computercraft/lua/rom/programs/turtle/go new file mode 100644 index 0000000000..651c831439 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/turtle/go @@ -0,0 +1,53 @@ +local tArgs = { ... } +if #tArgs < 1 then + print( "Usage: go " ) + return +end + +local tHandlers = { + ["fd"] = turtle.forward, + ["forward"] = turtle.forward, + ["forwards"] = turtle.forward, + ["bk"] = turtle.back, + ["back"] = turtle.back, + ["up"] = turtle.up, + ["dn"] = turtle.down, + ["down"] = turtle.down, + ["lt"] = turtle.turnLeft, + ["left"] = turtle.turnLeft, + ["rt"] = turtle.turnRight, + ["right"] = turtle.turnRight, +} + +local nArg = 1 +while nArg <= #tArgs do + local sDirection = tArgs[nArg] + local nDistance = 1 + if nArg < #tArgs then + local num = tonumber( tArgs[nArg + 1] ) + if num then + nDistance = num + nArg = nArg + 1 + end + end + nArg = nArg + 1 + + local fnHandler = tHandlers[string.lower(sDirection)] + if fnHandler then + while nDistance > 0 do + if fnHandler() then + nDistance = nDistance - 1 + elseif turtle.getFuelLevel() == 0 then + print( "Out of fuel" ) + return + else + sleep(0.5) + end + end + else + print( "No such direction: "..sDirection ) + print( "Try: forward, back, up, down" ) + return + end + +end \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/turtle/refuel b/src/main/resources/assets/computercraft/lua/rom/programs/turtle/refuel new file mode 100644 index 0000000000..fcfbd84c57 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/turtle/refuel @@ -0,0 +1,33 @@ + +local tArgs = { ... } +local nLimit = 1 +if #tArgs > 1 then + print( "Usage: refuel [number]" ) + return +elseif #tArgs > 0 then + if tArgs[1] == "all" then + nLimit = 64 * 16 + else + nLimit = tonumber( tArgs[1] ) + end +end + +if turtle.getFuelLevel() ~= "unlimited" then + for n=1,16 do + local nCount = turtle.getItemCount(n) + if nLimit > 0 and nCount > 0 and turtle.getFuelLevel() < turtle.getFuelLimit() then + local nBurn = math.min( nLimit, nCount ) + turtle.select( n ) + if turtle.refuel( nBurn ) then + local nNewCount = turtle.getItemCount(n) + nLimit = nLimit - (nCount - nNewCount) + end + end + end + print( "Fuel level is "..turtle.getFuelLevel() ) + if turtle.getFuelLevel() == turtle.getFuelLimit() then + print( "Fuel limit reached" ) + end +else + print( "Fuel level is unlimited" ) +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/turtle/tunnel b/src/main/resources/assets/computercraft/lua/rom/programs/turtle/tunnel new file mode 100644 index 0000000000..2835757b90 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/turtle/tunnel @@ -0,0 +1,184 @@ + +local tArgs = { ... } +if #tArgs ~= 1 then + print( "Usage: tunnel " ) + return +end + +-- Mine in a quarry pattern until we hit something we can't dig +local length = tonumber( tArgs[1] ) +if length < 1 then + print( "Tunnel length must be positive" ) + return +end + +local depth = 0 +local collected = 0 + +local function collect() + collected = collected + 1 + if math.fmod(collected, 25) == 0 then + print( "Mined "..collected.." items." ) + end +end + +local function tryDig() + while turtle.detect() do + if turtle.dig() then + collect() + sleep(0.5) + else + return false + end + end + return true +end + +local function tryDigUp() + while turtle.detectUp() do + if turtle.digUp() then + collect() + sleep(0.5) + else + return false + end + end + return true +end + +local function tryDigDown() + while turtle.detectDown() do + if turtle.digDown() then + collect() + sleep(0.5) + else + return false + end + end + return true +end + +local function refuel() + local fuelLevel = turtle.getFuelLevel() + if fuelLevel == "unlimited" or fuelLevel > 0 then + return + end + + local function tryRefuel() + for n=1,16 do + if turtle.getItemCount(n) > 0 then + turtle.select(n) + if turtle.refuel(1) then + turtle.select(1) + return true + end + end + end + turtle.select(1) + return false + end + + if not tryRefuel() then + print( "Add more fuel to continue." ) + while not tryRefuel() do + os.pullEvent( "turtle_inventory" ) + end + print( "Resuming Tunnel." ) + end +end + +local function tryUp() + refuel() + while not turtle.up() do + if turtle.detectUp() then + if not tryDigUp() then + return false + end + elseif turtle.attackUp() then + collect() + else + sleep( 0.5 ) + end + end + return true +end + +local function tryDown() + refuel() + while not turtle.down() do + if turtle.detectDown() then + if not tryDigDown() then + return false + end + elseif turtle.attackDown() then + collect() + else + sleep( 0.5 ) + end + end + return true +end + +local function tryForward() + refuel() + while not turtle.forward() do + if turtle.detect() then + if not tryDig() then + return false + end + elseif turtle.attack() then + collect() + else + sleep( 0.5 ) + end + end + return true +end + +print( "Tunnelling..." ) + +for n=1,length do + turtle.placeDown() + tryDigUp() + turtle.turnLeft() + tryDig() + tryUp() + tryDig() + turtle.turnRight() + turtle.turnRight() + tryDig() + tryDown() + tryDig() + turtle.turnLeft() + + if n 0 do + if turtle.forward() then + depth = depth - 1 + else + turtle.dig() + end +end +turtle.turnRight() +turtle.turnRight() +]] + +print( "Tunnel complete." ) +print( "Mined "..collected.." items total." ) diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/turtle/turn b/src/main/resources/assets/computercraft/lua/rom/programs/turtle/turn new file mode 100644 index 0000000000..55b6c32300 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/turtle/turn @@ -0,0 +1,38 @@ +local tArgs = { ... } +if #tArgs < 1 then + print( "Usage: turn " ) + return +end + +local tHandlers = { + ["lt"] = turtle.turnLeft, + ["left"] = turtle.turnLeft, + ["rt"] = turtle.turnRight, + ["right"] = turtle.turnRight, +} + +local nArg = 1 +while nArg <= #tArgs do + local sDirection = tArgs[nArg] + local nDistance = 1 + if nArg < #tArgs then + local num = tonumber( tArgs[nArg + 1] ) + if num then + nDistance = num + nArg = nArg + 1 + end + end + nArg = nArg + 1 + + local fnHandler = tHandlers[string.lower(sDirection)] + if fnHandler then + for n=1,nDistance do + fnHandler( nArg ) + end + else + print( "No such direction: "..sDirection ) + print( "Try: left, right" ) + return + end + +end \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/turtle/unequip b/src/main/resources/assets/computercraft/lua/rom/programs/turtle/unequip new file mode 100644 index 0000000000..f8c9e08df7 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/turtle/unequip @@ -0,0 +1,40 @@ + +local tArgs = { ... } +local function printUsage() + print( "Usage: unequip " ) +end + +if #tArgs ~= 1 then + printUsage() + return +end + +local function unequip( fnEquipFunction ) + for nSlot=1,16 do + local nOldCount = turtle.getItemCount( nSlot ) + if nOldCount == 0 then + turtle.select( nSlot ) + if fnEquipFunction() then + local nNewCount = turtle.getItemCount( nSlot ) + if nNewCount > 0 then + print( "Item unequipped" ) + return + else + print( "Nothing to unequip" ) + return + end + end + end + end + print( "No space to unequip item" ) +end + +local sSide = tArgs[1] +if sSide == "left" then + unequip( turtle.equipLeft ) +elseif sSide == "right" then + unequip( turtle.equipRight ) +else + printUsage() + return +end diff --git a/src/main/resources/assets/computercraft/lua/rom/programs/type b/src/main/resources/assets/computercraft/lua/rom/programs/type new file mode 100644 index 0000000000..b4f33a8440 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/programs/type @@ -0,0 +1,18 @@ + +local tArgs = { ... } +if #tArgs < 1 then + print( "Usage: type " ) + return +end + +local sPath = shell.resolve( tArgs[1] ) +if fs.exists( sPath ) then + if fs.isDir( sPath ) then + print( "directory" ) + else + print( "file" ) + end +else + print( "No such path" ) +end + diff --git a/src/main/resources/assets/computercraft/lua/rom/startup b/src/main/resources/assets/computercraft/lua/rom/startup new file mode 100644 index 0000000000..b3b02f67a0 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/rom/startup @@ -0,0 +1,230 @@ + +-- Setup paths +local sPath = ".:/rom/programs" +if term.isColor() then + sPath = sPath..":/rom/programs/advanced" +end +if turtle then + sPath = sPath..":/rom/programs/turtle" +else + sPath = sPath..":/rom/programs/rednet:/rom/programs/fun" + if term.isColor() then + sPath = sPath..":/rom/programs/fun/advanced" + end +end +if pocket then + sPath = sPath..":/rom/programs/pocket" +end +if commands then + sPath = sPath..":/rom/programs/command" +end +if http then + sPath = sPath..":/rom/programs/http" +end +shell.setPath( sPath ) +help.setPath( "/rom/help" ) + +-- Setup aliases +shell.setAlias( "ls", "list" ) +shell.setAlias( "dir", "list" ) +shell.setAlias( "cp", "copy" ) +shell.setAlias( "mv", "move" ) +shell.setAlias( "rm", "delete" ) +shell.setAlias( "clr", "clear" ) +shell.setAlias( "rs", "redstone" ) +shell.setAlias( "sh", "shell" ) +if term.isColor() then + shell.setAlias( "background", "bg" ) + shell.setAlias( "foreground", "fg" ) +end + +-- Setup completion functions +local function completeMultipleChoice( sText, tOptions, bAddSpaces ) + local tResults = {} + for n=1,#tOptions do + local sOption = tOptions[n] + if #sOption + (bAddSpaces and 1 or 0) > #sText and string.sub( sOption, 1, #sText ) == sText then + local sResult = string.sub( sOption, #sText + 1 ) + if bAddSpaces then + table.insert( tResults, sResult .. " " ) + else + table.insert( tResults, sResult ) + end + end + end + return tResults +end +local function completePeripheralName( sText, bAddSpaces ) + return completeMultipleChoice( sText, peripheral.getNames(), bAddSpaces ) +end +local tRedstoneSides = redstone.getSides() +local function completeSide( sText, bAddSpaces ) + return completeMultipleChoice( sText, tRedstoneSides, bAddSpaces ) +end +local function completeFile( shell, nIndex, sText, tPreviousText ) + if nIndex == 1 then + return fs.complete( sText, shell.dir(), true, false ) + end +end +local function completeDir( shell, nIndex, sText, tPreviousText ) + if nIndex == 1 then + return fs.complete( sText, shell.dir(), false, true ) + end +end +local function completeEither( shell, nIndex, sText, tPreviousText ) + if nIndex == 1 then + return fs.complete( sText, shell.dir(), true, true ) + end +end +local function completeEitherEither( shell, nIndex, sText, tPreviousText ) + if nIndex == 1 then + local tResults = fs.complete( sText, shell.dir(), true, true ) + for n=1,#tResults do + local sResult = tResults[n] + if string.sub( sResult, #sResult, #sResult ) ~= "/" then + tResults[n] = sResult .. " " + end + end + return tResults + elseif nIndex == 2 then + return fs.complete( sText, shell.dir(), true, true ) + end +end +local function completeProgram( shell, nIndex, sText, tPreviousText ) + if nIndex == 1 then + return shell.completeProgram( sText ) + end +end +local function completeHelp( shell, nIndex, sText, tPreviousText ) + if nIndex == 1 then + return help.completeTopic( sText ) + end +end +local function completeAlias( shell, nIndex, sText, tPreviousText ) + if nIndex == 2 then + return shell.completeProgram( sText ) + end +end +local function completePeripheral( shell, nIndex, sText, tPreviousText ) + if nIndex == 1 then + return completePeripheralName( sText ) + end +end +local tGPSOptions = { "host", "host ", "locate" } +local function completeGPS( shell, nIndex, sText, tPreviousText ) + if nIndex == 1 then + return completeMultipleChoice( sText, tGPSOptions ) + end +end +local tLabelOptions = { "get", "get ", "set ", "clear", "clear " } +local function completeLabel( shell, nIndex, sText, tPreviousText ) + if nIndex == 1 then + return completeMultipleChoice( sText, tLabelOptions ) + elseif nIndex == 2 then + return completePeripheralName( sText ) + end +end +local function completeMonitor( shell, nIndex, sText, tPreviousText ) + if nIndex == 1 then + return completePeripheralName( sText, true ) + elseif nIndex == 2 then + return shell.completeProgram( sText ) + end +end +local tRedstoneOptions = { "probe", "set ", "pulse " } +local function completeRedstone( shell, nIndex, sText, tPreviousText ) + if nIndex == 1 then + return completeMultipleChoice( sText, tRedstoneOptions ) + elseif nIndex == 2 then + return completeSide( sText ) + end +end +local tDJOptions = { "play", "play ", "stop " } +local function completeDJ( shell, nIndex, sText, tPreviousText ) + if nIndex == 1 then + return completeMultipleChoice( sText, tDJOptions ) + elseif nIndex == 2 then + return completePeripheralName( sText ) + end +end +local tPastebinOptions = { "put ", "get ", "run " } +local function completePastebin( shell, nIndex, sText, tPreviousText ) + if nIndex == 1 then + return completeMultipleChoice( sText, tPastebinOptions ) + elseif nIndex == 2 then + if tPreviousText[2] == "put" then + return fs.complete( sText, shell.dir(), true, false ) + end + end +end +local tChatOptions = { "host ", "join " } +local function completeChat( shell, nIndex, sText, tPreviousText ) + if nIndex == 1 then + return completeMultipleChoice( sText, tChatOptions ) + end +end +local function completeSet( shell, nIndex, sText, tPreviousText ) + if nIndex == 1 then + return completeMultipleChoice( sText, settings.getNames(), true ) + end +end +shell.setCompletionFunction( "rom/programs/alias", completeAlias ) +shell.setCompletionFunction( "rom/programs/cd", completeDir ) +shell.setCompletionFunction( "rom/programs/copy", completeEitherEither ) +shell.setCompletionFunction( "rom/programs/delete", completeEither ) +shell.setCompletionFunction( "rom/programs/drive", completeDir ) +shell.setCompletionFunction( "rom/programs/edit", completeFile ) +shell.setCompletionFunction( "rom/programs/eject", completePeripheral ) +shell.setCompletionFunction( "rom/programs/gps", completeGPS ) +shell.setCompletionFunction( "rom/programs/help", completeHelp ) +shell.setCompletionFunction( "rom/programs/id", completePeripheral ) +shell.setCompletionFunction( "rom/programs/label", completeLabel ) +shell.setCompletionFunction( "rom/programs/list", completeDir ) +shell.setCompletionFunction( "rom/programs/mkdir", completeFile ) +shell.setCompletionFunction( "rom/programs/monitor", completeMonitor ) +shell.setCompletionFunction( "rom/programs/move", completeEitherEither ) +shell.setCompletionFunction( "rom/programs/redstone", completeRedstone ) +shell.setCompletionFunction( "rom/programs/rename", completeEitherEither ) +shell.setCompletionFunction( "rom/programs/shell", completeProgram ) +shell.setCompletionFunction( "rom/programs/type", completeEither ) +shell.setCompletionFunction( "rom/programs/set", completeSet ) +shell.setCompletionFunction( "rom/programs/advanced/bg", completeProgram ) +shell.setCompletionFunction( "rom/programs/advanced/fg", completeProgram ) +shell.setCompletionFunction( "rom/programs/fun/dj", completeDJ ) +shell.setCompletionFunction( "rom/programs/fun/advanced/paint", completeFile ) +shell.setCompletionFunction( "rom/programs/http/pastebin", completePastebin ) +shell.setCompletionFunction( "rom/programs/rednet/chat", completeChat ) + +-- Run autorun files +if fs.exists( "/rom/autorun" ) and fs.isDir( "/rom/autorun" ) then + local tFiles = fs.list( "/rom/autorun" ) + table.sort( tFiles ) + for n, sFile in ipairs( tFiles ) do + if string.sub( sFile, 1, 1 ) ~= "." then + local sPath = "/rom/autorun/"..sFile + if not fs.isDir( sPath ) then + shell.run( sPath ) + end + end + end +end + +-- Run the user created startup, either from disk drives or the root +local sUserStartup = nil +if settings.get( "shell.allow_startup" ) then + sUserStartup = shell.resolveProgram( "/startup" ) +end +if settings.get( "shell.allow_disk_startup" ) then + for n,sName in pairs( peripheral.getNames() ) do + if disk.isPresent( sName ) and disk.hasData( sName ) then + local sDiskStartup = shell.resolveProgram( "/" .. disk.getMountPath( sName ) .. "/startup" ) + if sDiskStartup then + sUserStartup = sDiskStartup + break + end + end + end +end +if sUserStartup then + shell.run( sUserStartup ) +end diff --git a/src/main/resources/assets/computercraft/lua/treasure/GopherAtl/battleship/battleship b/src/main/resources/assets/computercraft/lua/treasure/GopherAtl/battleship/battleship new file mode 100755 index 0000000000..a3fa2b6e91 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/GopherAtl/battleship/battleship @@ -0,0 +1,875 @@ +--[[ +battleship, + +by GopherAtl, 2013 + +Do whatever you want, just don't judge me by +what a mess this code is. +--]] +local args={...} +local action=args[1] +local opponentID=nil +local openedSide=nil +local opponent=nil +local myName="" +local opponentReady=false +local myTurn +local targetX,targetY +local shipsLeft=5 +local oppShipsLeft=5 + +local originalTerm = term.current() + +--bounding box of the target grid +local targetGridBounds={ + minX=16, maxX=25, + minY=4, maxY=13 + } + + +local function doColor(text,background) + term.setTextColor(text) + term.setBackgroundColor(background) +end + +local function doColor_mono(text,background) + if text==colors.blue or text==colors.red or text==colors.black or text==colors.lime or background==colors.lightGray then + term.setTextColor(colors.black) + term.setBackgroundColor(colors.white) + else + term.setTextColor(colors.white) + term.setBackgroundColor(colors.black) + end +end + +local function doScreenColor() + if term.isColor() then + doColor(colors.white,colors.lightGray) + else + doColor(colors.black,colors.white) + end +end + +local function toGridRef(x,y) + return string.sub("ABCDEFGHIJ",x,x)..string.sub("1234567890",y,y) +end + + +if not term.isColor() then + doColor=doColor_mono +end + +local function quit() + if openedSide then + rednet.close(openedSide) + end + term.redirect( originalTerm ) + term.setCursorPos(term.getSize()) + print() + error() +end + +local foundModem=false +--find modem +for k,v in pairs(redstone.getSides()) do + if peripheral.getType(v)=="modem" then + foundModem=true + if not rednet.isOpen(v) then + rednet.open(v) + openedSide=v + end + break + end +end + +if not foundModem then + print("You must have a modem to play!") + return +end + +if action==nil or (action~="join" and action~="host") then + print("Invalid parameters. Usage:\n> battleship host\nHosts a game, waits for another computer to join\n> battleship join\nLooks for another game to join") + quit() +end + +--get player name +while true do + doColor(colors.cyan,colors.black) + write("player name: ") + doColor(colors.gray,colors.black) + myName=read() + if myName=="" then + doColor(colors.red,colors.black) + print("You have to give a name!") + elseif #myName>11 then + doColor(colors.red,colors.black) + print("Max name is 11 characters!") + else + break + end +end + +if action=="join" then + print("Attempting to join a game...\n(press q to cancel)") + while true do + local retryTimer=os.startTimer(1); + rednet.broadcast("bs join "..myName); + + while true do + local event,p1,p2,p3=os.pullEvent(); + if event=="rednet_message" then + opponent=string.match(p2,"bs accept %s*(.+)%s*") + if opponent then + opponentID=p1 + break + end + elseif event=="timer" and p1==retryTimer then + break + elseif event=="char" and (p1=="q" or p1=="Q") then + print("Couldn't find an opponent; quitting") + quit() + end + end + local joined=false + + if opponentID then + print("Joining game!") + rednet.send(opponentID,"bs start") + break + end + end +elseif action=="host" then + print("Waiting for challenger...\n(Press q to cancel)") + while true do + while true do + local event,p1,p2=os.pullEvent() + if event=="rednet_message" then + opponent=string.match(p2,"bs join %s*(.+)%s*") if opponent then + print("found player, inviting..") + opponentID=p1 + break + end + elseif event=="char" and (p1=="q" or p1=="Q") then + print("Couldn't find opponent, quitting") + quit() + end + end + + if opponentID then + rednet.send(opponentID,"bs accept "..myName) + local timeout=os.startTimer(1) + while true do + local event,p1,p2=os.pullEvent() + if event=="rednet_message" and p2=="bs start" then + print("player joined!") + break + elseif event=="timer" and p1==timeout then + print("player joined another game. Waiting for another...") + opponentID=nil + break + end + end + + if opponentID then + break + end + end + end +end + +local ships={ + {pos=nil,dir="h",size=5,name="carrier",hits=0}, + {pos=nil,dir="h",size=4,name="battleship",hits=0}, + {pos=nil,dir="h",size=3,name="cruiser",hits=0}, + {pos=nil,dir="h",size=3,name="submarine",hits=0}, + {pos=nil,dir="h",size=2,name="destroyer",hits=0}, +} + +local myShotTable={ {1,1,true},{5,5,false} } +local oppShotTable={ } + +local myGrid,oppGrid={title=myName},{title=opponent} + +--setup grids +for i=1,10 do + myGrid[i]={} + oppGrid[i]={} + for j=1,10 do + myGrid[i][j]={hit=false,ship=false} + oppGrid[i][j]={hit=false,ship=false} + end +end + +local function drawShipsToGrid(ships,grid) + for i=1,#ships do + local x,y=table.unpack(ships[i].pos) + local stepX=ships[i].dir=="h" and 1 or 0 + local stepY=stepX==1 and 0 or 1 + for j=1,ships[i].size do + grid[x][y].ship=i + x,y=x+stepX,y+stepY + end + end +end + +local function drawShotToGrid(shot,grid) + grid[shot[1]][shot[2]].shot=true + grid[shot[1]][shot[2]].hit=shot[3] +end + +local function makeShot(x,y,grid) + local tile=grid[x][y] + if tile.shot==true then + return nil --already shot here! + end + + local shot={x,y,tile.ship} + drawShotToGrid(shot,grid) + if tile.ship then + ships[tile.ship].hits=ships[tile.ship].hits+1 + if ships[tile.ship].hits==ships[tile.ship].size then + os.queueEvent("shipsunk",tile.ship) + end + end + return shot +end + + +local function drawTile(scrX,scrY,tile) + term.setCursorPos(scrX,scrY) + + if tile.ship then + if tile.shot then + doColor(colors.red,colors.gray) + term.write("@") + else + doColor(colors.white,colors.gray) + term.write("O") + end + else + if tile.hit then + doColor(colors.red,colors.gray) + term.write("x") + elseif tile.shot then + doColor(colors.white,colors.lightBlue) + term.write(".") + else + doColor(colors.white,colors.lightBlue) + term.write(" ") + end + end +end + +local function drawGrid(scrX,scrY,grid) + doColor(colors.white,colors.black) + term.setCursorPos(scrX,scrY+1) + term.write(" ") + doColor(colors.white,colors.gray) + term.setCursorPos(scrX,scrY) + local pad=11-#grid.title + term.write(string.rep(" ",math.ceil(pad/2))..grid.title..string.rep(" ",math.floor(pad/2))) + + for gx=1,10 do + term.setTextColor(colors.white) + term.setBackgroundColor(colors.black) + term.setCursorPos(scrX+gx,scrY+1) + term.write(gx==10 and "0" or string.char(string.byte("0")+gx)) + + term.setCursorPos(scrX,scrY+gx+1) + term.write(string.char(string.byte("A")+gx-1)) + for gy=1,10 do + drawTile(scrX+gx,scrY+gy+1,grid[gx][gy]) + end + end + doColor(colors.white,colors.black) +end + +function moveTargetIndicator(newX,newY) + --if x has changed... + if targetX and targetY then + drawTile(targetX+targetGridBounds.minX-1,targetY+targetGridBounds.minY-1,oppGrid[targetX][targetY]) + end + doColor(colors.yellow,colors.lightGray) + if newX~=targetX then + --space over old + if targetX then + term.setCursorPos(targetGridBounds.minX+targetX-1,targetGridBounds.maxY+1) + term.write(" ") + term.setCursorPos(targetGridBounds.minX+targetX-1,targetGridBounds.minY-3) + term.write(" ") + end + --draw new + term.setCursorPos(targetGridBounds.minX+newX-1,targetGridBounds.maxY+1) + term.write("^") + term.setCursorPos(targetGridBounds.minX+newX-1,targetGridBounds.minY-3) + term.write("v") + + targetX=newX + end + if newY~=targetY then + --space over old + if targetY then + term.setCursorPos(targetGridBounds.maxX+1,targetGridBounds.minY+targetY-1) + term.write(" ") + term.setCursorPos(targetGridBounds.minX-2,targetGridBounds.minY+targetY-1) + term.write(" ") + end + --draw new + term.setCursorPos(targetGridBounds.maxX+1,targetGridBounds.minY+newY-1) + term.write("<") + term.setCursorPos(targetGridBounds.minX-2,targetGridBounds.minY+newY-1) + term.write(">") + + targetY=newY + end + term.setCursorPos(15,15) + term.write("Target : "..toGridRef(targetX,targetY)) + --if the target tile is a valid target, draw a "+" + if not oppGrid[targetX][targetY].shot then + term.setCursorPos(targetX+targetGridBounds.minX-1,targetY+targetGridBounds.minY-1) + doColor(colors.yellow,colors.lightBlue) + term.write("+") + end +end + +local log={} + +local termWidth,termHeight=term.getSize() + +local logHeight=termHeight-3 +local logWidth=termWidth-28 + +for i=1,logHeight do + log[i]="" +end + +local function printLog() + doColor(colors.white,colors.black) + for i=1,logHeight do + term.setCursorPos(28,1+i) + local name,line=string.match(log[i],"(<[^>]+> )(.*)") + if name then + doColor(colors.lightBlue,colors.black) + write(name) + doColor(colors.white,colors.black) + write(line..string.rep(" ",logWidth-#log[i])) + else + write(log[i]..string.rep(" ",logWidth-#log[i])) + end + end +end + + + +--shipX/Y are the position of ship on grid; gridX/Y are the offset of the top-left of grid +local function drawShip(size,align,x,y,char) + local stepX=align=="h" and 1 or 0 + local stepY=stepX==1 and 0 or 1 + for j=1,size do + term.setCursorPos(x,y) + term.write(char) + x,y=x+stepX,y+stepY + end +end + +local function setStatusLine(lineNum,text) + doScreenColor() + local pad=math.floor((termWidth-#text)/2) + term.setCursorPos(1,16+lineNum) + term.write((" "):rep(pad)..text..(" "):rep(termWidth-#text-pad)) +end + + +doScreenColor() +term.clear() + +drawGrid(2,2,myGrid) + +setStatusLine(1,"Started game with "..opponent.." at computer #"..(opponentID or "nil")) + +local function getShipBounds(ship) + return { + minX=ship.pos[1], + minY=ship.pos[2], + maxX=ship.pos[1]+(ship.dir=="h" and ship.size-1 or 0), + maxY=ship.pos[2]+(ship.dir=="v" and ship.size-1 or 0) + } +end + +local function getPointBounds(x,y) + return { + minX=x, + minY=y, + maxX=x, + maxY=y, + } +end + +local function boundsIntersect(boundsA,boundsB) + return not ( + boundsA.minX>boundsB.maxX or + boundsA.maxXboundsB.maxY or + boundsA.maxY="a" and p1<="j" then + --row selected + moveTargetIndicator(targetX,string.byte(p1)-string.byte("a")+1) + elseif p1>="0" and p1<="9" then + local t=string.byte(p1)-string.byte("0") + if t==0 then t=10 end + moveTargetIndicator(t,targetY) + end + elseif e=="key" then + if p1==keys.enter or p1==keys.space and targetX and targetY then + local shot=makeShot(targetX,targetY,oppGrid) + if shot then + rednet.send(opponentID,"bs shot "..targetX.." "..targetY) + break + end + elseif p1==keys.up then + moveTargetIndicator(targetX,math.max(targetY-1,1)) + elseif p1==keys.down then + moveTargetIndicator(targetX,math.min(targetY+1,10)) + elseif p1==keys.left then + moveTargetIndicator(math.max(targetX-1,1),targetY) + elseif p1==keys.right then + moveTargetIndicator(math.min(targetX+1,10),targetY) + end + end + end + --shot sent, wait for my turn to resolve (top coroutine will switch turns and draw the hit to the grid) + setStatusLine(2,"Waiting for opponent...") + while myTurn do + os.pullEvent() + end + end +end + +local gameRoutine=coroutine.create(runGame) +--if advanced terminal, default focus to chat, can play with mouse +local inChat=term.isColor() +local savedCursorPos={7,19} + +--redirect just to block scroll +local redir={} +for k,v in pairs(originalTerm) do + if k~="scroll" then + redir[k]=v + else + redir[k]=function() end + end +end +originalTerm = term.redirect(redir) + +--run the game routine once +coroutine.resume(gameRoutine) +--hide cursor +term.setCursorBlink(false) + +while true do + local e,p1,p2,p3,p4,p5=os.pullEventRaw() + if e=="terminate" then + quit() + elseif e=="shipsunk" then + setStatusLine(1,opponent.." sank your "..ships[p1].name.."!") + rednet.send(opponentID,"bs sink") + shipsLeft=shipsLeft-1 + if shipsLeft==1 then + setStatusLine(3,"You only have 1 ship left!") + elseif shipsLeft>1 then + setStatusLine(3,"You have "..shipsLeft.." ships left!") + else + rednet.send(opponentID,"bs win") + setStatusLine(3,"You lost the game!") + break + end + elseif e=="rednet_message" then + local cmd,args=string.match(p2,"^bs (%S+)%s?(.*)") + if cmd=="ready" then + opponentReady=true + os.queueEvent("kickcoroutine") + elseif cmd=="cointoss" then + myTurn=args=="true" + if myTurn then + setStatusLine(2,"Your turn, take your shot!") + else + setStatusLine(2,"Opponent's turn, waiting...") + end + os.queueEvent("kickcoroutine") + elseif cmd=="shot" then + if myTurn then + setStatusLine(3,"What the?! Got a shot but not their turn! Ignoring") + else + local tx, ty=string.match(args,"(%d+) (%d+)") + tx,ty=tonumber(tx),tonumber(ty) + local tile=myGrid[tx][ty] + local shot=makeShot(tx,ty,myGrid) + rednet.send(opponentID,"bs result "..(shot[3] and "hit" or "miss")) + drawTile(2+tx,3+ty,tile) + myTurn=true + os.queueEvent("kickcoroutine") + displayGameHelp() + setStatusLine(1,opponent.." fired at "..toGridRef(tx,ty).." and "..(shot[3] and "hit" or "missed")) + setStatusLine(2,"Your turn, take your shot!") + end + elseif cmd=="sink" then + setStatusLine(1,"You sank one of "..opponent.."'s ships!") + oppShipsLeft=oppShipsLeft-1 + if oppShipsLeft==0 then + setStatusLine(2,opponent.." has no ships left!") + elseif oppShipsLeft==1 then + setStatusLine(2,"Sink 1 more to win!") + else + setStatusLine(2,"They have "..oppShipsLeft.." ships left.") + end + elseif cmd=="result" then + if not myTurn then + setStatusLine(3,"What the?! Got a shot result but not my turn! Ignoring") + else + local tile=oppGrid[targetX][targetY] + tile.hit=args=="hit" + drawTile(targetX+15,targetY+3,tile) + myTurn=false + doColor(tile.hit and colors.red or colors.white,colors.lightGray) + term.setCursorPos(17,16) + term.write(tile.hit and "HIT!" or "MISS") + setStatusLine(2,"Waiting for opponent...") + os.queueEvent("kickcoroutine") + end + + elseif cmd=="win" then + --we won! + setStatusLine(3,"You won the game! Congratulations!") + break + end + --everything else goes to gameRoutine + else + --all other events go to this routine + local succ,err=coroutine.resume(gameRoutine,e,p1,p2,p3,p4,p5) + if not succ then + print("game coroutine crashed with the following error: "..err) + quit() + end + + if coroutine.status(gameRoutine)=="dead" then + --game over + break + end + end + +end + +term.setCursorPos(1,19) +term.clearLine() +term.write(" Press any key to continue...") +os.pullEvent("key") +--if a char event was queued following the key event, this will eat it +os.sleep(0) + +term.setTextColor(colors.white) +term.setBackgroundColor(colors.black) +term.clear() +quit() +-- \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/treasure/GravityScore/LuaIDE/luaide b/src/main/resources/assets/computercraft/lua/treasure/GravityScore/LuaIDE/luaide new file mode 100644 index 0000000000..b8de7b1473 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/GravityScore/LuaIDE/luaide @@ -0,0 +1,2212 @@ + +-- +-- Lua IDE +-- Made by GravityScore +-- + + +-- -------- Variables + +-- Version +local version = "1.0" +local args = {...} + +-- Editing +local w, h = term.getSize() +local tabWidth = 2 + +local autosaveInterval = 20 +local allowEditorEvent = true +local keyboardShortcutTimeout = 0.4 + +-- Clipboard +local clipboard = nil + +-- Theme +local theme = {} + +-- Language +local languages = {} +local curLanguage = {} + +-- Events +local event_distract = "luaide_distractionEvent" + +-- Locations +--local updateURL = "https://raw.github.com/GravityScore/LuaIDE/master/luaide.lua" +local ideLocation = "/" .. shell.getRunningProgram() +local themeLocation = "/.LuaIDE-Theme" + +local function isAdvanced() return term.isColor and term.isColor() end + + +-- -------- Utilities + +local function modRead(properties) + local w, h = term.getSize() + local defaults = {replaceChar = nil, history = nil, visibleLength = nil, textLength = nil, + liveUpdates = nil, exitOnKey = nil} + if not properties then properties = {} end + for k, v in pairs(defaults) do if not properties[k] then properties[k] = v end end + if properties.replaceChar then properties.replaceChar = properties.replaceChar:sub(1, 1) end + if not properties.visibleLength then properties.visibleLength = w end + + local sx, sy = term.getCursorPos() + local line = "" + local pos = 0 + local historyPos = nil + + local function redraw(repl) + local scroll = 0 + if properties.visibleLength and sx + pos > properties.visibleLength + 1 then + scroll = (sx + pos) - (properties.visibleLength + 1) + end + + term.setCursorPos(sx, sy) + local a = repl or properties.replaceChar + if a then term.write(string.rep(a, line:len() - scroll)) + else term.write(line:sub(scroll + 1, -1)) end + term.setCursorPos(sx + pos - scroll, sy) + end + + local function sendLiveUpdates(event, ...) + if type(properties.liveUpdates) == "function" then + local ox, oy = term.getCursorPos() + local a, data = properties.liveUpdates(line, event, ...) + if a == true and data == nil then + term.setCursorBlink(false) + return line + elseif a == true and data ~= nil then + term.setCursorBlink(false) + return data + end + term.setCursorPos(ox, oy) + end + end + + term.setCursorBlink(true) + while true do + local e, but, x, y, p4, p5 = os.pullEvent() + + if e == "char" then + local s = false + if properties.textLength and line:len() < properties.textLength then s = true + elseif not properties.textLength then s = true end + + local canType = true + if not properties.grantPrint and properties.refusePrint then + local canTypeKeys = {} + if type(properties.refusePrint) == "table" then + for _, v in pairs(properties.refusePrint) do + table.insert(canTypeKeys, tostring(v):sub(1, 1)) + end + elseif type(properties.refusePrint) == "string" then + for char in properties.refusePrint:gmatch(".") do + table.insert(canTypeKeys, char) + end + end + for _, v in pairs(canTypeKeys) do if but == v then canType = false end end + elseif properties.grantPrint then + canType = false + local canTypeKeys = {} + if type(properties.grantPrint) == "table" then + for _, v in pairs(properties.grantPrint) do + table.insert(canTypeKeys, tostring(v):sub(1, 1)) + end + elseif type(properties.grantPrint) == "string" then + for char in properties.grantPrint:gmatch(".") do + table.insert(canTypeKeys, char) + end + end + for _, v in pairs(canTypeKeys) do if but == v then canType = true end end + end + + if s and canType then + line = line:sub(1, pos) .. but .. line:sub(pos + 1, -1) + pos = pos + 1 + redraw() + end + elseif e == "key" then + if but == keys.enter then break + elseif but == keys.left then if pos > 0 then pos = pos - 1 redraw() end + elseif but == keys.right then if pos < line:len() then pos = pos + 1 redraw() end + elseif (but == keys.up or but == keys.down) and properties.history then + redraw(" ") + if but == keys.up then + if historyPos == nil and #properties.history > 0 then + historyPos = #properties.history + elseif historyPos > 1 then + historyPos = historyPos - 1 + end + elseif but == keys.down then + if historyPos == #properties.history then historyPos = nil + elseif historyPos ~= nil then historyPos = historyPos + 1 end + end + + if properties.history and historyPos then + line = properties.history[historyPos] + pos = line:len() + else + line = "" + pos = 0 + end + + redraw() + local a = sendLiveUpdates("history") + if a then return a end + elseif but == keys.backspace and pos > 0 then + redraw(" ") + line = line:sub(1, pos - 1) .. line:sub(pos + 1, -1) + pos = pos - 1 + redraw() + local a = sendLiveUpdates("delete") + if a then return a end + elseif but == keys.home then + pos = 0 + redraw() + elseif but == keys.delete and pos < line:len() then + redraw(" ") + line = line:sub(1, pos) .. line:sub(pos + 2, -1) + redraw() + local a = sendLiveUpdates("delete") + if a then return a end + elseif but == keys["end"] then + pos = line:len() + redraw() + elseif properties.exitOnKey then + if but == properties.exitOnKey or (properties.exitOnKey == "control" and + (but == 29 or but == 157)) then + term.setCursorBlink(false) + return nil + end + end + end + local a = sendLiveUpdates(e, but, x, y, p4, p5) + if a then return a end + end + + term.setCursorBlink(false) + if line ~= nil then line = line:gsub("^%s*(.-)%s*$", "%1") end + return line +end + + +-- -------- Themes + +local defaultTheme = { + background = "gray", + backgroundHighlight = "lightGray", + prompt = "cyan", + promptHighlight = "lightBlue", + err = "red", + errHighlight = "pink", + + editorBackground = "gray", + editorLineHightlight = "lightBlue", + editorLineNumbers = "gray", + editorLineNumbersHighlight = "lightGray", + editorError = "pink", + editorErrorHighlight = "red", + + textColor = "white", + conditional = "yellow", + constant = "orange", + ["function"] = "magenta", + string = "red", + comment = "lime" +} + +local normalTheme = { + background = "black", + backgroundHighlight = "black", + prompt = "black", + promptHighlight = "black", + err = "black", + errHighlight = "black", + + editorBackground = "black", + editorLineHightlight = "black", + editorLineNumbers = "black", + editorLineNumbersHighlight = "white", + editorError = "black", + editorErrorHighlight = "black", + + textColor = "white", + conditional = "white", + constant = "white", + ["function"] = "white", + string = "white", + comment = "white" +} + +--[[ +local availableThemes = { + {"Water (Default)", "https://raw.github.com/GravityScore/LuaIDE/master/themes/default.txt"}, + {"Fire", "https://raw.github.com/GravityScore/LuaIDE/master/themes/fire.txt"}, + {"Sublime Text 2", "https://raw.github.com/GravityScore/LuaIDE/master/themes/st2.txt"}, + {"Midnight", "https://raw.github.com/GravityScore/LuaIDE/master/themes/midnight.txt"}, + {"TheOriginalBIT", "https://raw.github.com/GravityScore/LuaIDE/master/themes/bit.txt"}, + {"Superaxander", "https://raw.github.com/GravityScore/LuaIDE/master/themes/superaxander.txt"}, + {"Forest", "https://raw.github.com/GravityScore/LuaIDE/master/themes/forest.txt"}, + {"Night", "https://raw.github.com/GravityScore/LuaIDE/master/themes/night.txt"}, + {"Original", "https://raw.github.com/GravityScore/LuaIDE/master/themes/original.txt"}, +} +]]-- + +local function loadTheme(path) + local f = io.open(path) + local l = f:read("*l") + local config = {} + while l ~= nil do + local k, v = string.match(l, "^(%a+)=(%a+)") + if k and v then config[k] = v end + l = f:read("*l") + end + f:close() + return config +end + +-- Load Theme +if isAdvanced() then theme = defaultTheme +else theme = normalTheme end + + +-- -------- Drawing + +local function centerPrint(text, ny) + if type(text) == "table" then for _, v in pairs(text) do centerPrint(v) end + else + local x, y = term.getCursorPos() + local w, h = term.getSize() + term.setCursorPos(w/2 - text:len()/2 + (#text % 2 == 0 and 1 or 0), ny or y) + print(text) + end +end + +local function title(t) + term.setTextColor(colors[theme.textColor]) + term.setBackgroundColor(colors[theme.background]) + term.clear() + + term.setBackgroundColor(colors[theme.backgroundHighlight]) + for i = 2, 4 do term.setCursorPos(1, i) term.clearLine() end + term.setCursorPos(3, 3) + term.write(t) +end + +local function centerRead(wid, begt) + local function liveUpdate(line, e, but, x, y, p4, p5) + if isAdvanced() and e == "mouse_click" and x >= w/2 - wid/2 and x <= w/2 - wid/2 + 10 + and y >= 13 and y <= 15 then + return true, "" + end + end + + if not begt then begt = "" end + term.setTextColor(colors[theme.textColor]) + term.setBackgroundColor(colors[theme.promptHighlight]) + for i = 8, 10 do + term.setCursorPos(w/2 - wid/2, i) + term.write(string.rep(" ", wid)) + end + + if isAdvanced() then + term.setBackgroundColor(colors[theme.errHighlight]) + for i = 13, 15 do + term.setCursorPos(w/2 - wid/2 + 1, i) + term.write(string.rep(" ", 10)) + end + term.setCursorPos(w/2 - wid/2 + 2, 14) + term.write("> Cancel") + end + + term.setBackgroundColor(colors[theme.promptHighlight]) + term.setCursorPos(w/2 - wid/2 + 1, 9) + term.write("> " .. begt) + return modRead({visibleLength = w/2 + wid/2, liveUpdates = liveUpdate}) +end + + +-- -------- Prompt + +local function prompt(list, dir, isGrid) + local function draw(sel) + for i, v in ipairs(list) do + if i == sel then term.setBackgroundColor(v.highlight or colors[theme.promptHighlight]) + else term.setBackgroundColor(v.bg or colors[theme.prompt]) end + term.setTextColor(v.tc or colors[theme.textColor]) + for i = -1, 1 do + term.setCursorPos(v[2], v[3] + i) + term.write(string.rep(" ", v[1]:len() + 4)) + end + + term.setCursorPos(v[2], v[3]) + if i == sel then + term.setBackgroundColor(v.highlight or colors[theme.promptHighlight]) + term.write(" > ") + else term.write(" - ") end + term.write(v[1] .. " ") + end + end + + local key1 = dir == "horizontal" and 203 or 200 + local key2 = dir == "horizontal" and 205 or 208 + local sel = 1 + draw(sel) + + while true do + local e, but, x, y = os.pullEvent() + if e == "key" and but == 28 then + return list[sel][1] + elseif e == "key" and but == key1 and sel > 1 then + sel = sel - 1 + draw(sel) + elseif e == "key" and but == key2 and ((err == true and sel < #list - 1) or (sel < #list)) then + sel = sel + 1 + draw(sel) + elseif isGrid and e == "key" and but == 203 and sel > 2 and #list == 4 then + sel = sel - 2 + draw(sel) + elseif isGrid and e == "key" and but == 205 and sel < 3 and #list == 4 then + sel = sel + 2 + draw(sel) + elseif e == "mouse_click" then + for i, v in ipairs(list) do + if x >= v[2] - 1 and x <= v[2] + v[1]:len() + 3 and y >= v[3] - 1 and y <= v[3] + 1 then + return list[i][1] + end + end + end + end +end + +local function scrollingPrompt(list) + local function draw(items, sel, loc) + for i, v in ipairs(items) do + local bg = colors[theme.prompt] + local bghigh = colors[theme.promptHighlight] + if v:find("Back") or v:find("Return") then + bg = colors[theme.err] + bghigh = colors[theme.errHighlight] + end + + if i == sel then term.setBackgroundColor(bghigh) + else term.setBackgroundColor(bg) end + term.setTextColor(colors[theme.textColor]) + for x = -1, 1 do + term.setCursorPos(3, (i * 4) + x + 4) + term.write(string.rep(" ", w - 13)) + end + + term.setCursorPos(3, i * 4 + 4) + if i == sel then + term.setBackgroundColor(bghigh) + term.write(" > ") + else term.write(" - ") end + term.write(v .. " ") + end + end + + local function updateDisplayList(items, loc, len) + local ret = {} + for i = 1, len do + local item = items[i + loc - 1] + if item then table.insert(ret, item) end + end + return ret + end + + -- Variables + local sel = 1 + local loc = 1 + local len = 3 + local disList = updateDisplayList(list, loc, len) + draw(disList, sel, loc) + + -- Loop + while true do + local e, key, x, y = os.pullEvent() + + if e == "mouse_click" then + for i, v in ipairs(disList) do + if x >= 3 and x <= w - 11 and y >= i * 4 + 3 and y <= i * 4 + 5 then return v end + end + elseif e == "key" and key == 200 then + if sel > 1 then + sel = sel - 1 + draw(disList, sel, loc) + elseif loc > 1 then + loc = loc - 1 + disList = updateDisplayList(list, loc, len) + draw(disList, sel, loc) + end + elseif e == "key" and key == 208 then + if sel < len then + sel = sel + 1 + draw(disList, sel, loc) + elseif loc + len - 1 < #list then + loc = loc + 1 + disList = updateDisplayList(list, loc, len) + draw(disList, sel, loc) + end + elseif e == "mouse_scroll" then + os.queueEvent("key", key == -1 and 200 or 208) + elseif e == "key" and key == 28 then + return disList[sel] + end + end +end + +function monitorKeyboardShortcuts() + local ta, tb = nil, nil + local allowChar = false + local shiftPressed = false + while true do + local event, char = os.pullEvent() + if event == "key" and (char == 42 or char == 52) then + shiftPressed = true + tb = os.startTimer(keyboardShortcutTimeout) + elseif event == "key" and (char == 29 or char == 157 or char == 219 or char == 220) then + allowEditorEvent = false + allowChar = true + ta = os.startTimer(keyboardShortcutTimeout) + elseif event == "key" and allowChar then + local name = nil + for k, v in pairs(keys) do + if v == char then + if shiftPressed then os.queueEvent("shortcut", "ctrl shift", k:lower()) + else os.queueEvent("shortcut", "ctrl", k:lower()) end + sleep(0.005) + allowEditorEvent = true + end + end + if shiftPressed then os.queueEvent("shortcut", "ctrl shift", char) + else os.queueEvent("shortcut", "ctrl", char) end + elseif event == "timer" and char == ta then + allowEditorEvent = true + allowChar = false + elseif event == "timer" and char == tb then + shiftPressed = false + end + end +end + + +-- -------- Saving and Loading + +--[[local function download(url, path) + for i = 1, 3 do + local response = http.get(url) + if response then + local data = response.readAll() + response.close() + if path then + local f = io.open(path, "w") + f:write(data) + f:close() + end + return true + end + end + + return false +end]] + +local function saveFile(path, lines) + local dir = path:sub(1, path:len() - fs.getName(path):len()) + if not fs.exists(dir) then fs.makeDir(dir) end + if not fs.isDir(path) and not fs.isReadOnly(path) then + local a = "" + for _, v in pairs(lines) do a = a .. v .. "\n" end + + local f = io.open(path, "w") + f:write(a) + f:close() + return true + else return false end +end + +local function loadFile(path) + if not fs.exists(path) then + local dir = path:sub(1, path:len() - fs.getName(path):len()) + if not fs.exists(dir) then fs.makeDir(dir) end + local f = io.open(path, "w") + f:write("") + f:close() + end + + local l = {} + if fs.exists(path) and not fs.isDir(path) then + local f = io.open(path, "r") + if f then + local a = f:read("*l") + while a do + table.insert(l, a) + a = f:read("*l") + end + f:close() + end + else return nil end + + if #l < 1 then table.insert(l, "") end + return l +end + + +-- -------- Languages + +languages.lua = {} +languages.brainfuck = {} +languages.none = {} + +-- Lua + +languages.lua.helpTips = { + "A function you tried to call doesn't exist.", + "You made a typo.", + "The index of an array is nil.", + "The wrong variable type was passed.", + "A function/variable doesn't exist.", + "You missed an 'end'.", + "You missed a 'then'.", + "You declared a variable incorrectly.", + "One of your variables is mysteriously nil." +} + +languages.lua.defaultHelpTips = { + 2, 5 +} + +languages.lua.errors = { + ["Attempt to call nil."] = {1, 2}, + ["Attempt to index nil."] = {3, 2}, + [".+ expected, got .+"] = {4, 2, 9}, + ["'end' expected"] = {6, 2}, + ["'then' expected"] = {7, 2}, + ["'=' expected"] = {8, 2} +} + +languages.lua.keywords = { + ["and"] = "conditional", + ["break"] = "conditional", + ["do"] = "conditional", + ["else"] = "conditional", + ["elseif"] = "conditional", + ["end"] = "conditional", + ["for"] = "conditional", + ["function"] = "conditional", + ["if"] = "conditional", + ["in"] = "conditional", + ["local"] = "conditional", + ["not"] = "conditional", + ["or"] = "conditional", + ["repeat"] = "conditional", + ["return"] = "conditional", + ["then"] = "conditional", + ["until"] = "conditional", + ["while"] = "conditional", + + ["true"] = "constant", + ["false"] = "constant", + ["nil"] = "constant", + + ["print"] = "function", + ["write"] = "function", + ["sleep"] = "function", + ["pairs"] = "function", + ["ipairs"] = "function", + ["load"] = "function", + ["loadfile"] = "function", + ["rawset"] = "function", + ["rawget"] = "function", +} + +languages.lua.parseError = function(e) + local ret = {filename = "unknown", line = -1, display = "Unknown!", err = ""} + if e and e ~= "" then + ret.err = e + if e:find(":") then + ret.filename = e:sub(1, e:find(":") - 1):gsub("^%s*(.-)%s*$", "%1") + -- The "" is needed to circumvent a CC bug + e = (e:sub(e:find(":") + 1) .. ""):gsub("^%s*(.-)%s*$", "%1") + if e:find(":") then + ret.line = e:sub(1, e:find(":") - 1) + e = e:sub(e:find(":") + 2):gsub("^%s*(.-)%s*$", "%1") .. "" + end + end + ret.display = e:sub(1, 1):upper() .. e:sub(2, -1) .. "." + end + + return ret +end + +languages.lua.getCompilerErrors = function(code) + code = "local function ee65da6af1cb6f63fee9a081246f2fd92b36ef2(...)\n\n" .. code .. "\n\nend" + local fn, err = load(code) + if not err then + local _, e = pcall(fn) + if e then err = e end + end + + if err then + local a = err:find("]", 1, true) + if a then err = "string" .. err:sub(a + 1, -1) end + local ret = languages.lua.parseError(err) + if tonumber(ret.line) then ret.line = tonumber(ret.line) end + return ret + else return languages.lua.parseError(nil) end +end + +languages.lua.run = function(path, ar) + local fn, err = loadfile(path, _ENV) + if not err then + _, err = pcall(function() fn(table.unpack(ar)) end) + end + return err +end + + +-- Brainfuck + +languages.brainfuck.helpTips = { + "Well idk...", + "Isn't this the whole point of the language?", + "Ya know... Not being able to debug it?", + "You made a typo." +} + +languages.brainfuck.defaultHelpTips = { + 1, 2, 3 +} + +languages.brainfuck.errors = { + ["No matching '['"] = {1, 2, 3, 4} +} + +languages.brainfuck.keywords = {} + +languages.brainfuck.parseError = function(e) + local ret = {filename = "unknown", line = -1, display = "Unknown!", err = ""} + if e and e ~= "" then + ret.err = e + ret.line = e:sub(1, e:find(":") - 1) + e = e:sub(e:find(":") + 2):gsub("^%s*(.-)%s*$", "%1") .. "" + ret.display = e:sub(1, 1):upper() .. e:sub(2, -1) .. "." + end + + return ret +end + +languages.brainfuck.mapLoops = function(code) + -- Map loops + local loopLocations = {} + local loc = 1 + local line = 1 + for let in string.gmatch(code, ".") do + if let == "[" then + loopLocations[loc] = true + elseif let == "]" then + local found = false + for i = loc, 1, -1 do + if loopLocations[i] == true then + loopLocations[i] = loc + found = true + end + end + + if not found then + return line .. ": No matching '['" + end + end + + if let == "\n" then line = line + 1 end + loc = loc + 1 + end + return loopLocations +end + +languages.brainfuck.getCompilerErrors = function(code) + local a = languages.brainfuck.mapLoops(code) + if type(a) == "string" then return languages.brainfuck.parseError(a) + else return languages.brainfuck.parseError(nil) end +end + +languages.brainfuck.run = function(path) + -- Read from file + local f = io.open(path, "r") + local content = f:read("*a") + f:close() + + -- Define environment + local dataCells = {} + local dataPointer = 1 + local instructionPointer = 1 + + -- Map loops + local loopLocations = languages.brainfuck.mapLoops(content) + if type(loopLocations) == "string" then return loopLocations end + + -- Execute code + while true do + local let = content:sub(instructionPointer, instructionPointer) + + if let == ">" then + dataPointer = dataPointer + 1 + if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end + elseif let == "<" then + if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end + dataPointer = dataPointer - 1 + if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end + elseif let == "+" then + if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end + dataCells[tostring(dataPointer)] = dataCells[tostring(dataPointer)] + 1 + elseif let == "-" then + if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end + dataCells[tostring(dataPointer)] = dataCells[tostring(dataPointer)] - 1 + elseif let == "." then + if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end + if term.getCursorPos() >= w then print("") end + write(string.char(math.max(1, dataCells[tostring(dataPointer)]))) + elseif let == "," then + if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end + term.setCursorBlink(true) + local e, but = os.pullEvent("char") + term.setCursorBlink(false) + dataCells[tostring(dataPointer)] = string.byte(but) + if term.getCursorPos() >= w then print("") end + write(but) + elseif let == "/" then + if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end + if term.getCursorPos() >= w then print("") end + write(dataCells[tostring(dataPointer)]) + elseif let == "[" then + if dataCells[tostring(dataPointer)] == 0 then + for k, v in pairs(loopLocations) do + if k == instructionPointer then instructionPointer = v end + end + end + elseif let == "]" then + for k, v in pairs(loopLocations) do + if v == instructionPointer then instructionPointer = k - 1 end + end + end + + instructionPointer = instructionPointer + 1 + if instructionPointer > content:len() then print("") break end + end +end + +-- None + +languages.none.helpTips = {} +languages.none.defaultHelpTips = {} +languages.none.errors = {} +languages.none.keywords = {} + +languages.none.parseError = function(err) + return {filename = "", line = -1, display = "", err = ""} +end + +languages.none.getCompilerErrors = function(code) + return languages.none.parseError(nil) +end + +languages.none.run = function(path) end + + +-- Load language +curLanguage = languages.lua + + +-- -------- Run GUI + +local function viewErrorHelp(e) + title("LuaIDE - Error Help") + + local tips = nil + for k, v in pairs(curLanguage.errors) do + if e.display:find(k) then tips = v break end + end + + term.setBackgroundColor(colors[theme.err]) + for i = 6, 8 do + term.setCursorPos(5, i) + term.write(string.rep(" ", 35)) + end + + term.setBackgroundColor(colors[theme.prompt]) + for i = 10, 18 do + term.setCursorPos(5, i) + term.write(string.rep(" ", 46)) + end + + if tips then + term.setBackgroundColor(colors[theme.err]) + term.setCursorPos(6, 7) + term.write("Error Help") + + term.setBackgroundColor(colors[theme.prompt]) + for i, v in ipairs(tips) do + term.setCursorPos(7, i + 10) + term.write("- " .. curLanguage.helpTips[v]) + end + else + term.setBackgroundColor(colors[theme.err]) + term.setCursorPos(6, 7) + term.write("No Error Tips Available!") + + term.setBackgroundColor(colors[theme.prompt]) + term.setCursorPos(6, 11) + term.write("There are no error tips available, but") + term.setCursorPos(6, 12) + term.write("you could see if it was any of these:") + + for i, v in ipairs(curLanguage.defaultHelpTips) do + term.setCursorPos(7, i + 12) + term.write("- " .. curLanguage.helpTips[v]) + end + end + + prompt({{"Back", w - 8, 7}}, "horizontal") +end + +local function run(path, lines, useArgs) + local ar = {} + if useArgs then + title("LuaIDE - Run " .. fs.getName(path)) + local s = centerRead(w - 13, fs.getName(path) .. " ") + for m in string.gmatch(s, "[^ \t]+") do ar[#ar + 1] = m:gsub("^%s*(.-)%s*$", "%1") end + end + + saveFile(path, lines) + term.setCursorBlink(false) + term.setBackgroundColor(colors.black) + term.setTextColor(colors.white) + term.clear() + term.setCursorPos(1, 1) + local err = curLanguage.run(path, ar) + + term.setBackgroundColor(colors.black) + print("\n") + if err then + if isAdvanced() then term.setTextColor(colors.red) end + centerPrint("The program has crashed!") + end + term.setTextColor(colors.white) + centerPrint("Press any key to return to LuaIDE...") + while true do + local e = os.pullEvent() + if e == "key" then break end + end + + -- To prevent key from showing up in editor + os.queueEvent(event_distract) + os.pullEvent() + + if err then + if curLanguage == languages.lua and err:find("]") then + err = fs.getName(path) .. err:sub(err:find("]", 1, true) + 1, -1) + end + + while true do + title("LuaIDE - Error!") + + term.setBackgroundColor(colors[theme.err]) + for i = 6, 8 do + term.setCursorPos(3, i) + term.write(string.rep(" ", w - 5)) + end + term.setCursorPos(4, 7) + term.write("The program has crashed!") + + term.setBackgroundColor(colors[theme.prompt]) + for i = 10, 14 do + term.setCursorPos(3, i) + term.write(string.rep(" ", w - 5)) + end + + local formattedErr = curLanguage.parseError(err) + term.setCursorPos(4, 11) + term.write("Line: " .. formattedErr.line) + term.setCursorPos(4, 12) + term.write("Error:") + term.setCursorPos(5, 13) + + local a = formattedErr.display + local b = nil + if a:len() > w - 8 then + for i = a:len(), 1, -1 do + if a:sub(i, i) == " " then + b = a:sub(i + 1, -1) + a = a:sub(1, i) + break + end + end + end + + term.write(a) + if b then + term.setCursorPos(5, 14) + term.write(b) + end + + local opt = prompt({{"Error Help", w/2 - 15, 17}, {"Go To Line", w/2 + 2, 17}}, + "horizontal") + if opt == "Error Help" then + viewErrorHelp(formattedErr) + elseif opt == "Go To Line" then + -- To prevent key from showing up in editor + os.queueEvent(event_distract) + os.pullEvent() + + return "go to", tonumber(formattedErr.line) + end + end + end +end + + +-- -------- Functions + +local function goto() + term.setBackgroundColor(colors[theme.backgroundHighlight]) + term.setCursorPos(2, 1) + term.clearLine() + term.write("Line: ") + local line = modRead({visibleLength = w - 2}) + + local num = tonumber(line) + if num and num > 0 then return num + else + term.setCursorPos(2, 1) + term.clearLine() + term.write("Not a line number!") + sleep(1.6) + return nil + end +end + +local function setsyntax() + local opts = { + "[Lua] Brainfuck None ", + " Lua [Brainfuck] None ", + " Lua Brainfuck [None]" + } + local sel = 1 + + term.setCursorBlink(false) + term.setBackgroundColor(colors[theme.backgroundHighlight]) + term.setCursorPos(2, 1) + term.clearLine() + term.write(opts[sel]) + while true do + local e, but, x, y = os.pullEvent("key") + if but == 203 then + sel = math.max(1, sel - 1) + term.setCursorPos(2, 1) + term.clearLine() + term.write(opts[sel]) + elseif but == 205 then + sel = math.min(#opts, sel + 1) + term.setCursorPos(2, 1) + term.clearLine() + term.write(opts[sel]) + elseif but == 28 then + if sel == 1 then curLanguage = languages.lua + elseif sel == 2 then curLanguage = languages.brainfuck + elseif sel == 3 then curLanguage = languages.none end + term.setCursorBlink(true) + return + end + end +end + + +-- -------- Re-Indenting + +local tabWidth = 2 + +local comments = {} +local strings = {} + +local increment = { + "if%s+.+%s+then%s*$", + "for%s+.+%s+do%s*$", + "while%s+.+%s+do%s*$", + "repeat%s*$", + "function%s+[a-zA-Z_0-9]\(.*\)%s*$" +} + +local decrement = { + "end", + "until%s+.+" +} + +local special = { + "else%s*$", + "elseif%s+.+%s+then%s*$" +} + +local function check(func) + for _, v in pairs(func) do + local cLineStart = v["lineStart"] + local cLineEnd = v["lineEnd"] + local cCharStart = v["charStart"] + local cCharEnd = v["charEnd"] + + if line >= cLineStart and line <= cLineEnd then + if line == cLineStart then return cCharStart < charNumb + elseif line == cLineEnd then return cCharEnd > charNumb + else return true end + end + end +end + +local function isIn(line, loc) + if check(comments) then return true end + if check(strings) then return true end + return false +end + +local function setComment(ls, le, cs, ce) + comments[#comments + 1] = {} + comments[#comments].lineStart = ls + comments[#comments].lineEnd = le + comments[#comments].charStart = cs + comments[#comments].charEnd = ce +end + +local function setString(ls, le, cs, ce) + strings[#strings + 1] = {} + strings[#strings].lineStart = ls + strings[#strings].lineEnd = le + strings[#strings].charStart = cs + strings[#strings].charEnd = ce +end + +local function map(contents) + local inCom = false + local inStr = false + + for i = 1, #contents do + if content[i]:find("%-%-%[%[") and not inStr and not inCom then + local cStart = content[i]:find("%-%-%[%[") + setComment(i, nil, cStart, nil) + inCom = true + elseif content[i]:find("%-%-%[=%[") and not inStr and not inCom then + local cStart = content[i]:find("%-%-%[=%[") + setComment(i, nil, cStart, nil) + inCom = true + elseif content[i]:find("%[%[") and not inStr and not inCom then + local cStart = content[i]:find("%[%[") + setString(i, nil, cStart, nil) + inStr = true + elseif content[i]:find("%[=%[") and not inStr and not inCom then + local cStart = content[i]:find("%[=%[") + setString(i, nil, cStart, nil) + inStr = true + end + + if content[i]:find("%]%]") and inStr and not inCom then + local cStart, cEnd = content[i]:find("%]%]") + strings[#strings].lineEnd = i + strings[#strings].charEnd = cEnd + inStr = false + elseif content[i]:find("%]=%]") and inStr and not inCom then + local cStart, cEnd = content[i]:find("%]=%]") + strings[#strings].lineEnd = i + strings[#strings].charEnd = cEnd + inStr = false + end + + if content[i]:find("%]%]") and not inStr and inCom then + local cStart, cEnd = content[i]:find("%]%]") + comments[#comments].lineEnd = i + comments[#comments].charEnd = cEnd + inCom = false + elseif content[i]:find("%]=%]") and not inStr and inCom then + local cStart, cEnd = content[i]:find("%]=%]") + comments[#comments].lineEnd = i + comments[#comments].charEnd = cEnd + inCom = false + end + + if content[i]:find("%-%-") and not inStr and not inCom then + local cStart = content[i]:find("%-%-") + setComment(i, i, cStart, -1) + elseif content[i]:find("'") and not inStr and not inCom then + local cStart, cEnd = content[i]:find("'") + local nextChar = content[i]:sub(cEnd + 1, string.len(content[i])) + local _, cEnd = nextChar:find("'") + setString(i, i, cStart, cEnd) + elseif content[i]:find('"') and not inStr and not inCom then + local cStart, cEnd = content[i]:find('"') + local nextChar = content[i]:sub(cEnd + 1, string.len(content[i])) + local _, cEnd = nextChar:find('"') + setString(i, i, cStart, cEnd) + end + end +end + +local function reindent(contents) + local err = nil + if curLanguage ~= languages.lua then + err = "Cannot indent languages other than Lua!" + elseif curLanguage.getCompilerErrors(table.concat(contents, "\n")).line ~= -1 then + err = "Cannot indent a program with errors!" + end + + if err then + term.setCursorBlink(false) + term.setCursorPos(2, 1) + term.setBackgroundColor(colors[theme.backgroundHighlight]) + term.clearLine() + term.write(err) + sleep(1.6) + return contents + end + + local new = {} + local level = 0 + for k, v in pairs(contents) do + local incrLevel = false + local foundIncr = false + for _, incr in pairs(increment) do + if v:find(incr) and not isIn(k, v:find(incr)) then + incrLevel = true + end + if v:find(incr:sub(1, -2)) and not isIn(k, v:find(incr)) then + foundIncr = true + end + end + + local decrLevel = false + if not incrLevel then + for _, decr in pairs(decrement) do + if v:find(decr) and not isIn(k, v:find(decr)) and not foundIncr then + level = math.max(0, level - 1) + decrLevel = true + end + end + end + + if not decrLevel then + for _, sp in pairs(special) do + if v:find(sp) and not isIn(k, v:find(sp)) then + incrLevel = true + level = math.max(0, level - 1) + end + end + end + + new[k] = string.rep(" ", level * tabWidth) .. v + if incrLevel then level = level + 1 end + end + + return new +end + + +-- -------- Menu + +local menu = { + [1] = {"File", +-- "About", +-- "Settings", +-- "", + "New File ^+N", + "Open File ^+O", + "Save File ^+S", + "Close ^+W", + "Print ^+P", + "Quit ^+Q" + }, [2] = {"Edit", + "Cut Line ^+X", + "Copy Line ^+C", + "Paste Line ^+V", + "Delete Line", + "Clear Line" + }, [3] = {"Functions", + "Go To Line ^+G", + "Re-Indent ^+I", + "Set Syntax ^+E", + "Start of Line ^+<", + "End of Line ^+>" + }, [4] = {"Run", + "Run Program ^+R", + "Run w/ Args ^+Shift+R" + } +} + +local shortcuts = { + -- File + ["ctrl n"] = "New File ^+N", + ["ctrl o"] = "Open File ^+O", + ["ctrl s"] = "Save File ^+S", + ["ctrl w"] = "Close ^+W", + ["ctrl p"] = "Print ^+P", + ["ctrl q"] = "Quit ^+Q", + + -- Edit + ["ctrl x"] = "Cut Line ^+X", + ["ctrl c"] = "Copy Line ^+C", + ["ctrl v"] = "Paste Line ^+V", + + -- Functions + ["ctrl g"] = "Go To Line ^+G", + ["ctrl i"] = "Re-Indent ^+I", + ["ctrl e"] = "Set Syntax ^+E", + ["ctrl 203"] = "Start of Line ^+<", + ["ctrl 205"] = "End of Line ^+>", + + -- Run + ["ctrl r"] = "Run Program ^+R", + ["ctrl shift r"] = "Run w/ Args ^+Shift+R" +} + +local menuFunctions = { + -- File +-- ["About"] = function() end, +-- ["Settings"] = function() end, + ["New File ^+N"] = function(path, lines) saveFile(path, lines) return "new" end, + ["Open File ^+O"] = function(path, lines) saveFile(path, lines) return "open" end, + ["Save File ^+S"] = function(path, lines) saveFile(path, lines) end, + ["Close ^+W"] = function(path, lines) saveFile(path, lines) return "menu" end, + ["Print ^+P"] = function(path, lines) saveFile(path, lines) return nil end, + ["Quit ^+Q"] = function(path, lines) saveFile(path, lines) return "exit" end, + + -- Edit + ["Cut Line ^+X"] = function(path, lines, y) + clipboard = lines[y] table.remove(lines, y) return nil, lines end, + ["Copy Line ^+C"] = function(path, lines, y) clipboard = lines[y] end, + ["Paste Line ^+V"] = function(path, lines, y) + if clipboard then table.insert(lines, y, clipboard) end return nil, lines end, + ["Delete Line"] = function(path, lines, y) table.remove(lines, y) return nil, lines end, + ["Clear Line"] = function(path, lines, y) lines[y] = "" return nil, lines, "cursor" end, + + -- Functions + ["Go To Line ^+G"] = function() return nil, "go to", goto() end, + ["Re-Indent ^+I"] = function(path, lines) + local a = reindent(lines) saveFile(path, lines) return nil, a + end, + ["Set Syntax ^+E"] = function(path, lines) + setsyntax() + if curLanguage == languages.brainfuck and lines[1] ~= "-- Syntax: Brainfuck" then + table.insert(lines, 1, "-- Syntax: Brainfuck") + return nil, lines + end + end, + ["Start of Line ^+<"] = function() os.queueEvent("key", 199) end, + ["End of Line ^+>"] = function() os.queueEvent("key", 207) end, + + -- Run + ["Run Program ^+R"] = function(path, lines) + saveFile(path, lines) + return nil, run(path, lines, false) + end, + ["Run w/ Args ^+Shift+R"] = function(path, lines) + saveFile(path, lines) + return nil, run(path, lines, true) + end, +} + +local function drawMenu(open) + term.setCursorPos(1, 1) + term.setTextColor(colors[theme.textColor]) + term.setBackgroundColor(colors[theme.backgroundHighlight]) + term.clearLine() + local curX = 0 + for _, v in pairs(menu) do + term.setCursorPos(3 + curX, 1) + term.write(v[1]) + curX = curX + v[1]:len() + 3 + end + + if open then + local it = {} + local x = 1 + for _, v in pairs(menu) do + if open == v[1] then + it = v + break + end + x = x + v[1]:len() + 3 + end + x = x + 1 + + local items = {} + for i = 2, #it do + table.insert(items, it[i]) + end + + local len = 1 + for _, v in pairs(items) do if v:len() + 2 > len then len = v:len() + 2 end end + + for i, v in ipairs(items) do + term.setCursorPos(x, i + 1) + term.write(string.rep(" ", len)) + term.setCursorPos(x + 1, i + 1) + term.write(v) + end + term.setCursorPos(x, #items + 2) + term.write(string.rep(" ", len)) + return items, len + end +end + +local function triggerMenu(cx, cy) + -- Determine clicked menu + local curX = 0 + local open = nil + for _, v in pairs(menu) do + if cx >= curX + 3 and cx <= curX + v[1]:len() + 2 then + open = v[1] + break + end + curX = curX + v[1]:len() + 3 + end + local menux = curX + 2 + if not open then return false end + + -- Flash menu item + term.setCursorBlink(false) + term.setCursorPos(menux, 1) + term.setBackgroundColor(colors[theme.background]) + term.write(string.rep(" ", open:len() + 2)) + term.setCursorPos(menux + 1, 1) + term.write(open) + sleep(0.1) + local items, len = drawMenu(open) + + local ret = true + + -- Pull events on menu + local ox, oy = term.getCursorPos() + while type(ret) ~= "string" do + local e, but, x, y = os.pullEvent() + if e == "mouse_click" then + -- If clicked outside menu + if x < menux - 1 or x > menux + len - 1 then break + elseif y > #items + 2 then break + elseif y == 1 then break end + + for i, v in ipairs(items) do + if y == i + 1 and x >= menux and x <= menux + len - 2 then + -- Flash when clicked + term.setCursorPos(menux, y) + term.setBackgroundColor(colors[theme.background]) + term.write(string.rep(" ", len)) + term.setCursorPos(menux + 1, y) + term.write(v) + sleep(0.1) + drawMenu(open) + + -- Return item + ret = v + break + end + end + end + end + + term.setCursorPos(ox, oy) + term.setCursorBlink(true) + return ret +end + + +-- -------- Editing + +local standardsCompletions = { + "if%s+.+%s+then%s*$", + "for%s+.+%s+do%s*$", + "while%s+.+%s+do%s*$", + "repeat%s*$", + "function%s+[a-zA-Z_0-9]?\(.*\)%s*$", + "=%s*function%s*\(.*\)%s*$", + "else%s*$", + "elseif%s+.+%s+then%s*$" +} + +local liveCompletions = { + ["("] = ")", + ["{"] = "}", + ["["] = "]", + ["\""] = "\"", + ["'"] = "'", +} + +local x, y = 0, 0 +local edw, edh = 0, h - 1 +local offx, offy = 0, 1 +local scrollx, scrolly = 0, 0 +local lines = {} +local liveErr = curLanguage.parseError(nil) +local displayCode = true +local lastEventClock = os.clock() + +local function attemptToHighlight(line, regex, col) + local match = string.match(line, regex) + if match then + if type(col) == "number" then term.setTextColor(col) + elseif type(col) == "function" then term.setTextColor(col(match)) end + term.write(match) + term.setTextColor(colors[theme.textColor]) + return line:sub(match:len() + 1, -1) + end + return nil +end + +local function writeHighlighted(line) + if curLanguage == languages.lua then + while line:len() > 0 do + line = attemptToHighlight(line, "^%-%-%[%[.-%]%]", colors[theme.comment]) or + attemptToHighlight(line, "^%-%-.*", colors[theme.comment]) or + attemptToHighlight(line, "^\".*[^\\]\"", colors[theme.string]) or + attemptToHighlight(line, "^\'.*[^\\]\'", colors[theme.string]) or + attemptToHighlight(line, "^%[%[.-%]%]", colors[theme.string]) or + attemptToHighlight(line, "^[%w_]+", function(match) + if curLanguage.keywords[match] then + return colors[theme[curLanguage.keywords[match]]] + end + return colors[theme.textColor] + end) or + attemptToHighlight(line, "^[^%w_]", colors[theme.textColor]) + end + else term.write(line) end +end + +local function draw() + -- Menu + term.setTextColor(colors[theme.textColor]) + term.setBackgroundColor(colors[theme.editorBackground]) + term.clear() + drawMenu() + + -- Line numbers + offx, offy = tostring(#lines):len() + 1, 1 + edw, edh = w - offx, h - 1 + + -- Draw text + for i = 1, edh do + local a = lines[scrolly + i] + if a then + local ln = string.rep(" ", offx - 1 - tostring(scrolly + i):len()) .. tostring(scrolly + i) + local l = a:sub(scrollx + 1, edw + scrollx + 1) + ln = ln .. ":" + + if liveErr.line == scrolly + i then ln = string.rep(" ", offx - 2) .. "!:" end + + term.setCursorPos(1, i + offy) + term.setBackgroundColor(colors[theme.editorBackground]) + if scrolly + i == y then + if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then + term.setBackgroundColor(colors[theme.editorErrorHighlight]) + else term.setBackgroundColor(colors[theme.editorLineHightlight]) end + term.clearLine() + elseif scrolly + i == liveErr.line then + term.setBackgroundColor(colors[theme.editorError]) + term.clearLine() + end + + term.setCursorPos(1 - scrollx + offx, i + offy) + if scrolly + i == y then + if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then + term.setBackgroundColor(colors[theme.editorErrorHighlight]) + else term.setBackgroundColor(colors[theme.editorLineHightlight]) end + elseif scrolly + i == liveErr.line then term.setBackgroundColor(colors[theme.editorError]) + else term.setBackgroundColor(colors[theme.editorBackground]) end + if scrolly + i == liveErr.line then + if displayCode then term.write(a) + else term.write(liveErr.display) end + else writeHighlighted(a) end + + term.setCursorPos(1, i + offy) + if scrolly + i == y then + if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then + term.setBackgroundColor(colors[theme.editorError]) + else term.setBackgroundColor(colors[theme.editorLineNumbersHighlight]) end + elseif scrolly + i == liveErr.line then + term.setBackgroundColor(colors[theme.editorErrorHighlight]) + else term.setBackgroundColor(colors[theme.editorLineNumbers]) end + term.write(ln) + end + end + term.setCursorPos(x - scrollx + offx, y - scrolly + offy) +end + +local function drawLine(...) + local ls = {...} + offx = tostring(#lines):len() + 1 + for _, ly in pairs(ls) do + local a = lines[ly] + if a then + local ln = string.rep(" ", offx - 1 - tostring(ly):len()) .. tostring(ly) + local l = a:sub(scrollx + 1, edw + scrollx + 1) + ln = ln .. ":" + + if liveErr.line == ly then ln = string.rep(" ", offx - 2) .. "!:" end + + term.setCursorPos(1, (ly - scrolly) + offy) + term.setBackgroundColor(colors[theme.editorBackground]) + if ly == y then + if ly == liveErr.line and os.clock() - lastEventClock > 3 then + term.setBackgroundColor(colors[theme.editorErrorHighlight]) + else term.setBackgroundColor(colors[theme.editorLineHightlight]) end + elseif ly == liveErr.line then + term.setBackgroundColor(colors[theme.editorError]) + end + term.clearLine() + + term.setCursorPos(1 - scrollx + offx, (ly - scrolly) + offy) + if ly == y then + if ly == liveErr.line and os.clock() - lastEventClock > 3 then + term.setBackgroundColor(colors[theme.editorErrorHighlight]) + else term.setBackgroundColor(colors[theme.editorLineHightlight]) end + elseif ly == liveErr.line then term.setBackgroundColor(colors[theme.editorError]) + else term.setBackgroundColor(colors[theme.editorBackground]) end + if ly == liveErr.line then + if displayCode then term.write(a) + else term.write(liveErr.display) end + else writeHighlighted(a) end + + term.setCursorPos(1, (ly - scrolly) + offy) + if ly == y then + if ly == liveErr.line and os.clock() - lastEventClock > 3 then + term.setBackgroundColor(colors[theme.editorError]) + else term.setBackgroundColor(colors[theme.editorLineNumbersHighlight]) end + elseif ly == liveErr.line then + term.setBackgroundColor(colors[theme.editorErrorHighlight]) + else term.setBackgroundColor(colors[theme.editorLineNumbers]) end + term.write(ln) + end + end + term.setCursorPos(x - scrollx + offx, y - scrolly + offy) +end + +local function cursorLoc(x, y, force) + local sx, sy = x - scrollx, y - scrolly + local redraw = false + if sx < 1 then + scrollx = x - 1 + sx = 1 + redraw = true + elseif sx > edw then + scrollx = x - edw + sx = edw + redraw = true + end if sy < 1 then + scrolly = y - 1 + sy = 1 + redraw = true + elseif sy > edh then + scrolly = y - edh + sy = edh + redraw = true + end if redraw or force then draw() end + term.setCursorPos(sx + offx, sy + offy) +end + +local function executeMenuItem(a, path) + if type(a) == "string" and menuFunctions[a] then + local opt, nl, gtln = menuFunctions[a](path, lines, y) + if type(opt) == "string" then term.setCursorBlink(false) return opt end + if type(nl) == "table" then + if #lines < 1 then table.insert(lines, "") end + y = math.min(y, #lines) + x = math.min(x, lines[y]:len() + 1) + lines = nl + elseif type(nl) == "string" then + if nl == "go to" and gtln then + x, y = 1, math.min(#lines, gtln) + cursorLoc(x, y) + end + end + end + term.setCursorBlink(true) + draw() + term.setCursorPos(x - scrollx + offx, y - scrolly + offy) +end + +local function edit(path) + -- Variables + x, y = 1, 1 + offx, offy = 0, 1 + scrollx, scrolly = 0, 0 + lines = loadFile(path) + if not lines then return "menu" end + + -- Enable brainfuck + if lines[1] == "-- Syntax: Brainfuck" then + curLanguage = languages.brainfuck + end + + -- Clocks + local autosaveClock = os.clock() + local scrollClock = os.clock() -- To prevent redraw flicker + local liveErrorClock = os.clock() + local hasScrolled = false + + -- Draw + draw() + term.setCursorPos(x + offx, y + offy) + term.setCursorBlink(true) + + -- Main loop + local tid = os.startTimer(3) + while true do + local e, key, cx, cy = os.pullEvent() + if e == "key" and allowEditorEvent then + if key == 200 and y > 1 then + -- Up + x, y = math.min(x, lines[y - 1]:len() + 1), y - 1 + drawLine(y, y + 1) + cursorLoc(x, y) + elseif key == 208 and y < #lines then + -- Down + x, y = math.min(x, lines[y + 1]:len() + 1), y + 1 + drawLine(y, y - 1) + cursorLoc(x, y) + elseif key == 203 and x > 1 then + -- Left + x = x - 1 + local force = false + if y - scrolly + offy < offy + 1 then force = true end + cursorLoc(x, y, force) + elseif key == 205 and x < lines[y]:len() + 1 then + -- Right + x = x + 1 + local force = false + if y - scrolly + offy < offy + 1 then force = true end + cursorLoc(x, y, force) + elseif (key == 28 or key == 156) and (displayCode and true or y + scrolly - 1 == + liveErr.line) then + -- Enter + local f = nil + for _, v in pairs(standardsCompletions) do + if lines[y]:find(v) then f = v end + end + + local _, spaces = lines[y]:find("^[ ]+") + if not spaces then spaces = 0 end + if f then + table.insert(lines, y + 1, string.rep(" ", spaces + 2)) + if not f:find("else", 1, true) and not f:find("elseif", 1, true) then + table.insert(lines, y + 2, string.rep(" ", spaces) .. + (f:find("repeat", 1, true) and "until " or f:find("{", 1, true) and "}" or + "end")) + end + x, y = spaces + 3, y + 1 + cursorLoc(x, y, true) + else + local oldLine = lines[y] + + lines[y] = lines[y]:sub(1, x - 1) + table.insert(lines, y + 1, string.rep(" ", spaces) .. oldLine:sub(x, -1)) + + x, y = spaces + 1, y + 1 + cursorLoc(x, y, true) + end + elseif key == 14 and (displayCode and true or y + scrolly - 1 == liveErr.line) then + -- Backspace + if x > 1 then + local f = false + for k, v in pairs(liveCompletions) do + if lines[y]:sub(x - 1, x - 1) == k then f = true end + end + + lines[y] = lines[y]:sub(1, x - 2) .. lines[y]:sub(x + (f and 1 or 0), -1) + drawLine(y) + x = x - 1 + cursorLoc(x, y) + elseif y > 1 then + local prevLen = lines[y - 1]:len() + 1 + lines[y - 1] = lines[y - 1] .. lines[y] + table.remove(lines, y) + x, y = prevLen, y - 1 + cursorLoc(x, y, true) + end + elseif key == 199 then + -- Home + x = 1 + local force = false + if y - scrolly + offy < offy + 1 then force = true end + cursorLoc(x, y, force) + elseif key == 207 then + -- End + x = lines[y]:len() + 1 + local force = false + if y - scrolly + offy < offy + 1 then force = true end + cursorLoc(x, y, force) + elseif key == 211 and (displayCode and true or y + scrolly - 1 == liveErr.line) then + -- Forward Delete + if x < lines[y]:len() + 1 then + lines[y] = lines[y]:sub(1, x - 1) .. lines[y]:sub(x + 1) + local force = false + if y - scrolly + offy < offy + 1 then force = true end + drawLine(y) + cursorLoc(x, y, force) + elseif y < #lines then + lines[y] = lines[y] .. lines[y + 1] + table.remove(lines, y + 1) + draw() + cursorLoc(x, y) + end + elseif key == 15 and (displayCode and true or y + scrolly - 1 == liveErr.line) then + -- Tab + lines[y] = string.rep(" ", tabWidth) .. lines[y] + x = x + 2 + local force = false + if y - scrolly + offy < offy + 1 then force = true end + drawLine(y) + cursorLoc(x, y, force) + elseif key == 201 then + -- Page up + y = math.min(math.max(y - edh, 1), #lines) + x = math.min(lines[y]:len() + 1, x) + cursorLoc(x, y, true) + elseif key == 209 then + -- Page down + y = math.min(math.max(y + edh, 1), #lines) + x = math.min(lines[y]:len() + 1, x) + cursorLoc(x, y, true) + end + elseif e == "char" and allowEditorEvent and (displayCode and true or + y + scrolly - 1 == liveErr.line) then + local shouldIgnore = false + for k, v in pairs(liveCompletions) do + if key == v and lines[y]:find(k, 1, true) and lines[y]:sub(x, x) == v then + shouldIgnore = true + end + end + + local addOne = false + if not shouldIgnore then + for k, v in pairs(liveCompletions) do + if key == k and lines[y]:sub(x, x) ~= k then key = key .. v addOne = true end + end + lines[y] = lines[y]:sub(1, x - 1) .. key .. lines[y]:sub(x, -1) + end + + x = x + (addOne and 1 or key:len()) + local force = false + if y - scrolly + offy < offy + 1 then force = true end + drawLine(y) + cursorLoc(x, y, force) + elseif e == "mouse_click" and key == 1 then + if cy > 1 then + if cx <= offx and cy - offy == liveErr.line - scrolly then + displayCode = not displayCode + drawLine(liveErr.line) + else + local oldy = y + y = math.min(math.max(scrolly + cy - offy, 1), #lines) + x = math.min(math.max(scrollx + cx - offx, 1), lines[y]:len() + 1) + if oldy ~= y then drawLine(oldy, y) end + cursorLoc(x, y) + end + else + local a = triggerMenu(cx, cy) + if a then + local opt = executeMenuItem(a, path) + if opt then return opt end + end + end + elseif e == "shortcut" then + local a = shortcuts[key .. " " .. cx] + if a then + local parent = nil + local curx = 0 + for i, mv in ipairs(menu) do + for _, iv in pairs(mv) do + if iv == a then + parent = menu[i][1] + break + end + end + if parent then break end + curx = curx + mv[1]:len() + 3 + end + local menux = curx + 2 + + -- Flash menu item + term.setCursorBlink(false) + term.setCursorPos(menux, 1) + term.setBackgroundColor(colors[theme.background]) + term.write(string.rep(" ", parent:len() + 2)) + term.setCursorPos(menux + 1, 1) + term.write(parent) + sleep(0.1) + drawMenu() + + -- Execute item + local opt = executeMenuItem(a, path) + if opt then return opt end + end + elseif e == "mouse_scroll" then + if key == -1 and scrolly > 0 then + scrolly = scrolly - 1 + if os.clock() - scrollClock > 0.0005 then + draw() + term.setCursorPos(x - scrollx + offx, y - scrolly + offy) + end + scrollClock = os.clock() + hasScrolled = true + elseif key == 1 and scrolly < #lines - edh then + scrolly = scrolly + 1 + if os.clock() - scrollClock > 0.0005 then + draw() + term.setCursorPos(x - scrollx + offx, y - scrolly + offy) + end + scrollClock = os.clock() + hasScrolled = true + end + elseif e == "timer" and key == tid then + drawLine(y) + tid = os.startTimer(3) + end + + -- Draw + if hasScrolled and os.clock() - scrollClock > 0.1 then + draw() + term.setCursorPos(x - scrollx + offx, y - scrolly + offy) + hasScrolled = false + end + + -- Autosave + if os.clock() - autosaveClock > autosaveInterval then + saveFile(path, lines) + autosaveClock = os.clock() + end + + -- Errors + if os.clock() - liveErrorClock > 1 then + local prevLiveErr = liveErr + liveErr = curLanguage.parseError(nil) + local code = "" + for _, v in pairs(lines) do code = code .. v .. "\n" end + + liveErr = curLanguage.getCompilerErrors(code) + liveErr.line = math.min(liveErr.line - 2, #lines) + if liveErr ~= prevLiveErr then draw() end + liveErrorClock = os.clock() + end + end + + return "menu" +end + + +-- -------- Open File + +local function newFile() + local wid = w - 13 + + -- Get name + title("Lua IDE - New File") + local name = centerRead(wid, "/") + if not name or name == "" then return "menu" end + name = "/" .. name + + -- Clear + title("Lua IDE - New File") + term.setTextColor(colors[theme.textColor]) + term.setBackgroundColor(colors[theme.promptHighlight]) + for i = 8, 10 do + term.setCursorPos(w/2 - wid/2, i) + term.write(string.rep(" ", wid)) + end + term.setCursorPos(1, 9) + if fs.isDir(name) then + centerPrint("Cannot Edit a Directory!") + sleep(1.6) + return "menu" + elseif fs.exists(name) then + centerPrint("File Already Exists!") + local opt = prompt({{"Open", w/2 - 9, 14}, {"Cancel", w/2 + 2, 14}}, "horizontal") + if opt == "Open" then return "edit", name + elseif opt == "Cancel" then return "menu" end + else return "edit", name end +end + +local function openFile() + local wid = w - 13 + + -- Get name + title("Lua IDE - Open File") + local name = centerRead(wid, "/") + if not name or name == "" then return "menu" end + name = "/" .. name + + -- Clear + title("Lua IDE - New File") + term.setTextColor(colors[theme.textColor]) + term.setBackgroundColor(colors[theme.promptHighlight]) + for i = 8, 10 do + term.setCursorPos(w/2 - wid/2, i) + term.write(string.rep(" ", wid)) + end + term.setCursorPos(1, 9) + if fs.isDir(name) then + centerPrint("Cannot Open a Directory!") + sleep(1.6) + return "menu" + elseif not fs.exists(name) then + centerPrint("File Doesn't Exist!") + local opt = prompt({{"Create", w/2 - 11, 14}, {"Cancel", w/2 + 2, 14}}, "horizontal") + if opt == "Create" then return "edit", name + elseif opt == "Cancel" then return "menu" end + else return "edit", name end +end + + +-- -------- Settings + +local function update() +--[[ + local function draw(status) + title("LuaIDE - Update") + term.setBackgroundColor(colors[theme.prompt]) + term.setTextColor(colors[theme.textColor]) + for i = 8, 10 do + term.setCursorPos(w/2 - (status:len() + 4), i) + write(string.rep(" ", status:len() + 4)) + end + term.setCursorPos(w/2 - (status:len() + 4), 9) + term.write(" - " .. status .. " ") + + term.setBackgroundColor(colors[theme.errHighlight]) + for i = 8, 10 do + term.setCursorPos(w/2 + 2, i) + term.write(string.rep(" ", 10)) + end + term.setCursorPos(w/2 + 2, 9) + term.write(" > Cancel ") + end + + if not http then + draw("HTTP API Disabled!") + sleep(1.6) + return "settings" + end + + draw("Updating...") + local tID = os.startTimer(10) + http.request(updateURL) + while true do + local e, but, x, y = os.pullEvent() + if (e == "key" and but == 28) or + (e == "mouse_click" and x >= w/2 + 2 and x <= w/2 + 12 and y == 9) then + draw("Cancelled") + sleep(1.6) + break + elseif e == "http_success" and but == updateURL then + local new = x.readAll() + local curf = io.open(ideLocation, "r") + local cur = curf:read("*a") + curf:close() + + if cur ~= new then + draw("Update Found") + sleep(1.6) + local f = io.open(ideLocation, "w") + f:write(new) + f:close() + + draw("Click to Exit") + while true do + local e = os.pullEvent() + if e == "mouse_click" or (not isAdvanced() and e == "key") then break end + end + return "exit" + else + draw("No Updates Found!") + sleep(1.6) + break + end + elseif e == "http_failure" or (e == "timer" and but == tID) then + draw("Update Failed!") + sleep(1.6) + break + end + end +]]-- + + return "settings" +end + +local function changeTheme() + title("LuaIDE - Theme") + term.setCursorPos(1, 7) + centerPrint("Themes are not available on the") + centerPrint("treasure disk version of LuaIDE!") + centerPrint("Download the full program from the") + centerPrint("ComputerCraft Forums!") + +--[[ + if isAdvanced() then + local disThemes = {"Back"} + for _, v in pairs(availableThemes) do table.insert(disThemes, v[1]) end + local t = scrollingPrompt(disThemes) + local url = nil + for _, v in pairs(availableThemes) do if v[1] == t then url = v[2] end end + + if not url then return "settings" end + if t == "Dawn (Default)" then + term.setBackgroundColor(colors[theme.backgroundHighlight]) + term.setCursorPos(3, 3) + term.clearLine() + term.write("LuaIDE - Loaded Theme!") + sleep(1.6) + + fs.delete(themeLocation) + theme = defaultTheme + return "menu" + end + + term.setBackgroundColor(colors[theme.backgroundHighlight]) + term.setCursorPos(3, 3) + term.clearLine() + term.write("LuaIDE - Downloading...") + + fs.delete("/.LuaIDE_temp_theme_file") + download(url, "/.LuaIDE_temp_theme_file") + local a = loadTheme("/.LuaIDE_temp_theme_file") + + term.setCursorPos(3, 3) + term.clearLine() + if a then + term.write("LuaIDE - Loaded Theme!") + fs.delete(themeLocation) + fs.move("/.LuaIDE_temp_theme_file", themeLocation) + theme = a + sleep(1.6) + return "menu" + end + + term.write("LuaIDE - Could Not Load Theme!") + fs.delete("/.LuaIDE_temp_theme_file") + sleep(1.6) + return "settings" + else + term.setCursorPos(1, 8) + centerPrint("Themes are not available on") + centerPrint("normal computers!") + end +]]-- +end + +local function settings() + title("LuaIDE - Settings") + + local opt = prompt({{"Change Theme", w/2 - 17, 8}, {"Return to Menu", w/2 - 19, 13}, + --[[{"Check for Updates", w/2 + 2, 8},]] {"Exit IDE", w/2 + 2, 13, bg = colors[theme.err], + highlight = colors[theme.errHighlight]}}, "vertical", true) + if opt == "Change Theme" then return changeTheme() +-- elseif opt == "Check for Updates" then return update() + elseif opt == "Return to Menu" then return "menu" + elseif opt == "Exit IDE" then return "exit" end +end + + +-- -------- Menu + +local function menu() + title("Welcome to LuaIDE " .. version) + + local opt = prompt({{"New File", w/2 - 13, 8}, {"Open File", w/2 - 14, 13}, + {"Settings", w/2 + 2, 8}, {"Exit IDE", w/2 + 2, 13, bg = colors[theme.err], + highlight = colors[theme.errHighlight]}}, "vertical", true) + if opt == "New File" then return "new" + elseif opt == "Open File" then return "open" + elseif opt == "Settings" then return "settings" + elseif opt == "Exit IDE" then return "exit" end +end + + +-- -------- Main + +local function main(arguments) + local opt, data = "menu", nil + + -- Check arguments + if type(arguments) == "table" and #arguments > 0 then + local f = "/" .. shell.resolve(arguments[1]) + if fs.isDir(f) then print("Cannot edit a directory.") end + opt, data = "edit", f + end + + -- Main run loop + while true do + -- Menu + if opt == "menu" then opt = menu() end + + -- Other + if opt == "new" then opt, data = newFile() + elseif opt == "open" then opt, data = openFile() + elseif opt == "settings" then opt = settings() + end if opt == "exit" then break end + + -- Edit + if opt == "edit" and data then opt = edit(data) end + end +end + +-- Load Theme +if fs.exists(themeLocation) then theme = loadTheme(themeLocation) end +if not theme and isAdvanced() then theme = defaultTheme +elseif not theme then theme = normalTheme end + +-- Run +local _, err = pcall(function() + parallel.waitForAny(function() main(args) end, monitorKeyboardShortcuts) +end) + +-- Catch errors +if err and not err:find("Terminated") then + term.setCursorBlink(false) + title("LuaIDE - Crash! D:") + + term.setBackgroundColor(colors[theme.err]) + for i = 6, 8 do + term.setCursorPos(5, i) + term.write(string.rep(" ", 36)) + end + term.setCursorPos(6, 7) + term.write("LuaIDE Has Crashed! D:") + + term.setBackgroundColor(colors[theme.background]) + term.setCursorPos(2, 10) + print(err) + + term.setBackgroundColor(colors[theme.prompt]) + local _, cy = term.getCursorPos() + for i = cy + 1, cy + 4 do + term.setCursorPos(5, i) + term.write(string.rep(" ", 36)) + end + term.setCursorPos(6, cy + 2) + term.write("Please report this error to") + term.setCursorPos(6, cy + 3) + term.write("GravityScore! ") + + term.setBackgroundColor(colors[theme.background]) + if isAdvanced() then centerPrint("Click to Exit...", h - 1) + else centerPrint("Press Any Key to Exit...", h - 1) end + while true do + local e = os.pullEvent() + if e == "mouse_click" or (not isAdvanced() and e == "key") then break end + end + + -- Prevent key from being shown + os.queueEvent(event_distract) + os.pullEvent() +end + +-- Exit +term.setBackgroundColor(colors.black) +term.setTextColor(colors.white) +term.clear() +term.setCursorPos(1, 1) +centerPrint("Thank You for Using Lua IDE " .. version) +centerPrint("Made by GravityScore") diff --git a/src/main/resources/assets/computercraft/lua/treasure/JTK/maze3d/maze2d b/src/main/resources/assets/computercraft/lua/treasure/JTK/maze3d/maze2d new file mode 100644 index 0000000000..ccc85fb29b --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/JTK/maze3d/maze2d @@ -0,0 +1,327 @@ +--[[ + Project info: + + Name: Maze + Creator: Jesusthekiller + Language: Lua (CC) + Website: None + License: GNU GPL + License file can be fount at www.jesusthekiller.com/license-gpl.html + + Version: 1.2 +]]-- + +--[[ + Changelog: + 1.0: + Initial Release + 1.1: + Typos D: + 1.2: + New logo + Time fixed +]]-- + +--[[ + LICENSE: + + Maze + Copyright (c) 2013 Jesusthekiller + + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . +]]-- + +-- The maze + +-- The cprint +local function cwrite(msg) + msg = tostring(msg) + local x, y = term.getCursorPos() + term.setCursorPos((51-#msg)/2, y) + write(msg) +end + +local function cprint(msg) + cwrite(msg.."\n") +end + +-- The splash +term.setBackgroundColor(colors.black) +term.setTextColor(colors.white) +term.clear() + +term.setCursorPos(27, 8) +print("Nano maze!") + +paintutils.drawImage({[1]={[1]=1,[2]=1,[3]=1,[4]=1,[5]=1,[6]=1,[7]=1,[8]=1,[9]=1,[10]=1,[11]=0,[12]=1,[13]=0,[14]=0,[15]=1,[16]=0,[17]=0,[18]=1,[19]=0,[20]=0,[21]=1,[22]=0,[23]=0,[24]=1,[25]=0,[26]=0,[27]=1,},[2]={[1]=1,[2]=0,[3]=0,[4]=0,[5]=0,[6]=1,[7]=0,[8]=0,[9]=0,[10]=1,[11]=0,[12]=1,[13]=1,[14]=0,[15]=1,[16]=0,[17]=1,[18]=0,[19]=1,[20]=0,[21]=1,[22]=1,[23]=0,[24]=1,[25]=0,[26]=1,[27]=0,[28]=1,},[3]={[1]=1,[2]=1,[3]=1,[4]=1,[5]=0,[6]=1,[7]=1,[8]=1,[9]=0,[10]=1,[11]=0,[12]=1,[13]=0,[14]=1,[15]=1,[16]=0,[17]=1,[18]=0,[19]=1,[20]=0,[21]=1,[22]=0,[23]=1,[24]=1,[25]=0,[26]=0,[27]=1,},[4]={[1]=1,[2]=0,[3]=0,[4]=0,[5]=0,[6]=0,[7]=0,[8]=1,[9]=0,[10]=1,},[5]={[1]=1,[2]=0,[3]=1,[4]=1,[5]=1,[6]=1,[7]=0,[8]=1,[9]=0,[10]=1,[11]=0,[12]=1,[13]=0,[14]=0,[15]=0,[16]=1,[17]=0,[18]=0,[19]=1,[20]=0,[21]=0,[22]=1,[23]=1,[24]=0,[25]=0,[26]=1,[27]=1,[28]=1,},[6]={[1]=1,[2]=0,[3]=0,[4]=0,[5]=1,[6]=0,[7]=0,[8]=0,[9]=0,[10]=1,[11]=0,[12]=1,[13]=1,[14]=0,[15]=1,[16]=1,[17]=0,[18]=1,[19]=0,[20]=1,[21]=0,[22]=0,[23]=1,[24]=0,[25]=0,[26]=1,[27]=1,},[7]={[1]=1,[2]=1,[3]=1,[4]=1,[5]=1,[6]=1,[7]=1,[8]=1,[9]=1,[10]=1,[11]=0,[12]=1,[13]=0,[14]=1,[15]=0,[16]=1,[17]=0,[18]=1,[19]=0,[20]=1,[21]=0,[22]=0,[23]=1,[24]=1,[25]=0,[26]=1,[27]=1,[28]=1,},}, 13, 5) + +parallel.waitForAny( + function() coroutine.yield(); os.pullEvent("key"); coroutine.yield() end, + function() term.setBackgroundColor(colors.black); term.setTextColor(colors.white) while true do term.setCursorPos(18, 14); term.write("Press any key.."); sleep(0.5); term.clearLine(); sleep(0.5) end end +) + +-- The size +local size + +repeat + term.setCursorPos(1, 14) + term.clearLine() + + cwrite("Enter maze size (5-99):") + size = read() + + size = tonumber(size) + if not size then + size = 0 + end +until size > 4 and size < 100 + +-- The generate +local function mazeGen(mx, my) + + --[[ + Format: + + maze.x.y.(1/2/3/4) = true/false + + 1 - top + 2 - bottom + 3 - right + 4 - left + ]]-- + + local maze = {} + for i = 1, mx do + maze[i] = {} + for j = 1, my do + maze[i][j] = {} + for k = 1, 4 do + maze[i][j][k] = true + end + end + end + + local vis = 1 + local tot = mx * my + local curr = {} + curr.x = math.random(1, mx) + curr.y = math.random(1, my) + local stack = {} + + while vis < tot do + local intact = {} + local x = curr.x + local y = curr.y + + if x - 1 >= 1 and maze[x-1][y][1] and maze[x-1][y][2] and maze[x-1][y][3] and maze[x-1][y][4] then -- Check for full cells + intact[#intact+1] = {x-1, y, 1} + end + + if x + 1 <= mx and maze[x+1][y][1] and maze[x+1][y][2] and maze[x+1][y][3] and maze[x+1][y][4] then + intact[#intact+1] = {x+1, y, 2} + end + + if y + 1 <= my and maze[x][y+1][1] and maze[x][y+1][2] and maze[x][y+1][3] and maze[x][y+1][4] then + intact[#intact+1] = {x, y+1, 3} + end + + if y - 1 >= 1 and maze[x][y-1][1] and maze[x][y-1][2] and maze[x][y-1][3] and maze[x][y-1][4] then + intact[#intact+1] = {x, y-1, 4} + end + + if #intact > 0 then + local i = math.random(1, #intact) -- Choose random + + if intact[i][3] == 1 then -- Set intact's attached wall to false + maze[intact[i][1]][intact[i][2]][2] = false + elseif intact[i][3] == 2 then + maze[intact[i][1]][intact[i][2]][1] = false + elseif intact[i][3] == 3 then + maze[intact[i][1]][intact[i][2]][4] = false + elseif intact[i][3] == 4 then + maze[intact[i][1]][intact[i][2]][3] = false + end + + maze[x][y][intact[i][3]] = false -- Set attached wall to false + + vis = vis + 1 -- Increase vis + + stack[#stack+1] = intact[i] -- Add to stack + else + local tmp = table.remove(stack) -- Get last cell + curr.x = tmp[1] + curr.y = tmp[2] + end + end + + return maze +end + +local m = mazeGen(size, size) + +-- The game init +local posx = 2 +local posy = 2 + +local offsetx = 51/2-2 +local offsety = 19/2-2 + +local stime = os.clock() + +-- The maze-to-table +local tab = {} + +for x = 1, size * 2 + 1 do + tab[x] = {} + + for y = 1, size * 2 + 1 do + if x % 2 == 0 and y % 2 == 0 then -- Fill cells (empty) + tab[x][y] = false + elseif x % 2 == 1 and y % 2 == 1 then -- Fill corners (full) + tab[x][y] = true + end + end +end + +for x, tV in ipairs(m) do + for y, v in ipairs(tV) do + tab[x*2-1][y*2] = v[1] -- Up + tab[x*2+1][y*2] = v[2] -- Down + tab[x*2][y*2+1] = v[3] -- Right + tab[x*2][y*2-1] = v[4] -- Left + end +end + +-- The game itself +repeat + -- Print map + term.setBackgroundColor(colors.white) + term.clear() + + if posx == 2 and posy == 2 then + term.setCursorPos(1, 1) + term.setTextColor(colors.black) + print("Controls: WASD") + print("Back to start: R") + print("Quit: Q") + print("Goal: Step on # (It's on bottom right corner)") + print("\nGood Luck!") + end + + --[[ + term.setTextColor(colors.black) + term.setCursorPos(1, 19) + write("X: "..posx.." Y: "..posy) + ]] + + for x, tV in ipairs(tab) do -- Print the map + for y, v in ipairs(tV) do + if offsety+y > 20 then + break + end + + term.setCursorPos(offsetx+x, offsety+y) + + if v then + term.setBackgroundColor(colors.black) + else + term.setBackgroundColor(colors.white) + end + + if offsety+y < 20 and offsety+y > 0 and offsetx+x < 52 and offsetx+x > 0 then + if x == size*2 and y == size*2 then + if term.isColor() then + term.setTextColor(colors.cyan) + end + write("#") + else + write(" ") + end + end + end + + if offsetx+x > 51 then + break + end + end + + term.setCursorPos(51/2, 19/2) + term.setBackgroundColor(colors.white) + + if term.isColor() then + term.setTextColor(colors.red) + else + term.setTextColor(colors.black) + end + + write("X") + + -- Wait for key + + local e, k = os.pullEvent("char") + + if k == "a" and (not tab[posx-1][posy]) then + posx = posx - 1 + offsetx = offsetx + 1 + end + + if k == "d" and (not tab[posx+1][posy]) then + posx = posx + 1 + offsetx = offsetx - 1 + end + + if k == "w" and (not tab[posx][posy-1]) then + posy = posy - 1 + offsety = offsety + 1 + end + + if k == "s" and (not tab[posx][posy+1]) then + posy = posy + 1 + offsety = offsety - 1 + end + + if k == "q" then + break + end + + if k == "r" then + posx = 2 + posy = 2 + + offsetx = 51/2-2 + offsety = 19/2-2 + end +until posx == size*2 and posy == size*2 + +-- The win/loose message +term.setBackgroundColor(colors.white) +term.setTextColor(colors.black) +term.clear() +term.setCursorPos(1, 1) + +if posx == size*2 and posy == size*2 then + local ntime = os.clock() + write("\n") + cprint("Congratulations!") + cprint("You made it in") + cprint(tostring(math.floor((ntime-stime)/60)).." minutes and "..tostring(math.ceil((ntime-stime)%60)).." seconds") + cprint("Size of maze: "..size) +else + write("\n") + cprint("Oh noes D:") +end + +parallel.waitForAny( + function() coroutine.yield(); os.pullEvent("key"); coroutine.yield() end, + function() term.setBackgroundColor(colors.white); term.setTextColor(colors.black) while true do term.setCursorPos(18, 14); term.write("Press any key.."); sleep(0.5); term.clearLine(); sleep(0.5) end end +) + +term.setBackgroundColor(colors.black) +term.setTextColor(colors.white) +term.clear() +term.setCursorPos(1, 1) +cprint(" Maze by JTK. Thanks for playing!") \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/treasure/JTK/maze3d/maze3d b/src/main/resources/assets/computercraft/lua/treasure/JTK/maze3d/maze3d new file mode 100644 index 0000000000..85343aeab0 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/JTK/maze3d/maze3d @@ -0,0 +1,614 @@ +--[[ + Project info: + + Name: Maze 3D + Creator: Jesusthekiller + Language: Lua (CC) + Website: None + License: GNU GPL + License file can be fount at www.jesusthekiller.com/license-gpl.html + + Version: 2.1 +]]-- + +--[[ + Big thanks to Gopher for 3D engine! + http://www.computercraft.info/forums2/index.php?/topic/10786-wolf3d-style-3d-engine-proof-of-concept/page__hl__wolf3d +]]-- + +--[[ + Changelog: + 1.0: + Initial Release + 2.0: + No-HTTP version for Treasure disk + 2.1: + No more temp files! +]]-- + +--[[ + LICENSE: + + Maze 3D + Copyright (c) 2013 Jesusthekiller + + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . +]]-- + +-- The color check +if (not term.isColor()) or turtle then + print("This program has to be run on advanced computer.") + error() +end + +-- The cprint +local function cwrite(msg) + msg = tostring(msg) + local x, y = term.getCursorPos() + term.setCursorPos((51-#msg)/2, y) + write(msg) +end + +local function cprint(msg) + cwrite(msg.."\n") +end + +-- The splash +term.setBackgroundColor(colors.black) +term.setTextColor(colors.white) +term.clear() + +paintutils.drawImage({[1]={[1]=1,[2]=0,[3]=0,[4]=0,[5]=1,[6]=0,[7]=0,[8]=1,[9]=1,[10]=0,[11]=0,[12]=0,[13]=1,[14]=1,[15]=1,[16]=1,[17]=0,[18]=1,[19]=1,[20]=1,[21]=1,},[2]={[1]=1,[2]=1,[3]=0,[4]=1,[5]=1,[6]=0,[7]=1,[8]=0,[9]=0,[10]=1,[11]=0,[12]=0,[13]=0,[14]=0,[15]=0,[16]=1,[17]=0,[18]=1,[19]=0,[20]=0,[21]=0,},[3]={[1]=1,[2]=0,[3]=1,[4]=0,[5]=1,[6]=0,[7]=1,[8]=1,[9]=1,[10]=1,[11]=0,[12]=0,[13]=0,[14]=1,[15]=1,[16]=0,[17]=0,[18]=1,[19]=1,[20]=1,[21]=0,},[4]={[1]=1,[2]=0,[3]=0,[4]=0,[5]=1,[6]=0,[7]=1,[8]=0,[9]=0,[10]=1,[11]=0,[12]=0,[13]=1,[14]=0,[15]=0,[16]=0,[17]=0,[18]=1,[19]=0,[20]=0,[21]=0,},[5]={[1]=1,[2]=0,[3]=0,[4]=0,[5]=1,[6]=0,[7]=1,[8]=0,[9]=0,[10]=1,[11]=0,[12]=0,[13]=1,[14]=1,[15]=1,[16]=1,[17]=0,[18]=1,[19]=1,[20]=1,[21]=1,},[6]={[1]=0,[2]=0,[3]=0,[4]=0,[5]=0,[6]=0,[7]=0,[8]=0,},[7]={[1]=0,[2]=0,[3]=0,[4]=16384,[5]=16384,[6]=16384,[7]=16384,[8]=0,[9]=0,[10]=0,[11]=0,[12]=512,[13]=512,[14]=512,[15]=512,[16]=0,[17]=0,[18]=0,[19]=0,[20]=0,[21]=0,},[8]={[1]=0,[2]=0,[3]=0,[4]=0,[5]=128,[6]=128,[7]=128,[8]=16384,[9]=0,[10]=0,[11]=0,[12]=512,[13]=128,[14]=128,[15]=128,[16]=512,[17]=0,[18]=0,[19]=0,[20]=0,[21]=0,},[9]={[1]=0,[2]=0,[3]=0,[4]=16384,[5]=16384,[6]=16384,[7]=16384,[8]=0,[9]=128,[10]=0,[11]=0,[12]=512,[13]=128,[14]=0,[15]=0,[16]=512,[17]=128,[18]=0,[19]=0,[20]=0,[21]=0,},[10]={[1]=0,[2]=0,[3]=0,[4]=0,[5]=128,[6]=128,[7]=128,[8]=16384,[9]=0,[10]=0,[11]=0,[12]=512,[13]=128,[14]=0,[15]=0,[16]=512,[17]=128,[18]=0,[19]=0,[20]=0,[21]=0,},[11]={[1]=0,[2]=0,[3]=0,[4]=16384,[5]=16384,[6]=16384,[7]=16384,[8]=0,[9]=128,[10]=0,[11]=0,[12]=512,[13]=512,[14]=512,[15]=512,[16]=128,[17]=128,[18]=0,[19]=0,[20]=0,[21]=0,},[12]={[1]=0,[2]=0,[3]=0,[4]=0,[5]=128,[6]=128,[7]=128,[8]=128,[9]=0,[10]=0,[11]=0,[12]=0,[13]=128,[14]=128,[15]=128,[16]=128,},}, 15, 3) + +parallel.waitForAny( + function() coroutine.yield(); os.pullEvent("key"); coroutine.yield() end, + function() term.setBackgroundColor(colors.black); term.setTextColor(colors.white) while true do term.setCursorPos(18, 16); term.write("Press any key.."); sleep(0.5); term.clearLine(); sleep(0.5) end end +) + +-- The size +local size + +repeat + term.setCursorPos(1, 16) + term.clearLine() + + cwrite("Enter maze size (5-99):") + size = read() + + size = tonumber(size) + if not size then + size = 0 + end +until size > 4 and size < 100 + +-- The generate +local function mazeGen(mx, my) + + --[[ + Format: + + maze.x.y.(1/2/3/4) = true/false + + 1 - top + 2 - bottom + 3 - right + 4 - left + ]]-- + + local maze = {} + for i = 1, mx do + maze[i] = {} + for j = 1, my do + maze[i][j] = {} + for k = 1, 4 do + maze[i][j][k] = true + end + end + end + + local vis = 1 + local tot = mx * my + local curr = {} + curr.x = math.random(1, mx) + curr.y = math.random(1, my) + local stack = {} + + while vis < tot do + local intact = {} + local x = curr.x + local y = curr.y + + if x - 1 >= 1 and maze[x-1][y][1] and maze[x-1][y][2] and maze[x-1][y][3] and maze[x-1][y][4] then -- Check for full cells + intact[#intact+1] = {x-1, y, 1} + end + + if x + 1 <= mx and maze[x+1][y][1] and maze[x+1][y][2] and maze[x+1][y][3] and maze[x+1][y][4] then + intact[#intact+1] = {x+1, y, 2} + end + + if y + 1 <= my and maze[x][y+1][1] and maze[x][y+1][2] and maze[x][y+1][3] and maze[x][y+1][4] then + intact[#intact+1] = {x, y+1, 3} + end + + if y - 1 >= 1 and maze[x][y-1][1] and maze[x][y-1][2] and maze[x][y-1][3] and maze[x][y-1][4] then + intact[#intact+1] = {x, y-1, 4} + end + + if #intact > 0 then + local i = math.random(1, #intact) -- Choose random + + if intact[i][3] == 1 then -- Set intact's attached wall to false + maze[intact[i][1]][intact[i][2]][2] = false + elseif intact[i][3] == 2 then + maze[intact[i][1]][intact[i][2]][1] = false + elseif intact[i][3] == 3 then + maze[intact[i][1]][intact[i][2]][4] = false + elseif intact[i][3] == 4 then + maze[intact[i][1]][intact[i][2]][3] = false + end + + maze[x][y][intact[i][3]] = false -- Set attached wall to false + + vis = vis + 1 -- Increase vis + + stack[#stack+1] = intact[i] -- Add to stack + else + local tmp = table.remove(stack) -- Get last cell + curr.x = tmp[1] + curr.y = tmp[2] + end + end + + return maze +end + +local m = mazeGen(size, size) + +-- The game init +local posx = 2 +local posy = 2 + +local offsetx = 51/2-2 +local offsety = 19/2-2 + +-- The maze-to-table +local tab = {} + +for x = 1, size * 2 + 1 do + tab[x] = {} + + for y = 1, size * 2 + 1 do + if x % 2 == 0 and y % 2 == 0 then -- Fill cells (empty) + tab[x][y] = " " + elseif x % 2 == 1 and y % 2 == 1 then -- Fill corners (full) + tab[x][y] = "1" + end + end +end + +for x, tV in ipairs(m) do + for y, v in ipairs(tV) do + if x == size and y == size then + v[1] = v[1] and "2" or " " + v[2] = v[2] and "2" or " " + v[3] = v[3] and "2" or " " + v[4] = v[4] and "2" or " " + tab[x*2-1][y*2] = v[1] -- Up + tab[x*2+1][y*2] = v[2] -- Down + tab[x*2][y*2+1] = v[3] -- Right + tab[x*2][y*2-1] = v[4] -- Left + else + v[1] = v[1] and "1" or " " + v[2] = v[2] and "1" or " " + v[3] = v[3] and "1" or " " + v[4] = v[4] and "1" or " " + tab[x*2-1][y*2] = v[1] -- Up + tab[x*2+1][y*2] = v[2] -- Down + tab[x*2][y*2+1] = v[3] -- Right + tab[x*2][y*2-1] = v[4] -- Left + end + end +end + +local gtab = {} + +for k, v in ipairs(tab) do + gtab[#gtab+1] = table.concat(v) +end + +size = size * 2 + 1 + +--[[ +local template = fs.open("maze3d_template", "r") +local game = fs.open("maze3d_game", "w") + +game.writeLine("local mapH, mapW = "..size..","..size) +game.writeLine("local dir = "..(gtab[2]:sub(3,3) == " " and '0' or '88')) +game.writeLine("local map = {") + +for k, v in ipairs(gtab) do + game.writeLine('"'..v..'",') +end + +game.writeLine("}") + +game.writeLine(template.readAll()) +game.close() +template.close() + +shell.run("maze3d_game") + +fs.delete("maze3d_game") +fs.delete("maze3d_template")]] + +local mapH, mapW = size, size +local dir = gtab[2]:sub(3,3) == " " and '0' or '88' +local map = gtab +local startdir = dir + +------------------------------------------------------------------------------------------------------ +--GOPHER'S CODE HERE + +local buffer=term +local loadedAPI=false + +local stime = os.clock() + +if redirect then + buffer=redirect.createRedirectBuffer() + print("redirect API found, using buffer") +else + local pe=printError + rawset(_G,"printError",error) + local ok, err=pcall(os.loadAPI,"redirect") + if not ok then + print("trying "..shell.dir().."/redirect") + ok,err=pcall(os.loadAPI,shell.dir().."/redirect") + end + if ok then + print("Loaded redirect API, using buffer") + buffer=redirect.createRedirectBuffer() + loadedAPI=true + else + print("redirect API not found or could not be loaded, drawing directly; this may cause flickering.") + end + rawset(_G,"printError",pe) +end + +local colorSchemes = { + {0,8}, --white+gray + {3,11}, --blue + {6,14}, --red + {5,13}, --green + {4,1}, --yellow/orange +} + + +local function cast(cx,cy,angle) + --direction vector + local vx,vy=math.cos(angle), math.sin(angle) + local slope=vy/vx + --next distance, x and y axis points + local ndx, ndy + --steps, distance and block + local dsx, dsy, bsx, bsy + if vx<0 then + local x=(cx%1) + bsx=-1 + ndx=math.sqrt(x*x*(1+slope*slope)) + dsx=math.sqrt((1+slope*slope)) + else + local x=1-(cx%1) + bsx=1 + ndx=math.sqrt(x*x*(1+slope*slope)) + dsx=math.sqrt((1+slope*slope)) + end + + if vy<0 then + local y=(cy%1) + bsy=-1 + ndy=math.sqrt(y*y*(1+1/(slope*slope))) + dsy=math.sqrt((1+1/(slope*slope))) + else + local y=1-(cy%1) + bsy=1 + ndy=math.sqrt(y*y*(1+1/(slope*slope))) + dsy=math.sqrt((1+1/(slope*slope))) + end + + local x,y=math.floor(cx),math.floor(cy) + while x>0 and x<=mapW and y>0 and y<=mapH do + local hitD + local isX + if ndxgx + local left=math.floor(x-radius)gy + + local pushed=false + + if right and map[gy]:sub(gx+1,gx+1)~=" " then + --push left + pushed=true + x=gx+1-radius + elseif left and map[gy]:sub(gx-1,gx-1)~=" " then + --push right + pushed=true + x=gx+radius + end + + if front and map[gy-1]:sub(gx,gx)~=" " then + --push back + pushed=true + y=gy+radius + elseif back and map[gy+1]:sub(gx,gx)~=" " then + --push forward + pushed=true + + + + y=gy+1-radius + end + + --if I wasn't pushed out on any side, I might be hitting a corner + if not pushed then + --square rad + local r2=radius^2 + local pushx,pushy=0,0 + if left then + if front and map[gy-1]:sub(gx-1,gx-1)~=" " then + --check front-left + local dist2=(gx-x)^2+(gy-y)^2 + if dist2= mapW-1 and py >= mapH-1 then + win = true + break + end + end +end + + +if loadedAPI then + os.unloadAPI("redirect") +end + +-- JESUS PART + +-- The win/loose message +term.setBackgroundColor(colors.white) +term.setTextColor(colors.black) +term.clear() +term.setCursorPos(1, 1) + +if win then + local ntime = os.clock() + write("\n") + cprint("Congratulations!") + cprint("You made it in") + cprint(tostring(math.floor((ntime-stime)/60)).." minutes and "..tostring(math.ceil((ntime-stime)%60)).." seconds") + cprint("Size of maze: "..(mapW-1)/2) +sleep(1) +else + write("\n") + cprint("Oh noes D:") +end + + + +parallel.waitForAny( + function() coroutine.yield(); os.pullEvent("key"); coroutine.yield() end, + function() term.setBackgroundColor(colors.white); term.setTextColor(colors.black) while true do term.setCursorPos(18, 14); term.write("Press any key.."); sleep(0.5); term.clearLine(); sleep(0.5) end end +) + +term.setBackgroundColor(colors.black) +term.setTextColor(colors.white) +term.clear() +term.setCursorPos(1, 1) +cprint(" Maze 3D by JTK. Thanks for playing!") +cprint("3D engine by Gopher, He is A-W-E-S-O-M-E") diff --git a/src/main/resources/assets/computercraft/lua/treasure/Lyqyd/nsh/framebuffer b/src/main/resources/assets/computercraft/lua/treasure/Lyqyd/nsh/framebuffer new file mode 100755 index 0000000000..11f13acac4 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/Lyqyd/nsh/framebuffer @@ -0,0 +1,159 @@ +function new(_sizeX, _sizeY, _color) + local redirect = {buffer = {text = {}, textColor = {}, backColor = {}, cursorX = 1, cursorY = 1, cursorBlink = false, curTextColor = "0", curBackColor = "f", sizeX = _sizeX or 51, sizeY = _sizeY or 19, color = _color}} + redirect.write = function(text) + text = tostring(text) + local pos = redirect.buffer.cursorX + if redirect.buffer.cursorY > redirect.buffer.sizeY or redirect.buffer.cursorY < 1 then + redirect.buffer.cursorX = pos + #text + return + end + local writeText + if pos + #text <= 1 then + --skip entirely. + redirect.buffer.cursorX = pos + #text + return + elseif pos < 1 then + --adjust text to fit on screen starting at one. + writeText = string.sub(text, math.abs(redirect.buffer.cursorX) + 2) + redirect.buffer.cursorX = 1 + elseif pos > redirect.buffer.sizeX then + --if we're off the edge to the right, skip entirely. + redirect.buffer.cursorX = pos + #text + return + else + writeText = text + end + local lineText = redirect.buffer.text[redirect.buffer.cursorY] + local lineColor = redirect.buffer.textColor[redirect.buffer.cursorY] + local lineBack = redirect.buffer.backColor[redirect.buffer.cursorY] + local preStop = redirect.buffer.cursorX - 1 + local preStart = math.min(1, preStop) + local postStart = redirect.buffer.cursorX + string.len(writeText) + local postStop = redirect.buffer.sizeX + redirect.buffer.text[redirect.buffer.cursorY] = string.sub(lineText, preStart, preStop)..writeText..string.sub(lineText, postStart, postStop) + redirect.buffer.textColor[redirect.buffer.cursorY] = string.sub(lineColor, preStart, preStop)..string.rep(redirect.buffer.curTextColor, #writeText)..string.sub(lineColor, postStart, postStop) + redirect.buffer.backColor[redirect.buffer.cursorY] = string.sub(lineBack, preStart, preStop)..string.rep(redirect.buffer.curBackColor, #writeText)..string.sub(lineBack, postStart, postStop) + redirect.buffer.cursorX = pos + string.len(text) + end + redirect.clear = function() + for i=1, redirect.buffer.sizeY do + redirect.buffer.text[i] = string.rep(" ", redirect.buffer.sizeX) + redirect.buffer.textColor[i] = string.rep(redirect.buffer.curTextColor, redirect.buffer.sizeX) + redirect.buffer.backColor[i] = string.rep(redirect.buffer.curBackColor, redirect.buffer.sizeX) + end + end + redirect.clearLine = function() + redirect.buffer.text[redirect.buffer.cursorY] = string.rep(" ", redirect.buffer.sizeX) + redirect.buffer.textColor[redirect.buffer.cursorY] = string.rep(redirect.buffer.curTextColor, redirect.buffer.sizeX) + redirect.buffer.backColor[redirect.buffer.cursorY] = string.rep(redirect.buffer.curBackColor, redirect.buffer.sizeX) + end + redirect.getCursorPos = function() + return redirect.buffer.cursorX, redirect.buffer.cursorY + end + redirect.setCursorPos = function(x, y) + redirect.buffer.cursorX = math.floor(tonumber(x)) or redirect.buffer.cursorX + redirect.buffer.cursorY = math.floor(tonumber(y)) or redirect.buffer.cursorY + end + redirect.setCursorBlink = function(b) + redirect.buffer.cursorBlink = b + end + redirect.getSize = function() + return redirect.buffer.sizeX, redirect.buffer.sizeY + end + redirect.scroll = function(n) + n = tonumber(n) or 1 + if n > 0 then + for i = 1, redirect.buffer.sizeY - n do + if redirect.buffer.text[i + n] then + redirect.buffer.text[i] = redirect.buffer.text[i + n] + redirect.buffer.textColor[i] = redirect.buffer.textColor[i + n] + redirect.buffer.backColor[i] = redirect.buffer.backColor[i + n] + end + end + for i = redirect.buffer.sizeY, redirect.buffer.sizeY - n + 1, -1 do + redirect.buffer.text[i] = string.rep(" ", redirect.buffer.sizeX) + redirect.buffer.textColor[i] = string.rep(redirect.buffer.curTextColor, redirect.buffer.sizeX) + redirect.buffer.backColor[i] = string.rep(redirect.buffer.curBackColor, redirect.buffer.sizeX) + end + elseif n < 0 then + for i = redirect.buffer.sizeY, math.abs(n) + 1, -1 do + if redirect.buffer.text[i + n] then + redirect.buffer.text[i] = redirect.buffer.text[i + n] + redirect.buffer.textColor[i] = redirect.buffer.textColor[i + n] + redirect.buffer.backColor[i] = redirect.buffer.backColor[i + n] + end + end + for i = 1, math.abs(n) do + redirect.buffer.text[i] = string.rep(" ", redirect.buffer.sizeX) + redirect.buffer.textColor[i] = string.rep(redirect.buffer.curTextColor, redirect.buffer.sizeX) + redirect.buffer.backColor[i] = string.rep(redirect.buffer.curBackColor, redirect.buffer.sizeX) + end + end + end + redirect.setTextColor = function(clr) + if clr and clr <= 32768 and clr >= 1 then + if redirect.buffer.color then + redirect.buffer.curTextColor = string.format("%x", math.floor(math.log(clr) / math.log(2))) + elseif clr == 1 or clr == 32768 then + redirect.buffer.curTextColor = string.format("%x", math.floor(math.log(clr) / math.log(2))) + else + return nil, "Colour not supported" + end + end + end + redirect.setTextColour = redirect.setTextColor + redirect.setBackgroundColor = function(clr) + if clr and clr <= 32768 and clr >= 1 then + if redirect.buffer.color then + redirect.buffer.curBackColor = string.format("%x", math.floor(math.log(clr) / math.log(2))) + elseif clr == 32768 or clr == 1 then + redirect.buffer.curBackColor = string.format("%x", math.floor(math.log(clr) / math.log(2))) + else + return nil, "Colour not supported" + end + end + end + redirect.setBackgroundColour = redirect.setBackgroundColor + redirect.isColor = function() + return redirect.buffer.color == true + end + redirect.isColour = redirect.isColor + redirect.render = function(inputBuffer) + for i = 1, redirect.buffer.sizeY do + redirect.buffer.text[i] = inputBuffer.text[i] + redirect.buffer.textColor[i] = inputBuffer.textColor[i] + redirect.buffer.backColor[i] = inputBuffer.backColor[i] + end + end + redirect.clear() + return redirect +end + +function draw(buffer, current) + for i=1, buffer.sizeY do + term.setCursorPos(1,i) + if (current and (buffer.text[i] ~= current.text[i] or buffer.textColor[i] ~= current.textColor[i] or buffer.backColor[i] ~= current.backColor[i])) or not current then + local lineEnd = false + local offset = 1 + while not lineEnd do + local textColorString = string.match(string.sub(buffer.textColor[i], offset), string.sub(buffer.textColor[i], offset, offset).."*") + local backColorString = string.match(string.sub(buffer.backColor[i], offset), string.sub(buffer.backColor[i], offset, offset).."*") + term.setTextColor(2 ^ tonumber(string.sub(textColorString, 1, 1), 16)) + term.setBackgroundColor(2 ^ tonumber(string.sub(backColorString, 1, 1), 16)) + term.write(string.sub(buffer.text[i], offset, offset + math.min(#textColorString, #backColorString) - 1)) + offset = offset + math.min(#textColorString, #backColorString) + if offset > buffer.sizeX then lineEnd = true end + end + if current then + current.text[i] = buffer.text[i] + current.textColor[i] = buffer.textColor[i] + current.backColor[i] = buffer.backColor[i] + end + end + end + term.setCursorPos(buffer.cursorX, buffer.cursorY) + term.setTextColor(2 ^ tonumber(buffer.curTextColor, 16)) + term.setBackgroundColor(2 ^ tonumber(buffer.curBackColor, 16)) + term.setCursorBlink(buffer.cursorBlink) + return current +end diff --git a/src/main/resources/assets/computercraft/lua/treasure/Lyqyd/nsh/get b/src/main/resources/assets/computercraft/lua/treasure/Lyqyd/nsh/get new file mode 100755 index 0000000000..5db52061f7 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/Lyqyd/nsh/get @@ -0,0 +1,26 @@ +if not nsh then print("No nsh session!") return end + +local args = {...} + +if #args < 2 then + print("Usage: get ") + print(": any file on the server") + print(": any non-existant file on the client") + return +end + +if fs.exists(args[1]) then + nsh.send("FS:;t="..args[2]) + local message = nsh.receive() + if message == "FR:;ok" then + nsh.send("FH:;"..args[1]) + local handle = io.open(args[1], "r") + if handle then + nsh.send("FD:;t="..handle:read("*a")) + handle:close() + end + nsh.send("FE:;end") + else + print("Client rejected file!") + end +end \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/treasure/Lyqyd/nsh/nsh b/src/main/resources/assets/computercraft/lua/treasure/Lyqyd/nsh/nsh new file mode 100755 index 0000000000..8d1bc35f3f --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/Lyqyd/nsh/nsh @@ -0,0 +1,721 @@ +local args = { ... } + +local connections = {} + +local nshAPI = { + connList = connections +} + +if not framebuffer then if not ((fs.exists("framebuffer") and os.loadAPI("framebuffer")) or (fs.exists("LyqydOS/framebuffer") and os.loadAPI("LyqydOS/framebuffer"))) then print("Couldn't find framebuffer API, using fallback") end end + +local function rawSend(id, msg) + if term.current then + return rednet.send(id, msg, "tror") + else + return rednet.send(id, msg) + end +end + +local function rawRecv(id, timeout) + if type(timeout) == "number" then timeout = os.startTimer(timeout) end + while true do + event = {os.pullEvent()} + if event[1] == "rednet_message" and (id == nil and true or event[2] == id) and (not term.current and true or event[4] == "tror") then + return event[3] + elseif event[1] == "timer" and event[2] == timeout then + return nil + end + end +end + + +nshAPI.getRemoteID = function() + --check for connected clients with matching threads. + for cNum, cInfo in pairs(nshAPI.connList) do + if cInfo.thread == coroutine.running() then + if cNum == "localShell" then + --if we are a client running on the server, return the remote server ID. + if nshAPI.serverNum then + return nshAPI.serverNum + else + return nil + end + end + return cNum + end + end + --client running without local server, return remote server ID. + if nshAPI.serverNum then return nshAPI.serverNum end + return nil +end + +nshAPI.send = function(msg) + local id = nshAPI.getRemoteID() + if id then + return rawSend(id, msg) + end + return nil +end + +nshAPI.receive = function(timeout) + return rawRecv(nshAPI.getRemoteID(), timeout) +end + +nshAPI.getClientCapabilities = function() + if nshAPI.clientCapabilities then return nshAPI.clientCapabilities end + nshAPI.send("SP:;clientCapabilities") + return nshAPI.receive(1) +end + +nshAPI.getRemoteConnections = function() + local remotes = {} + for cNum, cInfo in pairs(nshAPI.connList) do + table.insert(remotes, cNum) + if cInfo.outbound then + table.insert(remotes, cInfo.outbound) + end + end + return remotes +end + +nshAPI.packFile = function(path) + local data = {} + local count = 0 + local handle = io.open(path, "rb") + if handle then + local byte = handle:read() + repeat + data[#data + 1] = byte + count = count + 1 + if count % 1000 == 0 then + os.queueEvent("yield") + os.pullEvent("yield") + end + byte = handle:read() + until not byte + handle:close() + else + return false + end + local outputTable = {} + for i = 1, #data, 3 do + local num1, num2, num3 = data[i], data[i + 1] or 0, data[i + 2] or 0 + table.insert(outputTable, string.char(bit32.band(bit32.arshift(num1, 2), 63))) + table.insert(outputTable, string.char(bit32.bor(bit32.band(bit32.lshift(num1, 4), 48), bit32.band(bit32.arshift(num2, 4), 15)))) + table.insert(outputTable, string.char(bit32.bor(bit32.band(bit32.lshift(num2, 2), 60), bit32.band(bit32.arshift(num3, 6), 3)))) + table.insert(outputTable, string.char(bit32.band(num3, 63))) + end + --mark non-data (invalid) bytes + if #data % 3 == 1 then + outputTable[#outputTable] = "=" + outputTable[#outputTable - 1] = "=" + elseif #data % 3 == 2 then + outputTable[#outputTable] = "=" + end + return table.concat(outputTable, "") +end + +nshAPI.unpackAndSaveFile = function(path, data) + local outputTable = {} + for i=1, #data, 4 do + local char1, char2, char3, char4 = string.byte(string.sub(data, i, i)), string.byte(string.sub(data, i + 1, i + 1)), string.byte(string.sub(data, i + 2, i + 2)), string.byte(string.sub(data, i + 3, i + 3)) + table.insert(outputTable, bit32.band(bit32.bor(bit32.lshift(char1, 2), bit32.arshift(char2, 4)), 255)) + table.insert(outputTable, bit32.band(bit32.bor(bit32.lshift(char2, 4), bit32.arshift(char3, 2)), 255)) + table.insert(outputTable, bit32.band(bit32.bor(bit32.lshift(char3, 6), char4), 255)) + end + --clean invalid bytes if marked + if string.sub(data, #data, #data) == "=" then + table.remove(outputTable) + if string.sub(data, #data - 1, #data - 1) == "=" then + table.remove(outputTable) + end + end + local handle = io.open(path, "wb") + if handle then + for i = 1, #outputTable do + handle:write(outputTable[i]) + if i % 10 == 0 then + os.startTimer(0.1) + os.pullEvent("timer") + end + end + handle:close() + end +end + +local packetConversion = { + query = "SQ", + response = "SR", + data = "SP", + close = "SC", + fileQuery = "FQ", + fileSend = "FS", + fileResponse = "FR", + fileHeader = "FH", + fileData = "FD", + fileEnd = "FE", + textWrite = "TW", + textCursorPos = "TC", + textGetCursorPos = "TG", + textGetSize = "TD", + textInfo = "TI", + textClear = "TE", + textClearLine = "TL", + textScroll = "TS", + textBlink = "TB", + textColor = "TF", + textBackground = "TK", + textIsColor = "TA", + textTable = "TT", + event = "EV", + SQ = "query", + SR = "response", + SP = "data", + SC = "close", + FQ = "fileQuery", + FS = "fileSend", + FR = "fileResponse", + FH = "fileHeader", + FD = "fileData", + FE = "fileEnd", + TW = "textWrite", + TC = "textCursorPos", + TG = "textGetCursorPos", + TD = "textGetSize", + TI = "textInfo", + TE = "textClear", + TL = "textClearLine", + TS = "textScroll", + TB = "textBlink", + TF = "textColor", + TK = "textBackground", + TA = "textIsColor", + TT = "textTable", + EV = "event", +} + +local function openModem() + local modemFound = false + for _, side in ipairs(rs.getSides()) do + if peripheral.getType(side) == "modem" then + if not rednet.isOpen(side) then rednet.open(side) end + modemFound = true + break + end + end + return modemFound +end + +local function send(id, pType, message) + if pType and message then + return rawSend(id, packetConversion[pType]..":;"..message) + end +end + +local function awaitResponse(id, time) + id = tonumber(id) + local listenTimeOut = nil + local messRecv = false + if time then listenTimeOut = os.startTimer(time) end + while not messRecv do + local event, p1, p2 = os.pullEvent() + if event == "timer" and p1 == listenTimeOut then + return false + elseif event == "rednet_message" then + sender, message = p1, p2 + if id == sender and message then + if packetConversion[string.sub(message, 1, 2)] then packetType = packetConversion[string.sub(message, 1, 2)] end + message = string.match(message, ";(.*)") + messRecv = true + end + end + end + return packetType, message +end + +local function processText(conn, pType, value) + if not pType then return false end + if pType == "textWrite" and value then + term.write(value) + elseif pType == "textClear" then + term.clear() + elseif pType == "textClearLine" then + term.clearLine() + elseif pType == "textGetCursorPos" then + local x, y = term.getCursorPos() + send(conn, "textInfo", math.floor(x)..","..math.floor(y)) + elseif pType == "textCursorPos" then + local x, y = string.match(value, "(%-?%d+),(%-?%d+)") + term.setCursorPos(tonumber(x), tonumber(y)) + elseif pType == "textBlink" then + if value == "true" then + term.setCursorBlink(true) + else + term.setCursorBlink(false) + end + elseif pType == "textGetSize" then + x, y = term.getSize() + send(conn, "textInfo", x..","..y) + elseif pType == "textScroll" and value then + term.scroll(tonumber(value)) + elseif pType == "textIsColor" then + send(conn, "textInfo", tostring(term.isColor())) + elseif pType == "textColor" and value then + value = tonumber(value) + if (value == 1 or value == 32768) or term.isColor() then + term.setTextColor(value) + end + elseif pType == "textBackground" and value then + value = tonumber(value) + if (value == 1 or value == 32768) or term.isColor() then + term.setBackgroundColor(value) + end + elseif pType == "textTable" then + local linesTable = textutils.unserialize(value) + for i=1, linesTable.sizeY do + term.setCursorPos(1,i) + local lineEnd = false + local offset = 1 + while not lineEnd do + local textColorString = string.match(string.sub(linesTable.textColor[i], offset), string.sub(linesTable.textColor[i], offset, offset).."*") + local backColorString = string.match(string.sub(linesTable.backColor[i], offset), string.sub(linesTable.backColor[i], offset, offset).."*") + term.setTextColor(2 ^ tonumber(string.sub(textColorString, 1, 1), 16)) + term.setBackgroundColor(2 ^ tonumber(string.sub(backColorString, 1, 1), 16)) + term.write(string.sub(linesTable.text[i], offset, offset + math.min(#textColorString, #backColorString) - 1)) + offset = offset + math.min(#textColorString, #backColorString) + if offset > linesTable.sizeX then lineEnd = true end + end + end + term.setCursorPos(linesTable.cursorX, linesTable.cursorY) + term.setCursorBlink(linesTable.cursorBlink) + end + return +end + +local function textRedirect(id) + local textTable = {} + textTable.id = id + textTable.write = function(text) + return send(textTable.id, "textWrite", text) + end + textTable.clear = function() + return send(textTable.id, "textClear", "nil") + end + textTable.clearLine = function() + return send(textTable.id, "textClearLine", "nil") + end + textTable.getCursorPos = function() + send(textTable.id, "textGetCursorPos", "nil") + local pType, message = awaitResponse(textTable.id, 2) + if pType and pType == "textInfo" then + local x, y = string.match(message, "(%-?%d+),(%-?%d+)") + return tonumber(x), tonumber(y) + end + end + textTable.setCursorPos = function(x, y) + return send(textTable.id, "textCursorPos", math.floor(x)..","..math.floor(y)) + end + textTable.setCursorBlink = function(b) + if b then + return send(textTable.id, "textBlink", "true") + else + return send(textTable.id, "textBlink", "false") + end + end + textTable.getSize = function() + send(textTable.id, "textGetSize", "nil") + local pType, message = awaitResponse(textTable.id, 2) + if pType and pType == "textInfo" then + local x, y = string.match(message, "(%d+),(%d+)") + return tonumber(x), tonumber(y) + end + end + textTable.scroll = function(lines) + return send(textTable.id, "textScroll", lines) + end + textTable.isColor = function() + send(textTable.id, "textIsColor", "nil") + local pType, message = awaitResponse(textTable.id, 2) + if pType and pType == "textInfo" then + if message == "true" then + return true + end + end + return false + end + textTable.isColour = textTable.isColor + textTable.setTextColor = function(color) + return send(textTable.id, "textColor", tostring(color)) + end + textTable.setTextColour = textTable.setTextColor + textTable.setBackgroundColor = function(color) + return send(textTable.id, "textBackground", tostring(color)) + end + textTable.setBackgroundColour = textTable.setBackgroundColor + return textTable +end + +local function getServerID(server) + if tonumber(server) then + return tonumber(server) + elseif term.current then + return rednet.lookup("tror", args[1]) + end +end + +local function resumeThread(conn, event) + local cInfo = connections[conn] + if not connections[conn].filter or event[1] == connections[conn].filter then + connections[conn].filter = nil + local _oldTerm = term.redirect(connections[conn].target) + local passback = {coroutine.resume(connections[conn].thread, table.unpack(event))} + if passback[1] and passback[2] then + connections[conn].filter = passback[2] + end + if coroutine.status(connections[conn].thread) == "dead" then + send(conn, "close", "disconnect") + connections[conn] = nil + end + if _oldTerm then + term.redirect(_oldTerm) + else + term.restore() + end + if connections[conn] and conn ~= "localShell" and framebuffer then + send(conn, "textTable", textutils.serialize(connections[conn].target.buffer)) + end + end +end + +local eventFilter = { + key = true, + char = true, + mouse_click = true, + mouse_drag = true, + mouse_scroll = true, +} + +local function newSession(conn, x, y, color) + local session = {} + local path = "/rom/programs/shell" + if #args >= 2 and shell.resolveProgram(args[2]) then path = shell.resolveProgram(args[2]) end + session.thread = coroutine.create(function() shell.run(path) end) + if framebuffer then + session.target = framebuffer.new(x, y, color) + else + session.target = textRedirect(conn) + end + session.status = "open" + _oldTerm = term.redirect(session.target) + coroutine.resume(session.thread) + if _oldTerm then + term.redirect(_oldTerm) + else + term.restore() + end + if framebuffer then + send(conn, "textTable", textutils.serialize(session.target.buffer)) + end + return session +end + +if #args >= 1 and args[1] == "host" then + _G.nsh = nshAPI + if not openModem() then return end + if term.current then + if args[4] then + rednet.host("tror", args[4]) + elseif os.getComputerLabel() then + rednet.host("tror", os.getComputerLabel()) + else + print("No label or hostname provided!") + return + end + end + local connInfo = {} + connInfo.target = term.current and term.current() or term.native + local path = "/rom/programs/shell" + if #args >= 3 and shell.resolveProgram(args[3]) then path = shell.resolveProgram(args[3]) end + connInfo.thread = coroutine.create(function() shell.run(path) end) + connections.localShell = connInfo + term.clear() + term.setCursorPos(1,1) + coroutine.resume(connections.localShell.thread) + + while true do + event = {os.pullEventRaw()} + if event[1] == "rednet_message" then + if type(event[3]) == "string" and packetConversion[string.sub(event[3], 1, 2)] then + --this is a packet meant for us. + conn = event[2] + packetType = packetConversion[string.sub(event[3], 1, 2)] + message = string.match(event[3], ";(.*)") + if connections[conn] and connections[conn].status == "open" then + if packetType == "event" or string.sub(packetType, 1, 4) == "text" then + local eventTable = {} + if packetType == "event" then + eventTable = textutils.unserialize(message) + else + --we can pass the packet in raw, since this is not an event packet. + eventTable = event + end + resumeThread(conn, eventTable) + elseif packetType == "query" then + local connType, color, x, y = string.match(message, "(%a+):(%a+);(%d+),(%d+)") + if connType == "connect" or (connType == "resume" and (not framebuffer)) then + --reset connection + send(conn, "response", "OK") + connections[conn] = newSession(conn, tonumber(x), tonumber(y), color == "true") + elseif connType == "resume" then + --restore connection + send(conn, "response", "OK") + send(conn, "textTable", textutils.serialize(connections[conn].target.buffer)) + end + elseif packetType == "close" then + connections[conn] = nil + send(conn, "close", "disconnect") + --close connection + else + --we got a packet, have an open connection, but despite it being in the conversion table, don't handle it ourselves. Send it onward. + resumeThread(conn, event) + end + elseif packetType ~= "query" then + --usually, we would send a disconnect here, but this prevents one from hosting nsh and connecting to other computers. Pass these to all shells as well. + for cNum, cInfo in pairs(connections) do + resumeThread(cNum, event) + end + else + --open new connection + send(conn, "response", "OK") + local color, x, y = string.match(message, "connect:(%a+);(%d+),(%d+)") + local connInfo = newSession(conn, tonumber(x), tonumber(y), color == "true") + connections[conn] = connInfo + end + else + --rednet message, but not in the correct format, so pass to all shells. + for cNum, cInfo in pairs(connections) do + resumeThread(cNum, event) + end + end + elseif eventFilter[event[1]] then + --user interaction. + coroutine.resume(connections.localShell.thread, table.unpack(event)) + if coroutine.status(connections.localShell.thread) == "dead" then + for cNum, cInfo in pairs(connections) do + if cNum ~= "localShell" then + send(cNum, "close", "disconnect") + end + end + return + end + else + --dispatch all other events to all shells + for cNum, cInfo in pairs(connections) do + resumeThread(cNum, event) + end + end + end + +elseif #args <= 2 and nsh and nsh.getRemoteID() then + print(nsh.getRemoteID()) + --forwarding mode + local conns = nsh.getRemoteConnections() + for i = 1, #conns do + if conns[i] == serverNum then + print("Cyclic connection refused.") + return + end + end + local fileTransferState = nil + local fileData = nil + local serverNum = getServerID(args[1]) + if not serverNum then + print("Server Not Found") + return + end + send(serverNum, "query", "connect") + local pType, message = awaitResponse(serverNum, 2) + if pType ~= "response" then + print("Connection Failed") + return + else + nsh.connList[nsh.getRemoteID()].outbound = serverNum + term.clear() + term.setCursorPos(1,1) + end + local clientID = nsh.getRemoteID() + local serverID = tonumber(args[1]) + while true do + event = {os.pullEvent()} + if event[1] == "rednet_message" then + if event[2] == clientID or event[2] == serverID then + if event[2] == serverID and string.sub(event[3], 1, 2) == "SC" then break end + rednet.send((event[2] == clientID and serverID or clientID), event[3]) + end + elseif eventFilter[event[1]] then + rednet.send(serverID, "EV:;"..textutils.serialize(event)) + end + end + nsh.connList[nsh.getRemoteID()].outbound = nil + term.clear() + term.setCursorPos(1, 1) + print("Connection closed by server") + +elseif #args >= 1 then --either no server running or we are the local shell on the server. + if not openModem() then return end + local serverNum = getServerID(args[1]) + if not serverNum then + print("Server Not Found") + return + end + if nsh then + local conns = nsh.getRemoteConnections() + for i = 1, #conns do + if conns[i] == serverNum then + print("Connection refused.") + return + end + end + end + local fileTransferState = nil + local fileData = nil + local fileBinaryData = nil + local unpackCo = {} + local color = term.isColor() + local x, y = term.getSize() + if args[2] == "resume" then + send(serverNum, "query", "resume:"..tostring(color)..";"..tostring(x)..","..tostring(y)) + else + send(serverNum, "query", "connect:"..tostring(color)..";"..tostring(x)..","..tostring(y)) + end + local timeout = os.startTimer(2) + while true do + local event = {os.pullEvent()} + if event[1] == "timer" and event[2] == timeout then + print("Connection failed.") + return + elseif event[1] == "rednet_message" and event[2] == serverNum and string.sub(event[3], 1, 2) == "SR" then + if nsh then nshAPI = nsh end + if nshAPI.connList and nshAPI.connList.localShell then nshAPI.connList.localShell.outbound = serverNum end + nshAPI.serverNum = serverNum + nshAPI.clientCapabilities = "-fileTransfer-extensions-" + term.clear() + term.setCursorPos(1,1) + break + end + end + + while true do + event = {os.pullEventRaw()} + if #unpackCo > 0 then + for i = #unpackCo, 1, -1 do + if coroutine.status(unpackCo[i]) ~= "dead" then + coroutine.resume(unpackCo[i], table.unpack(event)) + else + table.remove(unpackCo, i) + end + end + end + if event[1] == "rednet_message" and event[2] == serverNum then + if packetConversion[string.sub(event[3], 1, 2)] then + packetType = packetConversion[string.sub(event[3], 1, 2)] + message = string.match(event[3], ";(.*)") + if string.sub(packetType, 1, 4) == "text" then + processText(serverNum, packetType, message) + elseif packetType == "data" then + if message == "clientCapabilities" then + rednet.send(serverNum, nshAPI.clientCapabilities) + end + elseif packetType == "fileQuery" then + --send a file to the server + local mode, file = string.match(message, "^(%a)=(.*)") + if fs.exists(file) then + send(serverNum, "fileHeader", file) + if mode == "b" then + local fileString = nshAPI.packFile(file) + send(serverNum, "fileData", "b="..fileString) + else + local handle = io.open(file, "r") + if handle then + send(serverNum, "fileData", "t="..handle:read("*a")) + handle:close() + end + end + else + send(serverNum, "fileHeader", "fileNotFound") + end + send(serverNum, "fileEnd", "end") + elseif packetType == "fileSend" then + --receive a file from the server, but don't overwrite existing files. + local mode, file = string.match(message, "^(%a)=(.*)") + if not fs.exists(file) then + fileTransferState = "receive_wait:"..file + send(serverNum, "fileResponse", "ok") + if mode == "b" then + fileBinaryData = "" + fileData = nil + else + fileData = "" + fileBinaryData = nil + end + else + send(serverNum, "fileResponse", "reject") + end + elseif packetType == "fileHeader" then + if message == "fileNotFound" then + fileTransferState = nil + end + elseif packetType == "fileData" then + if fileTransferState and string.match(fileTransferState, "(.-):") == "receive_wait" then + if string.match(message, "^(%a)=") == "b" then + fileBinaryData = fileBinaryData..string.match(message, "^b=(.*)") + else + fileData = fileData..string.match(message, "^t=(.*)") + end + end + elseif packetType == "fileEnd" then + if fileTransferState and string.match(fileTransferState, "(.-):") == "receive_wait" then + if fileBinaryData then + local co = coroutine.create(nshAPI.unpackAndSaveFile) + coroutine.resume(co, string.match(fileTransferState, ":(.*)"), fileBinaryData) + if coroutine.status(co) ~= "dead" then + table.insert(unpackCo, co) + end + elseif fileData then + local handle = io.open(string.match(fileTransferState, ":(.*)"), "w") + if handle then + handle:write(fileData) + handle:close() + end + end + fileTransferState = nil + end + elseif packetType == "close" then + if term.isColor() then + term.setBackgroundColor(colors.black) + term.setTextColor(colors.white) + end + term.clear() + term.setCursorPos(1, 1) + print("Connection closed by server.") + nshAPI.serverNum = nil + if nshAPI.connList and nshAPI.connList.localShell then nshAPI.connList.localShell.outbound = nil end + return + end + end + elseif event[1] == "mouse_click" or event[1] == "mouse_drag" or event[1] == "mouse_scroll" or event[1] == "key" or event[1] == "char" then + --pack up event + send(serverNum, "event", textutils.serialize(event)) + elseif event[1] == "terminate" then + nshAPI.serverNum = nil + if nshAPI.localShell then nshAPI.localShell.outbound = nil end + term.clear() + term.setCursorPos(1, 1) + print("Connection closed locally.") + return + end + end +else + print("Usage: nsh [resume]") + print(" nsh host [remote [local [name]]]") +end \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/treasure/Lyqyd/nsh/put b/src/main/resources/assets/computercraft/lua/treasure/Lyqyd/nsh/put new file mode 100755 index 0000000000..aed5ad0e31 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/Lyqyd/nsh/put @@ -0,0 +1,35 @@ +if not nsh then print("No nsh session!") return end + +local args = {...} + +if #args < 2 then + print("Usage: put ") + print(": any file on the client") + print(": any file on the server") + return +end + +local fileData = "" + +nsh.send("FQ:;t="..args[1]) +local message = nsh.receive() +if message ~= "fileNotFound" then + while true do + message = nsh.receive() + pType = string.sub(message, 1, 2) + if pType == "FD" then + fileData = fileData..string.match(message, "^FD:;t=(.*)") + elseif pType == "FE" then + break + end + end + if #fileData > 0 then + local handle = io.open(args[2], "w") + if handle then + handle:write(fileData) + handle:close() + end + else + print("Empty file not written!") + end +end \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/treasure/TheOriginalBIT/tictactoe/tictactoe b/src/main/resources/assets/computercraft/lua/treasure/TheOriginalBIT/tictactoe/tictactoe new file mode 100644 index 0000000000..8fdfbbf85a --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/TheOriginalBIT/tictactoe/tictactoe @@ -0,0 +1,444 @@ +--[[ +Author: TheOriginalBIT +Version: 1.1.2 +Created: 26 APR 2013 +Last Update: 30 APR 2013 + +License: + +COPYRIGHT NOTICE +Copyright © 2013 Joshua Asbury a.k.a TheOriginalBIT [theoriginalbit@gmail.com] + +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, +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. +-Visible credit is given to the original author. +-The software is distributed in a non-profit way. + +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. +]]-- + +-- make sure that its only a computer terminal that is displaying +local sw, sh = term.getSize() + +if sw ~= 51 and sh ~= 19 then + error("Sorry this game can only run on computers", 0) +end + +-- the wining directions +local winCombos = { + -- horizontal + {1,2,3}, {4,5,6}, {7,8,9}, + -- vertical + {1,4,7}, {2,5,8}, {3,6,9}, + -- diagonal + {1,5,9}, {3,5,7} +} + +local players = {x = 'Player', o = 'The Computer'} +-- whether an AI is active, could be used later to allow SP +local activeAI = true +local currentPlayer +local opposites = { x = 'o', o = 'x' } +local board +local winner +local move +local allowedBgColors = { colors.orange, colors.lightBlue, colors.gray, colors.cyan, colors.purple, colors.blue, colors.brown, colors.green, colors.red, colors.black } +local bg + +local function clear(col) + term.setBackgroundColor(col or colors.black) + term.clear() + term.setCursorPos(1,1) +end + +-- function thanks to Mads... found here: http://www.computercraft.info/forums2/index.php?/topic/11771-print-coloured-text-easily/page__p__105389#entry105389 +local function writeWithFormat(...) + local s = "&0" + for k, v in ipairs(arg) do + s = s .. v + end + s = s .. "&0" + local fields = {} + local lastcolor, lastpos = "0", 0 + for pos, clr in s:gmatch"()&(%x)" do + table.insert(fields, {s:sub(lastpos + 2, pos - 1), lastcolor}) + lastcolor, lastpos = clr , pos + end + for i = 2, #fields do + term.setTextColor(2 ^ (tonumber(fields[i][2], 16))) + write(fields[i][1]) + end +end + +-- modification of Mads' function to get the length of the string without the color modifiers +local function countFormatters(text) + return #(text:gsub("()&(%x)", '')) +end + +-- print a color formatted string in the center of the screen +local function cwriteWithFormat(text, y) + local sw,sh = term.getSize() + local _,cy = term.getCursorPos() + term.setCursorPos(math.floor((sw-countFormatters(text))/2)+(countFormatters(text) % 2 == 0 and 1 or 0), y or cy) + writeWithFormat(text) +end + +-- writes the text at the give location +local function writeAt(text, x, y) + local _,cy = term.getCursorPos() + term.setCursorPos(x or 1, y or cy) + write(text) +end + +local function reset() + bg = allowedBgColors[math.random(1, #allowedBgColors)] + currentPlayer = 'x' + board = {} + for i = 1, 9 do + board[i] = ' ' + end + winner = nil + move = nil +end + +local function search(match) + for _, check in ipairs(winCombos) do + if board[check[1]] == board[check[2]] and board[check[1]] == match and board[check[3]] == ' ' then + return check[3] + elseif board[check[1]] == board[check[3]] and board[check[1]] == match and board[check[2]] == ' ' then + return check[2] + elseif board[check[2]] == board[check[3]] and board[check[2]] == match and board[check[1]] == ' ' then + return check[1] + end + end +end + +local function getAIMove() + -- make it seem like the computer actually has to think about its move + sleep(0.8) + + -- check if AI can win and return the 3rd tile to create a win, if it cannot, check for a human attempt at winning and stop it, if there is none, return a random + return (search(currentPlayer) or search(opposites[currentPlayer])) or math.random(1,9) +end + +local function modread( _mask, _history, _limit ) + term.setCursorBlink(true) + + local input = "" + local pos = 0 + if _mask then + _mask = _mask:sub(1,1) + end + local historyPos = nil + + local sw, sh = term.getSize() + local sx, sy = term.getCursorPos() + + local function redraw( _special ) + local scroll = (sx + pos >= sw and (sx + pos) - sw or 0) + local replace = _special or _mask + term.setCursorPos( sx, sy ) + term.write( replace and string.rep(replace, #input - scroll) or input:sub(scroll + 1) ) + term.setCursorPos( sx + pos - scroll, sy ) + end + + while true do + local event = {os.pullEvent()} + if event[1] == 'char' and (not _limit or #input < _limit) then + input = input:sub(1, pos)..event[2]..input:sub(pos + 1) + pos = pos + 1 + elseif event[1] == 'key' then + if event[2] == keys.enter then + break + elseif event[2] == keys.backspace and pos > 0 then + redraw(' ') + input = input:sub(1, pos - 1)..input:sub(pos + 1) + pos = pos - 1 + elseif event[2] == keys.delete and pos < #input then + redraw(' ') + input = input:sub(1, pos)..input:sub(pos + 2) + elseif event[2] == keys.home then + pos = 0 + elseif event[2] == keys['end'] then + pos = #input + elseif event[2] == keys.left and pos > 0 then + pos = pos - 1 + elseif event[2] == keys.right and pos < #input then + pos = pos + 1 + elseif _history and event[2] == keys.up or event[2] == keys.down then + redraw(' ') + if event[2] == keys.up then + if not historyPos then + historyPos = #_history + elseif historyPos > 1 then + historyPos = historyPos - 1 + end + else + if historyPos ~= nil and historyPos < #_history then + historyPos = historyPos + 1 + elseif historyPos == #_history then + historyPos = nil + end + end + + if historyPos then + input = string.sub(_history[historyPos], 1, _limit) or "" + pos = #input + else + input = "" + pos = 0 + end + end + elseif event[1] == 'mouse_click' then + local xPos, yPos = event[3], event[4] + if xPos == sw and yPos == 1 then + -- exit and make sure to fool the catch-all + error('Terminated', 0) + end + local row = (xPos >= 16 and xPos <= 21) and 1 or (xPos >= 23 and xPos <= 28) and 2 or (xPos >= 30 and xPos <= 35) and 3 or 10 + local col = (yPos >= 4 and yPos <= 6) and 1 or (yPos >= 8 and yPos <= 10) and 2 or (yPos >= 12 and yPos <= 16) and 3 or 10 + local ret = (col - 1) * 3 + row + if ret >= 1 and ret <= 9 then + return ret + end + end + + redraw(_mask) + end + + term.setCursorBlink(false) + term.setCursorPos(1, sy + 1) + + return input +end + +local function getHumanMove() + writeWithFormat('&b[1-9] >>&f ') + return modread() +end + +local function processInput() + -- set the cursor pos ready for the input + term.setCursorPos(3, sh-1) + move = (currentPlayer == 'x' and getHumanMove or getAIMove)() +end + +local function output(msg) + -- if the player is not an AI, print the error + if not (activeAI and currentPlayer == 'o') then + term.setCursorPos(3, sh-1) + writeWithFormat('&eERROR >> '..msg) + sleep(2) + end +end + +local function checkMove() + -- if the user typed exit + if not tonumber(move) and move:lower() == 'exit' then + -- exit and make sure to fool the catch-all + error('Terminated', 0) + end + + -- attempt to convert the move to a number + local nmove = tonumber(move) + -- if it wasn't a number + if not nmove then + output(tostring(move)..' is not a number between 1 and 9!') + return false + end + -- if it is not within range of the board + if nmove > 9 or nmove < 1 then + output('Must be a number between 1 and 9!') + return false + end + -- if the space is already taken + if board[nmove] ~= ' ' then + output('Position already taken!') + return false + end + -- keep the conversion + move = tonumber(move) + return true +end + +local function checkWin() + for _, check in ipairs(winCombos) do + if board[check[1]] ~= ' ' and board[check[1]] == board[check[2]] and board[check[1]] == board[check[3]] then + return board[check[1]] + end + end + + for _, tile in ipairs(board) do + if tile == ' ' then + return nil + end + end + + return 'tie' +end + +local function update() + if checkMove() then + board[move] = currentPlayer + winner = checkWin() + + currentPlayer = currentPlayer == 'x' and 'o' or 'x' + end +end + +local function render() + -- clear the screen light blue + clear(bg) + + -- draw the ascii borders + term.setTextColor(colors.white) + for i = 2, sh-1 do + writeAt('|', 1, i) + writeAt('|', sw, i) + end + writeAt('+'..string.rep('-', sw-2)..'+', 1, 1) + writeAt('+'..string.rep('-', sw-2)..'+', 1, 3) + writeAt('+'..string.rep('-', sw-2)..'+', 1, sh-2) + writeAt('+'..string.rep('-', sw-2)..'+', 1, sh) + + if term.isColor and term.isColor() then + term.setCursorPos(sw, 1) + term.setBackgroundColor(colors.red) + term.setTextColor(colors.black) + writeWithFormat('X') + end + + -- set our colours + term.setBackgroundColor(colors.white) + term.setTextColor(colors.black) + + -- clear an area for the title + writeAt(string.rep(' ', sw-2), 2, 2) + writeAt('Tic-Tac-Toe!', sw/2-5, 2) + + -- clear an area for the input + writeAt(string.rep(' ', sw-2), 2, sh-1) + + -- clear the area for the board + local h = sh - 6 + for i = 0, h - 1 do + writeAt(string.rep(' ', sw - 2), 2, 4+i) + end + + -- draw the grid + for i = 0, 10 do + writeAt(((i == 3 or i == 7) and '------+------+------' or ' | | '), 16, i + 4) + end + + -- draw the first line moves + for i = 1, 3 do + if board[i] ~= ' ' then + writeAt((board[i] == 'x' and '\\/' or '/\\'), 18+((i-1)*7), 5) + writeAt((board[i] == 'x' and '/\\' or '\\/'), 18+((i-1)*7), 6) + end + end + -- draw the second line moves + for i = 1, 3 do + if board[i + 3] ~= ' ' then + writeAt((board[i + 3] == 'x' and '\\/' or '/\\'), 18+((i-1)*7), 9) + writeAt((board[i + 3] == 'x' and '/\\' or '\\/'), 18+((i-1)*7), 10) + end + end + -- draw the third line moves + for i = 1, 3 do + if board[i + 6] ~= ' ' then + writeAt((board[i + 6] == 'x' and '\\/' or '/\\'), 18+((i-1)*7), 13) + writeAt((board[i + 6] == 'x' and '/\\' or '\\/'), 18+((i-1)*7), 14) + end + end + + -- draw the current player + term.setCursorPos(3, sh - 3) + if not winner then + writeWithFormat('&bCurrent Player: &f'..players[currentPlayer]) + end +end + +local function main(arc, argv) + clear() + writeWithFormat('&0Welcome to CCTicTacToe by &8TheOriginal&3BIT&0\n\nPlease enter your name\n\n&4>>&0 ') + players.x = read() or 'Player' + + -- setup the game, will later be used to + reset() + + -- initial render + render() + + -- game loop + while not winner do + processInput() + update() + render() + + -- highly unorthodox having something that isn't in input, update, render! + -- print the winner info + if winner then + writeWithFormat('&f'..(winner == 'tie' and 'There was no winner :(&f' or players[winner]..'&f is the winner!')) + -- allow the player to start a new game or quit + writeAt("Press 'R' to play again, 'Q' to quit...", 3, sh - 1) + while true do + local _, k = os.pullEvent('key') + if k == 16 then + break + elseif k == 19 then + reset() -- reset the game + render() -- render the new game ready to wait for input + break + end + end + os.pullEvent() -- remove the char event that would be waiting + end + end + + return true +end + +-- create a terminal object with a non-advanced computer safe version of setting colors +local oldTermObj = term.current() +local termObj = { + setTextColor = function(n) if term.isColor and term.isColor() then local ok, err = pcall(oldTermObj.setTextColor , n) if not ok then error(err, 2) end end end, + setBackgroundColor = function(n) if term.isColor and term.isColor() then local ok, err = pcall(oldTermObj.setBackgroundColor , n) if not ok then error(err, 2) end end end +} +-- also override the English spelling of the colour functions +termObj.setTextColour = termObj.setTextColor +termObj.setBackgroundColour = termObj.setBackgroundColor + +-- make the terminal object refer to the native terminal for every other function +termObj.__index = oldTermObj +setmetatable(termObj, termObj) + +-- redirect the terminal to the new object +term.redirect(termObj) + +-- run the program +local ok, err = pcall(main, #{...}, {...}) + +-- catch-all +if not ok and err ~= 'Terminated' then + clear() + print('Error in runtime!') + print(err) + sleep(5) +end + +-- print thank you message +clear() +cwriteWithFormat('&4Thank you for playing CCTicTacToe v1.0', 1) +cwriteWithFormat('&4By &8TheOriginal&3BIT\n', 2) + +-- restore the default terminal object +term.redirect( oldTermObj ) \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/treasure/dan200/alongtimeago/alongtimeago b/src/main/resources/assets/computercraft/lua/treasure/dan200/alongtimeago/alongtimeago new file mode 100644 index 0000000000..bf126850da --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/dan200/alongtimeago/alongtimeago @@ -0,0 +1,47 @@ + +local filmText = '2\n\n\n\n\n\n\n\n\n\n\n\n\n\n15\n\n\n\n\n WWW.ASCIIMATION.CO.NZ\n\n\n presents\n\n\n\n\n\n6\n\n\n\n\n\n\n\n\n\n\n\n\n\n1\n .......... @@@@@ @@@@@.......\n ......... @ @ @ @.......\n ........ @@@ @ @........\n ....... @@ @ @ .......\n ...... @@@@@@@ @@@@@ th ......\n ..... ----------------------- .....\n .... C E N T U R Y ....\n ... ----------------------- ...\n .. @@@@@ @@@@@ @ @ @@@@@ ..\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n .......... @@@@@ @@@@@.........\n ......... @ @ @ @.........\n ........ @@@ @ @ .........\n ....... @@ @ @ .........\n ....... @@@@@@@ @@@@@ th .......\n ..... ----------------------- ......\n .... C E N T U R Y ....\n ... ----------------------- ...\n .. @@@@@ @@@@@ @ @ @@@@@ ..\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n .......... @@@@@ @@@@@ ..........\n ......... @ @ @ @ .........\n ........ @@@ @ @ .........\n ....... @@ @ @ ........\n ....... @@@@@@@ @@@@@ th .......\n ..... ----------------------- .......\n .... C E N T U R Y .....\n .. ----------------------- ....\n .. @@@@@ @@@@@ @ @ @@@@@ ..\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n .......... @@@@@ @@@@@ ..........\n ......... @ @ @ @ .........\n ......... @@@ @ @ ........\n ....... @@ @ @ .......\n ..... @@@@@@@ @@@@@ th .......\n ..... ----------------------- ......\n ... C E N T U R Y .....\n .. ----------------------- ....\n .. @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n ......... @@@@@ @@@@@ ..........\n ......... @ @ @ @ .........\n ......... @@@ @ @ ........\n ....... @@ @ @ ........\n ...... @@@@@@@ @@@@@ th .......\n ..... ----------------------- ......\n ... C E N T U R Y .....\n .. ----------------------- ...\n .. @@@@@ @@@@@ @ @ @@@@@ ..\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n ......... @@@@@ @@@@@ ..........\n ......... @ @ @ @ ..........\n ........ @@@ @ @ .........\n ....... @@ @ @ .......\n ...... @@@@@@@ @@@@@ th ......\n ..... ----------------------- .....\n .... C E N T U R Y ....\n ... ----------------------- ..\n .. @@@@@ @@@@@ @ @ @@@@@ ..\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n .......... @@@@@ @@@@@ .........\n ......... @ @ @ @ .........\n ......... @@@ @ @ ........\n ....... @@ @ @ ......\n ...... @@@@@@@ @@@@@ th ......\n ...... ----------------------- ....\n ..... C E N T U R Y ...\n .... ----------------------- ...\n .. @@@@@ @@@@@ @ @ @@@@@ ..\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n .......... @@@@@ @@@@@ ...........\n ......... @ @ @ @ ..........\n ........ @@@ @ @ ........\n ....... @@ @ @ ........\n ...... @@@@@@@ @@@@@ th .......\n ..... ----------------------- .....\n .... C E N T U R Y ....\n ... ----------------------- ...\n .. @@@@@ @@@@@ @ @ @@@@@ ..\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n ........... @@@@@ @@@@@ ...........\n .......... @ @ @ @ ..........\n ......... @@@ @ @ .........\n ........ @@ @ @ ........\n ...... @@@@@@@ @@@@@ th ........\n ..... ----------------------- .......\n .... C E N T U R Y .....\n ... ----------------------- ....\n .. @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n ........... @@@@@ @@@@@ ...........\n .......... @ @ @ @ ..........\n ........ @@@ @ @ ..........\n ....... @@ @ @ .........\n ...... @@@@@@@ @@@@@ th ........\n ..... ----------------------- .......\n .... C E N T U R Y .......\n ... ----------------------- .....\n .. @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n ........... @@@@@ @@@@@ .........\n .......... @ @ @ @ .........\n ......... @@@ @ @ .........\n ....... @@ @ @ ........\n ...... @@@@@@@ @@@@@ th ........\n .... ----------------------- ........\n ... C E N T U R Y .......\n .. ----------------------- .....\n .. @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n ........... @@@@@ @@@@@ ......\n .......... @ @ @ @ .......\n ........ @@@ @ @ ........\n ....... @@ @ @ .........\n ...... @@@@@@@ @@@@@ th ........\n ..... ----------------------- ........\n .... C E N T U R Y .......\n ... ----------------------- .....\n .. @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n ............. @@@@@ @@@@@ ......\n ........... @ @ @ @ .......\n .......... @@@ @ @ ........\n ......... @@ @ @ .........\n ........ @@@@@@@ @@@@@ th ........\n ....... ----------------------- ........\n ..... C E N T U R Y .......\n .... ----------------------- .....\n ... @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n............ @@@@@ @@@@@ ......\n ........... @ @ @ @ .......\n .......... @@@ @ @ ........\n ......... @@ @ @ .........\n ........ @@@@@@@ @@@@@ th ........\n ........ ----------------------- ........\n ....... C E N T U R Y .......\n ..... ----------------------- .....\n ... @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n.......... @@@@@ @@@@@ .......\n.......... @ @ @ @ ........\n .......... @@@ @ @ ........\n ........ @@ @ @ ........\n ........ @@@@@@@ @@@@@ th ........\n ....... ----------------------- .......\n ...... C E N T U R Y ......\n .... ----------------------- .....\n ... @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n....... @@@@@ @@@@@ .........\n........ @ @ @ @ .........\n......... @@@ @ @ .........\n ......... @@ @ @ ........\n ....... @@@@@@@ @@@@@ th ........\n ....... ----------------------- ......\n ...... C E N T U R Y .....\n ..... ----------------------- ....\n ... @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n..... @@@@@ @@@@@ ........\n...... @ @ @ @ ........\n....... @@@ @ @ ........\n........ @@ @ @ ........\n ........ @@@@@@@ @@@@@ th .......\n ....... ----------------------- .....\n ...... C E N T U R Y .....\n ..... ----------------------- ....\n ... @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n..... @@@@@ @@@@@ ...........\n...... @ @ @ @ ..........\n....... @@@ @ @ .........\n........ @@ @ @ ........\n ........ @@@@@@@ @@@@@ th .......\n ....... ----------------------- ......\n ...... C E N T U R Y .....\n ..... ----------------------- ....\n ... @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n..... @@@@@ @@@@@ ...........\n...... @ @ @ @ ..........\n....... @@@ @ @ .........\n........ @@ @ @ .......\n ........ @@@@@@@ @@@@@ th ......\n ....... ----------------------- ......\n ...... C E N T U R Y ....\n ..... ----------------------- ....\n ... @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n..... @@@@@ @@@@@ ..........\n...... @ @ @ @ ..........\n....... @@@ @ @ ........\n........ @@ @ @ .......\n ........ @@@@@@@ @@@@@ th ......\n ....... ----------------------- ......\n ...... C E N T U R Y ....\n ..... ----------------------- ....\n ... @@@@@ @@@@@ @ @ @@@@@ ..\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n....... @@@@@ @@@@@ ..........\n........ @ @ @ @ .........\n........ @@@ @ @ .........\n ........ @@ @ @ ........\n ........ @@@@@@@ @@@@@ th .......\n ....... ----------------------- ......\n ..... C E N T U R Y ....\n .... ----------------------- ...\n ... @@@@@ @@@@@ @ @ @@@@@ ..\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n......... @@@@@ @@@@@ ...........\n......... @ @ @ @ ...........\n ......... @@@ @ @ ..........\n ........ @@ @ @ .........\n ........ @@@@@@@ @@@@@ th .......\n ...... ----------------------- ......\n ..... C E N T U R Y ....\n .... ----------------------- ...\n ... @@@@@ @@@@@ @ @ @@@@@ ..\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n ........ @@@@@ @@@@@ ...........\n ........ @ @ @ @ ...........\n ....... @@@ @ @ ..........\n ........ @@ @ @ ........\n ...... @@@@@@@ @@@@@ th .......\n ..... ----------------------- ......\n .... C E N T U R Y .....\n ... ----------------------- ....\n ... @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n ......... @@@@@ @@@@@ ...........\n ......... @ @ @ @ ...........\n ........ @@@ @ @ ..........\n ....... @@ @ @ .........\n ...... @@@@@@@ @@@@@ th .......\n ..... ----------------------- ......\n .... C E N T U R Y .....\n ... ----------------------- ....\n .. @@@@@ @@@@@ @ @ @@@@@ ..\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n ......... @@@@@ @@@@@...........\n ......... @ @ @ @..........\n ........ @@@ @ @...........\n ....... @@ @ @ .........\n ...... @@@@@@@ @@@@@ th .......\n ..... ----------------------- ......\n .... C E N T U R Y .....\n ... ----------------------- ....\n .. @@@@@ @@@@@ @ @ @@@@@ ..\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n .......... @@@@@ @@@@@........\n ......... @ @ @ @........\n ........ @@@ @ @.........\n ....... @@ @ @ ........\n ...... @@@@@@@ @@@@@ th .......\n ..... ----------------------- ......\n .... C E N T U R Y .....\n ... ----------------------- ....\n .. @@@@@ @@@@@ @ @ @@@@@ ..\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n .......... @@@@@ @@@@@.......\n ......... @ @ @ @.......\n ........ @@@ @ @........\n ...... @@ @ @ .......\n ..... @@@@@@@ @@@@@ th ......\n ..... ----------------------- .....\n .... C E N T U R Y ....\n ... ----------------------- ...\n .. @@@@@ @@@@@ @ @ @@@@@ ..\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n ......... @@@@@ @@@@@.........\n ........ @ @ @ @.........\n ....... @@@ @ @ .........\n ...... @@ @ @ .........\n ...... @@@@@@@ @@@@@ th .......\n .... ----------------------- ......\n ... C E N T U R Y ....\n ... ----------------------- ...\n .. @@@@@ @@@@@ @ @ @@@@@ ..\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n .......... @@@@@ @@@@@ ..........\n ......... @ @ @ @ .........\n ........ @@@ @ @ .........\n ....... @@ @ @ ........\n ....... @@@@@@@ @@@@@ th .......\n ..... ----------------------- .......\n .... C E N T U R Y .....\n .. ----------------------- ....\n .. @@@@@ @@@@@ @ @ @@@@@ ..\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n .......... @@@@@ @@@@@ ..........\n ......... @ @ @ @ .........\n ......... @@@ @ @ ........\n ....... @@ @ @ .......\n ..... @@@@@@@ @@@@@ th .......\n ..... ----------------------- ......\n ... C E N T U R Y .....\n .. ----------------------- ....\n .. @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n ......... @@@@@ @@@@@ ..........\n ......... @ @ @ @ .........\n ......... @@@ @ @ ........\n ....... @@ @ @ ........\n ...... @@@@@@@ @@@@@ th .......\n ..... ----------------------- ......\n ... C E N T U R Y .....\n .. ----------------------- ...\n .. @@@@@ @@@@@ @ @ @@@@@ ..\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n ......... @@@@@ @@@@@ ..........\n ......... @ @ @ @ ..........\n ........ @@@ @ @ .........\n ....... @@ @ @ .......\n ...... @@@@@@@ @@@@@ th ......\n ..... ----------------------- .....\n .... C E N T U R Y ....\n ... ----------------------- ..\n .. @@@@@ @@@@@ @ @ @@@@@ ..\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n .......... @@@@@ @@@@@ .........\n ......... @ @ @ @ .........\n ......... @@@ @ @ ........\n ....... @@ @ @ ......\n ...... @@@@@@@ @@@@@ th ......\n ...... ----------------------- ....\n ..... C E N T U R Y ...\n .... ----------------------- ...\n .. @@@@@ @@@@@ @ @ @@@@@ ..\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n .......... @@@@@ @@@@@ ...........\n ......... @ @ @ @ ..........\n ........ @@@ @ @ ........\n ....... @@ @ @ ........\n ...... @@@@@@@ @@@@@ th .......\n ..... ----------------------- .....\n .... C E N T U R Y ....\n ... ----------------------- ...\n .. @@@@@ @@@@@ @ @ @@@@@ ..\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n ........... @@@@@ @@@@@ ...........\n .......... @ @ @ @ ..........\n ......... @@@ @ @ .........\n ........ @@ @ @ ........\n ...... @@@@@@@ @@@@@ th ........\n ..... ----------------------- .......\n .... C E N T U R Y .....\n ... ----------------------- ....\n .. @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n ........... @@@@@ @@@@@ ...........\n .......... @ @ @ @ ..........\n ........ @@@ @ @ ..........\n ....... @@ @ @ .........\n ...... @@@@@@@ @@@@@ th ........\n ..... ----------------------- .......\n .... C E N T U R Y .......\n ... ----------------------- .....\n .. @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n ........... @@@@@ @@@@@ .........\n .......... @ @ @ @ .........\n ......... @@@ @ @ .........\n ....... @@ @ @ ........\n ...... @@@@@@@ @@@@@ th ........\n .... ----------------------- ........\n ... C E N T U R Y .......\n .. ----------------------- .....\n .. @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n ........... @@@@@ @@@@@ ......\n .......... @ @ @ @ .......\n ........ @@@ @ @ ........\n ....... @@ @ @ .........\n ...... @@@@@@@ @@@@@ th ........\n ..... ----------------------- ........\n .... C E N T U R Y .......\n ... ----------------------- .....\n .. @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n ............. @@@@@ @@@@@ ......\n ........... @ @ @ @ .......\n .......... @@@ @ @ ........\n ......... @@ @ @ .........\n ........ @@@@@@@ @@@@@ th ........\n ....... ----------------------- ........\n ..... C E N T U R Y .......\n .... ----------------------- .....\n ... @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n............ @@@@@ @@@@@ ......\n ........... @ @ @ @ .......\n .......... @@@ @ @ ........\n ......... @@ @ @ .........\n ........ @@@@@@@ @@@@@ th ........\n ........ ----------------------- ........\n ....... C E N T U R Y .......\n ..... ----------------------- .....\n ... @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n.......... @@@@@ @@@@@ .......\n.......... @ @ @ @ ........\n .......... @@@ @ @ ........\n ........ @@ @ @ ........\n ........ @@@@@@@ @@@@@ th ........\n ....... ----------------------- .......\n ...... C E N T U R Y ......\n .... ----------------------- .....\n ... @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n....... @@@@@ @@@@@ .........\n........ @ @ @ @ .........\n......... @@@ @ @ .........\n ......... @@ @ @ ........\n ....... @@@@@@@ @@@@@ th ........\n ....... ----------------------- ......\n ...... C E N T U R Y .....\n ..... ----------------------- ....\n ... @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n..... @@@@@ @@@@@ ........\n...... @ @ @ @ ........\n....... @@@ @ @ ........\n........ @@ @ @ ........\n ........ @@@@@@@ @@@@@ th .......\n ....... ----------------------- .....\n ...... C E N T U R Y .....\n ..... ----------------------- ....\n ... @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n1\n..... @@@@@ @@@@@ ...........\n...... @ @ @ @ ..........\n....... @@@ @ @ .........\n........ @@ @ @ ........\n ........ @@@@@@@ @@@@@ th .......\n ....... ----------------------- ......\n ...... C E N T U R Y .....\n ..... ----------------------- ....\n ... @@@@@ @@@@@ @ @ @@@@@ ...\n == @ @ @ @ @ ==\n __||__ @ @@@@ @ @ __||__\n | | @ @ @ @ @ | |\n_________|______|_____ @ @@@@@ @ @ @ _____|______|_________\n10\n\n\n\n\n\n\n\n\n\n\n\n\n\n30\n\n\n\n\n A long time ago in a galaxy far,\n far away....\n\n\n\n\n\n\n\n9\n\n\n\n\n\n\n\n\n\n\n\n\n\n40\n\n 8888888888 888 88888\n 88 88 88 88 88 88\n 8888 88 88 88 88888\n 88 88 888888888 88 88\n 88888888 88 88 88 88 888888\n\n 88 88 88 888 88888 888888\n 88 88 88 88 88 88 88 88\n 88 8888 88 88 88 88888 8888\n 888 888 888888888 88 88 88\n 88 88 88 88 88 8888888\n\n9\n\n\n\n\n\n\n\n\n\n\n\n\n\n8\n\n\n\n\n\n\n\n\n\n\n\n\n E p i s o d e I V\n8\n\n\n\n\n\n\n\n\n\n\n\n E p i s o d e I V\n\n8\n\n\n\n\n\n\n\n\n\n\n E p i s o d e I V\n\n\n8\n\n\n\n\n\n\n\n\n\n E p i s o d e I V\n\n\n A N E W H O P E\n8\n\n\n\n\n\n\n\n\n E p i s o d e I V\n\n\n A N E W H O P E\n\n8\n\n\n\n\n\n\n\n E p i s o d e I V\n\n\n A N E W H O P E\n\n\n8\n\n\n\n\n\n\n E p i s o d e I V\n\n\n A N E W H O P E\n\n\n\n8\n\n\n\n\n\n E p i s o d e I V\n\n\n A N E W H O P E\n\n\n I t i s a p e r i o d o f c i v i l w a r.\n\n8\n\n\n\n\n E p i s o d e I V\n\n\n A N E W H O P E\n\n\n I t i s a p e r i o d o f c i v i l w a r.\n\n\n8\n\n\n\n E p i s o d e I V\n\n\n A N E W H O P E\n\n\n I t i s a p e r i o d o f c i v i l w a r.\n\n R e b e l s p a c e s h i p s , s t r i k i n g\n\n8\n\n\n E p i s o d e I V\n\n\n A N E W H O P E\n\n\n I t i s a p e r i o d o f c i v i l w a r.\n\n R e b e l s p a c e s h i p s , s t r i k i n g\n\n f r o m a h i d d e n b a s e , h a v e w o n\n8\n\n E p i s o d e I V\n\n\n A N E W H O P E\n\n\n I t i s a p e r i o d o f c i v i l w a r.\n\n R e b e l s p a c e s h i p s , s t r i k i n g\n\n f r o m a h i d d e n b a s e , h a v e w o n\n\n8\n E p i s o d e I V\n\n\n A N E W H O P E\n\n\n I t i s a p e r i o d o f c i v i l w a r.\n\n R e b e l s p a c e s h i p s , s t r i k i n g\n\n f r o m a h i d d e n b a s e , h a v e w o n\n\n t h e i r f i r s t v i c t o r y a g a i n s t\n8\n\n\n A N E W H O P E\n\n\n I t i s a p e r i o d o f c i v i l w a r.\n\n R e b e l s p a c e s h i p s , s t r i k i n g\n\n f r o m a h i d d e n b a s e , h a v e w o n\n\n t h e i r f i r s t v i c t o r y a g a i n s t\n\n8\n\n A N E W H O P E\n\n\n I t i s a p e r i o d o f c i v i l w a r.\n\n R e b e l s p a c e s h i p s , s t r i k i n g\n\n f r o m a h i d d e n b a s e , h a v e w o n\n\n t h e i r f i r s t v i c t o r y a g a i n s t\n\n t h e e v i l G a l a c t i c E m p i r e.\n8\n A N E W H O P E\n\n\n I t i s a p e r i o d o f c i v i l w a r.\n\n R e b e l s p a c e s h i p s , s t r i k i n g\n\n f r o m a h i d d e n b a s e , h a v e w o n\n\n t h e i r f i r s t v i c t o r y a g a i n s t\n\n t h e e v i l G a l a c t i c E m p i r e.\n\n8\n\n\n I t i s a p e r i o d o f c i v i l w a r.\n\n R e b e l s p a c e s h i p s , s t r i k i n g\n\n f r o m a h i d d e n b a s e , h a v e w o n\n\n t h e i r f i r s t v i c t o r y a g a i n s t\n\n t h e e v i l G a l a c t i c E m p i r e.\n\n\n8\n\n I t i s a p e r i o d o f c i v i l w a r.\n\n R e b e l s p a c e s h i p s , s t r i k i n g\n\n f r o m a h i d d e n b a s e , h a v e w o n\n\n t h e i r f i r s t v i c t o r y a g a i n s t\n\n t h e e v i l G a l a c t i c E m p i r e.\n\n\n\n8\n I t i s a p e r i o d o f c i v i l w a r.\n\n R e b e l s p a c e s h i p s , s t r i k i n g\n\n f r o m a h i d d e n b a s e , h a v e w o n\n\n t h e i r f i r s t v i c t o r y a g a i n s t\n\n t h e e v i l G a l a c t i c E m p i r e.\n\n\n D u r i n g t h e b a t t l e , R e b e l\n\n8\n\n R e b e l s p a c e s h i p s , s t r i k i n g\n\n f r o m a h i d d e n b a s e , h a v e w o n\n\n t h e i r f i r s t v i c t o r y a g a i n s t\n\n t h e e v i l G a l a c t i c E m p i r e.\n\n\n D u r i n g t h e b a t t l e , R e b e l\n\n\n8\n R e b e l s p a c e s h i p s , s t r i k i n g\n\n f r o m a h i d d e n b a s e , h a v e w o n\n\n t h e i r f i r s t v i c t o r y a g a i n s t\n\n t h e e v i l G a l a c t i c E m p i r e.\n\n\n D u r i n g t h e b a t t l e , R e b e l\n\n s p i e s m a n a g e d to s t e a l s e c r e t\n\n8\n\n f r o m a h i d d e n b a s e , h a v e w o n\n\n t h e i r f i r s t v i c t o r y a g a i n s t\n\n t h e e v i l G a l a c t i c E m p i r e.\n\n\n D u r i n g t h e b a t t l e , R e b e l\n\n s p i e s m a n a g e d to s t e a l s e c r e t\n\n\n8\n f r o m a h i d d e n b a s e , h a v e w o n\n\n t h e i r f i r s t v i c t o r y a g a i n s t\n\n t h e e v i l G a l a c t i c E m p i r e.\n\n\n D u r i n g t h e b a t t l e , R e b e l\n\n s p i e s m a n a g e d to s t e a l s e c r e t\n\n p l a n s t o t h e E m p i r e \' s\n\n8\n\n t h e i r f i r s t v i c t o r y a g a i n s t\n\n t h e e v i l G a l a c t i c E m p i r e.\n\n\n D u r i n g t h e b a t t l e , R e b e l\n\n s p i e s m a n a g e d to s t e a l s e c r e t\n\n p l a n s t o t h e E m p i r e \' s\n\n\n8\n t h e i r f i r s t v i c t o r y a g a i n s t\n\n t h e e v i l G a l a c t i c E m p i r e.\n\n\n D u r i n g t h e b a t t l e , R e b e l\n\n s p i e s m a n a g e d to s t e a l s e c r e t\n\n p l a n s t o t h e E m p i r e \' s\n\n u l t i m a t e w e a p o n , t h e D E A T H\n\n8\n\n t h e e v i l G a l a c t i c E m p i r e.\n\n\n D u r i n g t h e b a t t l e , R e b e l\n\n s p i e s m a n a g e d to s t e a l s e c r e t\n\n p l a n s t o t h e E m p i r e \' s\n\n u l t i m a t e w e a p o n , t h e D E A T H\n\n\n8\n t h e e v i l G a l a c t i c E m p i r e.\n\n\n D u r i n g t h e b a t t l e , R e b e l\n\n s p i e s m a n a g e d to s t e a l s e c r e t\n\n p l a n s t o t h e E m p i r e \' s\n\n u l t i m a t e w e a p o n , t h e D E A T H\n\n S T A R , a n a r m o r e d s p a c e\n\n8\n\n\n D u r i n g t h e b a t t l e , R e b e l\n\n s p i e s m a n a g e d to s t e a l s e c r e t\n\n p l a n s t o t h e E m p i r e \' s\n\n u l t i m a t e w e a p o n , t h e D E A T H\n\n S T A R , a n a r m o r e d s p a c e\n\n\n8\n\n D u r i n g t h e b a t t l e , R e b e l\n\n s p i e s m a n a g e d to s t e a l s e c r e t\n\n p l a n s t o t h e E m p i r e \' s\n\n u l t i m a t e w e a p o n , t h e D E A T H\n\n S T A R , a n a r m o r e d s p a c e\n\n s t a t i o n w i t h e n o u g h p o w e r to\n\n8\n D u r i n g t h e b a t t l e , R e b e l\n\n s p i e s m a n a g e d to s t e a l s e c r e t\n\n p l a n s t o t h e E m p i r e \' s\n\n u l t i m a t e w e a p o n , t h e D E A T H\n\n S T A R , a n a r m o r e d s p a c e\n\n s t a t i o n w i t h e n o u g h p o w e r to\n\n\n8\n\n s p i e s m a n a g e d to s t e a l s e c r e t\n\n p l a n s t o t h e E m p i r e \' s\n\n u l t i m a t e w e a p o n , t h e D E A T H\n\n S T A R , a n a r m o r e d s p a c e\n\n s t a t i o n w i t h e n o u g h p o w e r to\n\n d e s t r o y a n e n t i r e p l a n e t.\n\n8\n s p i e s m a n a g e d to s t e a l s e c r e t\n\n p l a n s t o t h e E m p i r e \' s\n\n u l t i m a t e w e a p o n , t h e D E A T H\n\n S T A R , a n a r m o r e d s p a c e\n\n s t a t i o n w i t h e n o u g h p o w e r to\n\n d e s t r o y a n e n t i r e p l a n e t.\n\n\n8\n\n p l a n s t o t h e E m p i r e \' s\n\n u l t i m a t e w e a p o n , t h e D E A T H\n\n S T A R , a n a r m o r e d s p a c e\n\n s t a t i o n w i t h e n o u g h p o w e r to\n\n d e s t r o y a n e n t i r e p l a n e t.\n\n\n\n8\n p l a n s t o t h e E m p i r e \' s\n\n u l t i m a t e w e a p o n , t h e D E A T H\n\n S T A R , a n a r m o r e d s p a c e\n\n s t a t i o n w i t h e n o u g h p o w e r to\n\n d e s t r o y a n e n t i r e p l a n e t.\n\n\n\n P u r s u e d b y t h e E m p i r e \' s\n8\n\n u l t i m a t e w e a p o n , t h e D E A T H\n\n S T A R , a n a r m o r e d s p a c e\n\n s t a t i o n w i t h e n o u g h p o w e r to\n\n d e s t r o y a n e n t i r e p l a n e t.\n\n\n\n P u r s u e d b y t h e E m p i r e \' s\n\n8\n u l t i m a t e w e a p o n , t h e D E A T H\n\n S T A R , a n a r m o r e d s p a c e\n\n s t a t i o n w i t h e n o u g h p o w e r to\n\n d e s t r o y a n e n t i r e p l a n e t.\n\n\n\n P u r s u e d b y t h e E m p i r e \' s\n\n s i n i s t e r a g e n t s , P r i n c e s s\n8\n\n S T A R , a n a r m o r e d s p a c e\n\n s t a t i o n w i t h e n o u g h p o w e r to\n\n d e s t r o y a n e n t i r e p l a n e t.\n\n\n\n P u r s u e d b y t h e E m p i r e \' s\n\n s i n i s t e r a g e n t s , P r i n c e s s\n\n8\n S T A R , a n a r m o r e d s p a c e\n\n s t a t i o n w i t h e n o u g h p o w e r to\n\n d e s t r o y a n e n t i r e p l a n e t.\n\n\n\n P u r s u e d b y t h e E m p i r e \' s\n\n s i n i s t e r a g e n t s , P r i n c e s s\n\n L e i a r a c e s h o m e a b o a r d h e r\n8\n\n s t a t i o n w i t h e n o u g h p o w e r to\n\n d e s t r o y a n e n t i r e p l a n e t.\n\n\n\n P u r s u e d b y t h e E m p i r e \' s\n\n s i n i s t e r a g e n t s , P r i n c e s s\n\n L e i a r a c e s h o m e a b o a r d h e r\n\n8\n s t a t i o n w i t h e n o u g h p o w e r to\n\n d e s t r o y a n e n t i r e p l a n e t.\n\n\n\n P u r s u e d b y t h e E m p i r e \' s\n\n s i n i s t e r a g e n t s , P r i n c e s s\n\n L e i a r a c e s h o m e a b o a r d h e r\n\n s t a r s h i p , c u s t o d i a n o f t h e\n8\n\n d e s t r o y a n e n t i r e p l a n e t.\n\n\n\n P u r s u e d b y t h e E m p i r e \' s\n\n s i n i s t e r a g e n t s , P r i n c e s s\n\n L e i a r a c e s h o m e a b o a r d h e r\n\n s t a r s h i p , c u s t o d i a n o f t h e\n\n8\n d e s t r o y a n e n t i r e p l a n e t.\n\n\n\n P u r s u e d b y t h e E m p i r e \' s\n\n s i n i s t e r a g e n t s , P r i n c e s s\n\n L e i a r a c e s h o m e a b o a r d h e r\n\n s t a r s h i p , c u s t o d i a n o f t h e\n\n s t o l e n p l a n s t h a t c a n s a v e\n8\n\n\n\n P u r s u e d b y t h e E m p i r e \' s\n\n s i n i s t e r a g e n t s , P r i n c e s s\n\n L e i a r a c e s h o m e a b o a r d h e r\n\n s t a r s h i p , c u s t o d i a n o f t h e\n\n s t o l e n p l a n s t h a t c a n s a v e\n\n8\n\n\n P u r s u e d b y t h e E m p i r e \' s\n\n s i n i s t e r a g e n t s , P r i n c e s s\n\n L e i a r a c e s h o m e a b o a r d h e r\n\n s t a r s h i p , c u s t o d i a n o f t h e\n\n s t o l e n p l a n s t h a t c a n s a v e\n\n h e r p e o p l e a n d r e s t o r e\n8\n\n P u r s u e d b y t h e E m p i r e \' s\n\n s i n i s t e r a g e n t s , P r i n c e s s\n\n L e i a r a c e s h o m e a b o a r d h e r\n\n s t a r s h i p , c u s t o d i a n o f t h e\n\n s t o l e n p l a n s t h a t c a n s a v e\n\n h e r p e o p l e a n d r e s t o r e\n\n8\n P u r s u e d b y t h e E m p i r e \' s\n\n s i n i s t e r a g e n t s , P r i n c e s s\n\n L e i a r a c e s h o m e a b o a r d h e r\n\n s t a r s h i p , c u s t o d i a n o f t h e\n\n s t o l e n p l a n s t h a t c a n s a v e\n\n h e r p e o p l e a n d r e s t o r e\n\n f r e e d o m t o t h e g a l a x y. . . .\n8\n\n s i n i s t e r a g e n t s , P r i n c e s s\n\n L e i a r a c e s h o m e a b o a r d h e r\n\n s t a r s h i p , c u s t o d i a n o f t h e\n\n s t o l e n p l a n s t h a t c a n s a v e\n\n h e r p e o p l e a n d r e s t o r e\n\n f r e e d o m t o t h e g a l a x y. . . .\n\n8\n s i n i s t e r a g e n t s , P r i n c e s s\n\n L e i a r a c e s h o m e a b o a r d h e r\n\n s t a r s h i p , c u s t o d i a n o f t h e\n\n s t o l e n p l a n s t h a t c a n s a v e\n\n h e r p e o p l e a n d r e s t o r e\n\n f r e e d o m t o t h e g a l a x y. . . .\n\n\n8\n\n L e i a r a c e s h o m e a b o a r d h e r\n\n s t a r s h i p , c u s t o d i a n o f t h e\n\n s t o l e n p l a n s t h a t c a n s a v e\n\n h e r p e o p l e a n d r e s t o r e\n\n f r e e d o m t o t h e g a l a x y. . . .\n\n\n\n8\n L e i a r a c e s h o m e a b o a r d h e r\n\n s t a r s h i p , c u s t o d i a n o f t h e\n\n s t o l e n p l a n s t h a t c a n s a v e\n\n h e r p e o p l e a n d r e s t o r e\n\n f r e e d o m t o t h e g a l a x y. . . .\n\n\n\n\n8\n\n s t a r s h i p , c u s t o d i a n o f t h e\n\n s t o l e n p l a n s t h a t c a n s a v e\n\n h e r p e o p l e a n d r e s t o r e\n\n f r e e d o m t o t h e g a l a x y. . . .\n\n\n\n\n\n8\n s t a r s h i p , c u s t o d i a n o f t h e\n\n s t o l e n p l a n s t h a t c a n s a v e\n\n h e r p e o p l e a n d r e s t o r e\n\n f r e e d o m t o t h e g a l a x y. . . .\n\n\n\n\n\n\n8\n\n s t o l e n p l a n s t h a t c a n s a v e\n\n h e r p e o p l e a n d r e s t o r e\n\n f r e e d o m t o t h e g a l a x y. . . .\n\n\n\n\n\n\n\n8\n s t o l e n p l a n s t h a t c a n s a v e\n\n h e r p e o p l e a n d r e s t o r e\n\n f r e e d o m t o t h e g a l a x y. . . .\n\n\n\n\n\n\n\n\n8\n\n h e r p e o p l e a n d r e s t o r e\n\n f r e e d o m t o t h e g a l a x y. . . .\n\n\n\n\n\n\n\n\n\n8\n h e r p e o p l e a n d r e s t o r e\n\n f r e e d o m t o t h e g a l a x y. . . .\n\n\n\n\n\n\n\n\n\n\n8\n\n f r e e d o m t o t h e g a l a x y. . . .\n\n\n\n\n\n\n\n\n\n\n\n8\n f r e e d o m t o t h e g a l a x y. . . .\n\n\n\n\n\n\n\n\n\n\n\n\n11\n\n\n\n\n\n\n\n\n\n\n\n\n\n8\n . . . . . .\n .\n . 8888888\n 88888888888 . . .\n . 8888888888888\n 888888888888888 . . .\n 888888888888888\n . 8888888888888 . . .\n . 88888888888\n . 8888888 . . .\n . . .\n . . .\n . . . .\n2\n .\n . 8888888\n 88888888888 . . .\n . 8888888888888\n 888888888888888 . . .\n 888888888888888\n . 8888888888888 . . .\n . 88888888888\n . 8888888 . . .\n . . .\n . . .\n . . . .\n\n1\n . 8888888\n 88888888888 . . .\n . 8888888888888\n 888888888888888 . . .\n 888888888888888\n . 8888888888888 . . .\n . 88888888888\n . 8888888 . . .\n . . .\n . . .\n . . . .\n\n . . .\n1\n . 8888888\n 88888888888 . . .\n . 8888888888888\n 888888888888888 . . .\n 888888888888888\n . 8888888888888 . . .\n . 88888888888\n . 8888888 . . .\n . . .\n . . .\n . . . .\n\n . .\n2\n 88888888888 . . .\n . 8888888888888\n 888888888888888 . . .\n 888888888888888\n . 8888888888888 . . .\n . 88888888888\n . 8888888 . . .\n . . .\n . . .\n . . . .\n\n . . .\n\n2\n . 88888888888888\n 8888888888888888 . . .\n 8888888888888888\n . 88888888888888 . . .\n . 8888888888\n . 888888 . . .\n . . .\n . . .\n . . . .\n\n . . .\n\n . .\n2\n 8888888888888888 . . .\n 8888888888888888\n . 88888888888888 . . .\n . 8888888888\n . 888888 . . .\n . . .\n . . .\n . . . .\n\n . . .\n\n . .\n\n2\n 8888888888888888\n . 88888888888888 . . .\n . 8888888888\n . 888888 . . .\n . . .\n . . .\n . . . .\n\n . . .\n\n . .\n\n\n2\n . 88888888888888 . . .\n . 8888888888\n . 888888 . . .\n . . .\n . . .\n . . . .\n\n . . .\n\n . .\n\n\n\n2\n . 8888888888\n . 888888 . . .\n . . .\n . . .\n . . . .\n\n . . .\n\n . .\n\n\n\n\n2\n . 888888 . . .\n . . .\n . . .\n . . . .\n\n . . .\n\n . .\n\n\n\n\n\n2\n . . .\n . . .\n . . . .\n\n . . .\n\n . .\n\n\n\n\n\n\n2\n . . .\n . . . .\n\n . . .\n\n . .\n\n\n\n\n\n\n\n2\n . . . .\n\n . . .\n\n . .\n\n\n\n\n\n\n\n\n2\n . . .\n\n . .\n\n\n\n\n\n\n\n\n\n\n2\n\n . .\n\n\n\n\n\n\n\n\n\n\n\n2\n . .\n\n\n\n\n\n\n\n\n\n\n\n\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n1\n\n\n\n\n\n\n\n\n\n O\n\n\n\n1\n\n\n\n\n\n\n\n\n\n O=\n\n\n\n1\n\n\n\n\n\n\n\n\n\n O=<\n\n\n\n1\n\n\n\n\n\n\n\n\n\n O=<8\n\n\n\n1\n\n\n\n\n\n\n\n\n\n O=<88\n\n\n\n1\n\n\n\n\n\n\n\n\n\n O=<88>\n\n\n\n1\n\n\n\n\n\n\n\n\n\n O=<88>=\n\n\n\n1\n\n\n\n\n\n\n\n\n\n O=<88>=O\n\n\n\n1\n\n\n\n\n\n\n\n\n\n O=<88>=O<\n\n\n\n1\n\n\n\n\n\n\n\n\n\n O=<88>=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O-\n O=<88>=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O______ ) _____\n / \\__/_________\\ /-\\ / __|\n . |====__ _________ |(O)|===|__\n \\__/ \\_________/ \\-/ \\_____| .\n <>\n .\n . .\n .\n .\n1\n\n . . . . . .\n\n\n . __ _<>______ ) _____\n / \\__/_________\\ /-\\ / __|\n . |====__ _________ |(O)|===|__\n \\__/ \\_________/ \\-/ \\_____| .\n <>\n .\n . .\n .\n .\n1\n\n . . . . . .\n\n\n . __ _<>______ ) _____\n / \\__/_________\\ /-\\ / __|\n . |====__ _________ |(O)|===|__\n \\__/ \\_________/ \\-/ \\_____| .\n <>\n .\n . .\n .\n .\n1\n\n . . . . . .\n\n\n . __ _<>______ ) _____\n / \\__/_________\\ /-\\ / __|\n .|====__ _________ |(O)|===|__\n. \\__/ \\_________/ \\-/ \\_____| .\n <>\n .\n . .\n .\n .\n1\n\n . . . . . .\n\n\n . __ _<>______ ) _____\n / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n . \\__/ \\_________/ \\-/ \\_____| .\n <>\n .\n . .\n .\n .\n1\n\n . . . . .\n\n. _\n . __ _<>______ ) _____\n / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n . \\__/ \\_________/ \\-/ \\_____| .\n <>\n .\n . .\n .\n .\n1\n\n . . . . .\n\n . ___\n . __ _<>______ ) _____\n / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n . \\__/ \\_________/ \\-/ \\_____| .\n <>\n .\n . .\n .\n .\n1\n\n . . . . .\n\n . _____\n . __ _<>______ ) _____\n / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n . \\__/ \\_________/ \\-/ \\_____| .\n <>\n .\n . .\n .\n .\n1\n\n . . . . .\n\n . _____\n . __ _<>______ ) _____\n / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n . \\__/ \\_________/ \\-/ \\_____| .\n <>\n .\n . .\n. .\n\n1\n\n . . . . .\n\n . _____\n . __ _<>______ ) _____\n / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n . \\__/ \\_________/ \\-/ \\_____| .\n <>\n .\n . .\n . .\n\n1\n\n . . . . .\n\n . _____\n . __ _<>______ ) _____\n / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n . \\__/ \\_________/ \\-/ \\_____| .\n <>\n .\n . .\n . .\n\n1\n\n . . . . .\n\n . _____\n . __ _<>______ ) _____\n / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n . \\__/ \\_________/ \\-/ \\_____| .\n <>\n .\n . .\n . .\n\n1\n.\n . . . . .\n\n . _____\n . __ _<>______ ) _____\n. / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n . \\__/ \\_________/ \\-/ \\_____| .\n <>\n .\n . .\n . .\n\n1\n .\n . . . . .\n\n . _____\n . __ _<>______ ) _____\n . / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n . \\__/ \\_________/ \\-/ \\_____| .\n <>\n .\n . .\n . .\n\n1\n .\n . . . . .\n\n . _____\n .__ _<>______ ) _____\n . / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n . \\__/ \\_________/ \\-/ \\_____| .\n <>\n .\n . .\n . .\n\n1\n .\n . . . . .\n\n . _____\n __ _<>______ ) _____\n . / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n . \\__/ \\_________/ \\-/ \\_____| .\n <>\n .\n . .\n . .\n\n1\n .\n . . . . .\n\n . _____\n __ _<>______ ) _____\n . / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n . \\__/ \\_________/ \\-/ \\_____|\n <>\n .\n . .\n . .\n\n1\n .\n . . . . .\n\n . _____\n __. _<>______ ) _____\n . / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n .\\__/ \\_________/ \\-/ \\_____|\n. <>\n .\n . .\n . .\n\n1\n .\n . . . . .\n\n . _____\n __ . _<>______ ) _____\n . / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n \\__/ \\_________/ \\-/ \\_____|\n . <>\n .\n . .\n . .\n\n1\n .\n . . . . .\n\n . _____\n __ . _<>______ ) _____\n . / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n \\__/ \\_________/ \\-/ \\_____|\n . <>\n .\n . .\n . .\n\n1\n .\n . . . .\n\n . _____\n __ ._<>______ ) _____\n . / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n \\__/ \\_________/ \\-/ \\_____|\n . <>\n .\n . .\n . .\n\n1\n .\n . . . .\n\n . \'__\n __ _<>______ ) _____\n . / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n \\__/ \\_________/ \\-/ \\_____|\n . <>\n .\n . .\n . .\n\n1\n .\n . . . .\n ,\n . \'._\n __ _<>______ `) _____\n . / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n \\__/ \\_________/ \\-/ \\_____|\n . <>\n .\n . .\n . .\n\n1\n .\n . . . .\n ; \' ,\n. . \'\n __ _<>______ : * _____\n . / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n \\__/ .\\_________/ \\-/ \\_____|\n . <>\n .\n . .\n . .\n\n1\n .\n . . , . . .\n \' ,\n. . : * ,\n __ _<>______" *** _____\n . / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n \\__/ .\\_________/ \\-/ \\_____|\n . <>\n .\n . .\n . .\n\n1\n . \' \'\n . \' ; \' . . .\n *\n. . ; , ***, \'\n __ _<>______ ***** _____\n . / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n \\__/ .\\_________/ \\-/ \\_____|\n . <>\n .\n . .\n . .\n\n1\n . \' "\n . * \'. . .\n " * * ,\n. . , * * "\n __ _<>______ * ** _____\n . / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n \\__/ .\\_________/ \\-/ \\_____|\n . <>\n .\n . .\n . .\n\n1\n . *\n " . . . .\n\n. . * * \'\n __ _<>______ _____\n . / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n \\__/ .\\_________/ \\-/ \\_____|\n . <>\n .\n . .\n . .\n\n1\n . \'\n . . . .\n \'\n. .\n __ _<>______ _____\n . / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n \\__/ .\\_________/ \\-/ \\_____|\n . <>\n .\n . .\n . .\n\n17\n .\n . . . .\n\n. .\n __ _<>______ _____\n . / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__\n \\__/ .\\_________/ \\-/ \\_____|\n . <>\n .\n . .\n . .\n\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n1\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n /() \\ //|/.\\|\\\\\n _|_____|_ \\\\ \\_/ ||\n | | === | | \\|\\ /| ||\n |_| O |_| # _ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n1\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n / ()\\ //|/.\\|\\\\\n _|_____|_ \\\\ \\_/ ||\n | | === | | \\|\\ /| ||\n |_| O |_| # _ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n_________________[_]_[_]_[_]________/_]_[_\\________________________\n1\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n /() \\ //|/.\\|\\\\\n _|_____|_ \\\\ \\_/ ||\n | | === | | \\|\\ /| ||\n |_| O |_| # _ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n1\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n /() \\ //|/.\\|\\\\\n _|_____|_ \\\\ \\_/ ||\n | | === | | \\|\\ /| ||\n |_| O |_| # _ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n_______________[_]_[_]_[_]________/_]_[_\\__________________________\n1\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n /() \\ //|/.\\|\\\\\n _|_____|_ \\\\ \\_/ ||\n | | === | | \\|\\ /| ||\n |_| O |_| # _ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n1\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n /() \\ //|/.\\|\\\\\n _|_____|_ \\\\ \\_/ ||\n | | === | | \\|\\ /| ||\n |_| O |_| # _ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n1\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n / ()\\ //|/.\\|\\\\\n _|_____|_ \\\\ \\_/ ||\n | | === | | \\|\\ /| ||\n |_| O |_| # _ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n_________________[_]_[_]_[_]________/_]_[_\\________________________\n1\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n /() \\ //|/.\\|\\\\\n _|_____|_ \\\\ \\_/ ||\n | | === | | \\|\\ /| ||\n |_| O |_| # _ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n1\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n /() \\ //|/.\\|\\\\\n _|_____|_ \\\\ \\_/ ||\n | | === | | \\|\\ /| ||\n |_| O |_| # _ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n_______________[_]_[_]_[_]________/_]_[_\\__________________________\n7\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n /() \\ //|/.\\|\\\\\n _|_____|_ \\\\ \\_/ ||\n | | === | | \\|\\ /| ||\n |_| O |_| # _ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n1\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n / ()\\ //|/.\\|\\\\\n _|_____|_ \\\\ \\_/ ||\n | | === | | \\|\\ /| ||\n |_| O |_| # _ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n15\n /~\\\n |oo ) Did you hear that?\n _\\=/_\n ___ / _ \\\n / ()\\ //|/.\\|\\\\\n _|_____|_ \\\\ \\_/ ||\n | | === | | \\|\\ /| ||\n |_| O |_| # _ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n5\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n / ()\\ //|/.\\|\\\\\n _|_____|_ \\\\ \\_/ ||\n | | === | | \\|\\ /| ||\n |_| O |_| # _ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n5\n /~\\\n |oo )\n _\\=/_\n ___ # / _ \\\n / ()\\ \\\\//|/.\\|\\\\\n _|_____|_ \\/ \\_/ ||\n | | === | | |\\ /| ||\n |_| O |_| \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n1\n /~\\\n ( oo| They\'ve shut down\n _\\=/_ the main reactor.\n ___ # / _ \\\n / ()\\ \\\\//|/.\\|\\\\\n _|_____|_ \\/ \\_/ ||\n | | === | | |\\ /| ||\n |_| O |_| \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n15\n /~\\\n ( oo| They\'ve shut down\n _\\=/_ the main reactor.\n ___ # / _ \\\n / ()\\ \\\\//|/.\\|\\\\\n _|_____|_ \\/ \\_/ ||\n | | === | | |\\ /| ||\n |_| O |_| \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n5\n /~\\\n |oo )\n _\\=/_\n ___ # / _ \\\n / ()\\ \\\\//|/.\\|\\\\\n _|_____|_ \\/ \\_/ ||\n | | === | | |\\ /| ||\n |_| O |_| \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n5\n /~\\\n |oo )\n _\\=/_\n ___ # / _ \\ #\n / ()\\ \\\\//|/.\\|\\\\//\n _|_____|_ \\/ \\_/ \\/\n | | === | | |\\ /|\n |_| O |_| \\_ _/\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n15\n /~\\\n |oo ) We\'re doomed!\n _\\=/_\n ___ # / _ \\ #\n /() \\ \\\\//|/.\\|\\\\//\n _|_____|_ \\/ \\_/ \\/\n | | === | | |\\ /|\n |_| O |_| \\_ _/\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n3\n . .\n . . .\n .\n . . . .\n .\n .\n . __ _<>______ . _____\n / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__ .\n . \\__/ \\_________/ \\-/ \\_____| .\n . <>\n . .\n . .\n2\n______| . |__________________\n . . .\n .\n . . . .\n .\n .\n . __ _<>______ . _____\n / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__ .\n . \\__/ \\_________/ \\-/ \\_____| .\n . <>\n . .\n . .\n2\n======| . |==================\n______| . . |__________________\n .\n . . . .\n .\n .\n . __ _<>______ . _____\n / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__ .\n . \\__/ \\_________/ \\-/ \\_____| .\n . <>\n . .\n . .\n2\n | . |\n======| . . |==================\n______| |__________________\n . . . .\n .\n .\n . __ _<>______ . _____\n / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__ .\n . \\__/ \\_________/ \\-/ \\_____| .\n . <>\n . .\n . .\n2\n | . |\n | . . |\n======| |==================\n______| . . |__________________\n .\n .\n . __ _<>______ . _____\n / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__ .\n . \\__/ \\_________/ \\-/ \\_____| .\n . <>\n . .\n . .\n2\n | . ## ## |\n | . . |\n | |\n======| . . |==================\n______| . |__________________\n .\n . __ _<>______ . _____\n / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__ .\n . \\__/ \\_________/ \\-/ \\_____| .\n . <>\n . .\n . .\n2\n | . ## ## |\n | ## . . ## |\n | |\n | . . |\n======| . |==================\n______| |__________________\n . __ _<>______ . _____\n / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__ .\n . \\__/ \\_________/ \\-/ \\_____| .\n . <>\n . .\n . .\n2\n | . ## ## |\n | ## . . ## |\n | ## ## |\n | . . |\n | . |\n======| |==================\n______| . __ _<>______ . _____ |__________________\n / \\__/_________\\ /-\\ / __|\n |====__ _________ |(O)|===|__ .\n . \\__/ \\_________/ \\-/ \\_____| .\n . <>\n . .\n . .\n1\n | . ## ## |\n | ## . . ## |\n | ## ## |\n | . ## ## . |\n | . |\n | |\n======| . __ _<>______ . _____ |==================\n______| / \\__/_________\\ /-\\ / __| |__________________\n |====__ _________ |(O)|===|__ .\n . \\__/ \\_________/ \\-/ \\_____| .\n . <>\n . .\n . .\n2\n | . #### #### |\n | ## . . ## |\n | ## ## |\n | . ## ## . |\n | ## . ## |\n | |\n | . __ _<>______ . _____ |\n======| / \\__/_________\\ /-\\ / __| |==================\n______| |====__ _________ |(O)|===|__ |__________________\n . \\__/ \\_________/ \\-/ \\_____| .\n . <>\n . .\n . .\n2\n _________________________________________\n | #### . . #### |\n | ## ## |\n | . ## ## . |\n | ## . ## |\n | ## ## |\n | . __ _<>______ . _____ |\n | / \\__/_________\\ /-\\ / __| |\n======| |====__ _________ |(O)|===|__ |==================\n______| \\__/ \\_________/ \\-/ \\_____| |__________________\n . <>\n . .\n . .\n2\n\n _________________________________________\n | #### #### |\n | . ## ## . |\n | ## . ## |\n | ## ## |\n | . __ ##_<>______ . ##_____ |\n | / \\__/_________\\ /-\\ / __| |\n | |====__ _________ |(O)|===|__ |\n======| \\__/ \\_________/ \\-/ \\_____| |==================\n______| . <> |__________________\n . .\n . .\n2\n\n\n _________________________________________\n | . #### #### . |\n | ## . ## |\n | ## ## |\n | . __ ##_<>______ . ##_____ |\n | / \\_##_________\\ /-\\## __| |\n | |====__ _________ |(O)|===|__ |\n | \\__/ \\_________/ \\-/ \\_____| |\n======| . <> |==================\n______| . |__________________\n . .\n14\n\n\n\n _________________________________________\n | #### . #### |\n | ## ## |\n | . __ ##_<>______ . ##_____ |\n | / \\_##_________\\ /-\\## __| |\n | |====_##_________ |(O)##==|__ |\n | \\__/ \\_________/ \\-/ \\_____| |\n | . <> |\n======| . |==================\n______| . .|__________________\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n15\n \\_\\ \\ _______________________________ / /_/\n | | | _________ | | |\n | | | // _____ \\\\ | | |\n | | | || / \\ || | | |\n | | | || | \\ / | || | | |\n | | | || | | || | | |\n | | | || | | || | | |\n | | | || | / \\ | || | | |\n | | | || \\_____/ || | | |\n | | | \\\\_________// | | |\n | | |_______________________________| | |\n |_| / \\ |_|\n / / / \\ \\ \\\n2\n \\_\\ \\ _______________________________ / /_/\n | | | _________ | | |\n | | | // __*__ \\\\ | | |\n | | | || / \\ || | | |\n | | | || | \\ / | || | | |\n | | | || | | || | | |\n | | | || | | || | | |\n | | | || | / \\ | || | | |\n | | | || \\_____/ || | | |\n | | | \\\\____*____// | | |\n | | |_______________________________| | |\n |_| / \\ |_|\n / / / \\ \\ \\\n2\n \\_\\ \\ _______________________________ / /_/\n | | | _________ | | |\n | | | // _***_ \\\\ | | |\n | | | || / \\ || | | |\n | | | || | \\ / | || | | |\n | | | || | | || | | |\n | | | || | | || | | |\n | | | || | / \\ | || | | |\n | | | || \\_____/ || | | |\n | | | \\\\___***___// | | |\n | | |_______________________________| | |\n |_| / \\ |_|\n / / / \\ \\ \\\n2\n \\_\\ \\ _______________________________ / /_/\n | | | _________ | | |\n | | | // ***** \\\\ | | |\n | | | || / \\ || | | |\n | | | || | \\ / | || | | |\n | | | || | | || | | |\n | | | || | | || | | |\n | | | || | / \\ | || | | |\n | | | || \\_____/ || | | |\n | | | \\\\__*****__// | | |\n | | |_______________________________| | |\n |_| / \\ |_|\n / / / \\ \\ \\\n2\n \\_\\ \\ _______________________________ / /_/\n | | | _________ | | |\n | | | // ******* \\\\ | | |\n | | | || / \\ || | | |\n | | | || | \\ / | || | | |\n | | | || | | || | | |\n | | | || | | || | | |\n | | | || | / \\ | || | | |\n | | | || \\_____/ || | | |\n | | | \\\\_*******_// | | |\n | | |_______________________________| | |\n |_| / \\ |_|\n / / / \\ \\ \\\n2\n \\_\\ \\ _______________________________ / /_/\n | | | _________ | | |\n | | | //*********\\\\ | | |\n | | | || / \\ || | | |\n | | | || | \\ / | || | | |\n | | | || | | || | | |\n | | | || | | || | | |\n | | | || | / \\ | || | | |\n | | | || \\_____/ || | | |\n | | | \\\\*********// | | |\n | | |_______________________________| | |\n |_| / \\ |_|\n / / / \\ \\ \\\n2\n \\_\\ \\ _______________________________ / /_/\n | | | _________ | | |\n | | | /***********\\ | | |\n | | | || / \\ || | | |\n | | | || | \\ / | || | | |\n | | | || | | || | | |\n | | | || | | || | | |\n | | | || | / \\ | || | | |\n | | | || \\_____/ || | | |\n | | | \\***********/ | | |\n | | |_______________________________| | |\n |_| / \\ |_|\n / / / \\ \\ \\\n2\n \\_\\ \\ _______________________________ / /_/\n | | | _________ | | |\n | | | /***********\\ | | |\n | | | |* / \\ *| | | |\n | | | || | \\ / | || | | |\n | | | || | | || | | |\n | | | || | | || | | |\n | | | || | / \\ | || | | |\n | | | |* \\_____/ *| | | |\n | | | \\***********/ | | |\n | | |_______________________________| | |\n |_| / \\ |_|\n / / / \\ \\ \\\n2\n \\_\\ \\ _______________________________ / /_/\n | | | _________ | | |\n | | | /***********\\ | | |\n | | | |* / \\ *| | | |\n | | | |* | \\ / | *| | | |\n | | | || | | || | | |\n | | | || | | || | | |\n | | | |* | / \\ | *| | | |\n | | | |* \\_____/ *| | | |\n | | | \\***********/ | | |\n | | |_______________________________| | |\n |_| / \\ |_|\n / / / \\ \\ \\\n2\n \\_\\ \\ _______________________________ / /_/\n | | | _________ | | |\n | | | /***********\\ | | |\n | | | |* / \\ *| | | |\n | | | |* | \\ / | *| | | |\n | | | |* | | *| | | |\n | | | |* | | *| | | |\n | | | |* | / \\ | *| | | |\n | | | |* \\_____/ *| | | |\n | | | \\***********/ | | |\n | | |_______________________________| | |\n |_| / \\ |_|\n / / / \\ \\ \\\n1\n \\_\\ \\ _______________________________ / /_/\n | | | ********* | | |\n | | | . ************* . | | |\n | | | ** / \' \\ ** | | |\n | | | .** | \\ / | ** | | |\n | | | . ** | . \'| ** : | | |\n | | | ** | | ** | | |\n | | | . ** | / . \\ | ** . | | |\n | | | ** \\_____/ ** | | |\n | | | . ************* . | | |\n | | |__________***********__________| | |\n |_| / \\ |_|\n / / / . . \\ \\ \\\n1\n \\_\\ \\ _______________________________ / /_/\n | | | " ********* | | |\n | | | ************* \' . | | |\n | | | " *************** | | |\n | | | ***| " |*** . " | | |\n | | | \' ***| " |*** | | |\n | | | ***| |*** . | | |\n | | | ,***| \' |*** " | | |\n | | | " *************** | | |\n | | | " ************* " | | |\n | | |__________***********__________| | |\n |_| / \'. \\ |_|\n / / / " \' " \\ \\ \\\n1\n \\_\\ \\ ____#____*************#________ / /_/\n | | | * _________ * | | |\n | | | # * ************* * " | | |\n | | | . * * # * * # | | |\n | | | * * . # "* *. | | |\n | | | \' * * " * * #| | |\n | | | # .* * \' * *. | | |\n | | | * * . \' * * " | | |\n | | | " * * # * * | | |\n | | | # * ************* * | | |\n | | |_________*____________*__"__#__| | |\n |_| / # ************ \\ |_|\n / / / \' \'\' # \\ \\ \\\n1\n \\_\\ \\ _______________________________ / /_/\n | | | _________ # . | . | |\n | | # | . /***********\\ # | |\n | | | * * | | |\n | | . | # . * | | |\n | | | * * | | |\n | | | . * * |# . | |\n | | #| * . * . | | |\n | | | . * * | | |\n | | | \\**********#/ | . | |\n | | . |_______________________________| | |\n |_| /# # #\\ |_|\n / / / . # . . \\ \\ \\\n1\n \\_\\ \\ _______________________________ / /_/\n | | | _________ | | |\n | | | # // \\\\ . | | |\n | | # | || || | | |\n | | | || || | # | |\n | | | . || || | | |\n | | | || || | | |\n | | . | || || # | \' | |\n | | | || || | | |\n | | | \\\\_________// | | |\n | | # |_________________________#_____| | |\n |_| / \\ # |_|\n / / # / \' # \\ \\ \\\n1\n \\_\\ \\ _#_____________________________ / /_/\n | | | _________ . | | |\n | | | // \\\\ | | |\n | | \' | || || | | |\n | | | || || | | |\n #| | | || || | | |\n | | | || || | # | |\n | | | || || | .| |\n | | | || || | | |\n | | | . \\\\_________// | # | |\n | | |_______________________________| | |\n |_| / \\ |_|\n / / /# # \\ # \\\n1\n \\_\\ \\ _______________________________ / /_/\n | | | _________ | | |\n | | | // \\\\ | | |\n | | | . || || . | | |\n | | | || || | | |\n | | | || || | | |\n # | | | || || | | |\n | | | || || | | |\n | | | || || | | |\n | | | \\\\_________// #| |#|\n | | . |_______________________________| | |\n |_| / \\ |_|\n / / / \\ \\ \\\n1\n \\_\\ \\ _______________________________ / /_/\n | | | _________ | | |\n | | | // \\\\ | | |\n | | | || || | | |\n | | | || || | | |\n | | | || || | | |\n | | | || || | | |\n | | | || || | | |\n | | | || || | | |\n # | | | \\\\_________// | | |\n | | |_______________________________| | |\n |_| / # \\ |_|\n / / / \\ \\ \\\n1\n \\_\\ \\ _______________________________ / /_/\n | | | _________ | | |\n | | | // \\\\ | | |\n | | | || || | | |\n | | | || || | | |\n | | | || || | | |\n | | | || || | | |\n | | | || || | | |\n | | | || || | | |\n | | | \\\\_________// | | |\n | | |_______________________________| | |\n |_| / \\ |_|\n / / / # \\ \\ \\\n4\n \\_\\ \\ _______________________________ / /_/\n | | | _________ | | |\n | | | // \\\\ | | |\n | | | || || | | |\n | | | || || | | |\n | | | || || | | |\n | | | || || | | |\n | | | || || | | |\n | | | || || | | |\n | | | \\\\_________// | | |\n | | |_______________________________| | |\n |_| / \\ |_|\n / / / \\ \\ \\\n1\n\n\n\n\n\n\n\n\n\n\n\n\n\n2\n | ___________________ |\n | / /__\\ \\ |\n | | |<><>| | |\n | | (_/\\_) | |\n | | / \\ | |\n | | //| __ |\\\\ | |\n | | || |/ \\| \\\\ | |\n | | || [][][] \\\\ | |\n | | || |\\ /| \'| | |\n | | \'] |_||_| | |\n | | [I [ ][ ] | |\n | \\_____I_|_||_|______/ |\n | |\n2\n | ___________________ |\n | / /__\\ \\ |\n | | |<><>| | |\n | | (_/\\_) | |\n | | / \\ | |\n | | //| ()\\|| | |\n | | || |/ \\ | | |\n | | || [][][\\/ | |\n | | || |\\ /| | |\n | | \'] |_||_| | |\n | | [I [ ][ ] | |\n | \\_____I_|_||_|______/ |\n | |\n2\n | ___________________ |\n | / /__\\ \\ |\n | | |<><>| | |\n | | (_/\\_) | |\n | | / \\ | |\n | | ||/=O\\|| | |\n | | | / \\ | | |\n | | \\/][][\\/ | |\n | | |\\ /| | |\n | | |_||_| | |\n | | [ ][ ] | |\n | \\_______|_||_|______/ |\n | |\n1\n | ___________________ |\n | / /__\\ \\ |\n | | |<><>| | |\n | | (_/\\_) | |\n | | / \\ | |\n | | ||/=*\\|| | |\n | | | / \\ | | |\n | | \\/][][\\/ | |\n | | |\\ /| | |\n | | |_||_| | |\n | | [ ][ ] | |\n | \\_______|_||_|______/ |\n | |\n1\n | ___________________ |\n | / /__\\ \\ |\n | | |<><>| | |\n | | (_/\\_) | |\n | | / * \\ | |\n | | ||/***|| | |\n | | | / *\\ | | |\n | | \\/][][\\/ | |\n | | |\\ /| | |\n | | |_||_| | |\n | | [ ][ ] | |\n | \\_______|_||_|______/ |\n | |\n1\n | ___________________ |\n | / /__\\ \\ |\n | | |<><>| | |\n | | (_/\\_) | |\n | | / *** \\ | |\n | | ||*****| | |\n | | | /*** | | |\n | | \\/][][\\/ | |\n | | |\\ /| | |\n | | |_||_| | |\n | | [ ][ ] | |\n | \\_______|_||_|______/ |\n | |\n1\n | ___________________ |\n | / /__\\ \\ |\n | | |<><>| | |\n | | (_/\\_) | |\n | | / * \\ | |\n | | ||/***|| | |\n | | | / *\\ | | |\n | | \\/][][\\/ | |\n | | |\\ /| | |\n | | |_||_| | |\n | | [ ][ ] | |\n | \\_______|_||_|______/ |\n | |\n1\n | ___________________ |\n | / /__\\ \\ |\n | | |<><>| | |\n | | (_/\\_) | |\n | | / \\ | |\n | | ||/=*\\|| | |\n | | | / \\ | | |\n | | \\/][][\\/ | |\n | | |\\ /| | |\n | | |_||_| | |\n | | [ ][ ] | |\n | \\_______|_||_|______/ |\n | |\n1\n | ___________________ |\n | / /__\\ \\ |\n | | |<><>| | |\n | | (_/\\_) | |\n | | / \\ | |\n | | ||/=O\\|| | |\n | | | / \\ | | |\n | | \\/][][\\/ | |\n | | |\\ /| | |\n | | |_||_| | |\n | | [ ][ ] | |\n | \\_______|_||_|______/ |\n | |\n1\n | ___________________ |\n | / /__\\ \\ |\n | | |<><>| | |\n | | (_/\\_) | |\n | | / \\ | |\n | | ||/=*\\|| | |\n | | | / \\ | | |\n | | \\/][][\\/ | |\n | | |\\ /| | |\n | | |_||_| | |\n | | [ ][ ] | |\n | \\_______|_||_|______/ |\n | |\n1\n | ___________________ |\n | / /__\\ \\ |\n | | |<><>| | |\n | | (_/\\_) | |\n | | / * \\ | |\n | | ||/***|| || |\n | | | / *\\ | || |\n | | \\/][][\\/ || |\n | | |\\ /| \'| |\n | | |_||_| [| |\n | | [ ][ ] | |\n | \\_______|_||_|______/ |\n | |\n1\n | ___________________ |\n | / /__\\ \\ |\n | | |<><>| | |\n | | (_/\\_) | |\n | | / *** \\ | |\n | | ||*****| || |\n | | | /*** | || |\n | | \\/][][\\/ || |\n | | |\\ /| \'| |\n | | |_||_| [| |\n | | [ ][ ] | |\n | \\_______|_||_|______/ |\n | |\n1\n | ___________________ |\n | / /__\\ \\ |\n | | |<><>| | |\n | | (_/\\_) | |\n | | / * \\ /| |\n | | ||/***|| | | |\n | | | / *\\ | ||| |\n | | \\/][][\\/ ||| |\n | | |\\ /| \']| |\n | | |_||_| [I| |\n | | [ ][ ] I| |\n | \\_______|_||_|______/ |\n | |\n1\n | ___________________ |\n | / /__\\ \\ |\n | | |<><>| | |\n | | (_/\\_) | |\n | | / \\ /| |\n | | ||/=*\\|| | | |\n | | | / \\ | ||| |\n | | \\/][][\\/ ||| |\n | | |\\ /| \']| |\n | | |_||_| [I| |\n | | [ ][ ] I| |\n | \\_______|_||_|______/ |\n | |\n2\n | ___________________ |\n | / /__\\ \\ |\n | | |<><>| || |\n | | (_/\\_) (| |\n | | / \\ / | |\n | | ||/=O\\|| | || |\n | | | / \\ | |||| |\n | | \\/][][\\/ ||[| |\n | | |\\ /| \']|| |\n | | |_||_| [I|| |\n | | [ ][ ] I[| |\n | \\_______|_||_|______/ |\n | |\n2\n | ___________________ |\n | / /__\\ \\ |\n | | |<><>| |<| |\n | | (_/\\_) (_| |\n | | / \\ / | |\n | | ||/=O\\|| | | | |\n | | | / \\ | |||/| |\n | | \\/][][\\/ ||[]| |\n | | |\\ /| \']|\\| |\n | | |_||_| [I|_| |\n | | [ ][ ] I[ | |\n | \\_______|_||_|_____|/ |\n | |\n1\n | ___________________ |\n | / /__\\ /\\ |\n | | |<><>| |<>| |\n | | (_/\\_) (_/| |\n | | / \\ / | |\n | | ||/=*\\|| | | _| |\n | | | / \\ | |||/ | |\n | | \\/][][\\/ ||[][| |\n | | |\\ /| \']|\\ | |\n | | |_||_| [I|_|| |\n | | [ ][ ] I[ ]| |\n | \\_______|_||_|____|_/ |\n | |\n1\n | ___________________ |\n | / /__\\ /\\ |\n | | |<><>| |<>| |\n | | (_/\\_) (_/| |\n | | / * \\ / | |\n | | ||/***|| | | _| |\n | | | / *\\ | |||/ | |\n | | \\/][][\\/ ||[][| |\n | | |\\ /| \']|\\ | |\n | | |_||_| [I|_|| |\n | | [ ][ ] I[ ]| |\n | \\_______|_||_|____|_/ |\n | |\n1\n | ___________________ |\n | / /__\\ /\\ |\n | | |<><>| |<>| |\n | | (_/\\_) (_/| |\n | |\\ / *** \\ / | |\n | || ||*****| ||/=| |\n | || | /*** | | / | |\n | |/ \\/][][\\/ \\/][| |\n | | |\\ /| |\\ | |\n | | |_||_| |_|| |\n | | [ ][ ] [ ]| |\n | \\_______|_||_|____|_/ |\n | |\n1\n | ___________________ |\n | / /__\\ /\\ |\n | || |<><>| |<>| |\n | |) (_/\\_) (_/| |\n | | \\ / * \\ / | |\n | ||| ||/***|| ||/=| |\n | | | | / *\\ | | / | |\n | |\\/ \\/][][\\/ \\/][| |\n | || |\\ /| |\\ | |\n | || |_||_| |_|| |\n | |] [ ][ ] [ ]| |\n | \\_______|_||_|____|_/ |\n | |\n1\n | ___________________ |\n | / /__\\ /\\ |\n | |>| |<><>| |<>| |\n | |_) (_/\\_) (_/| |\n | | \\ / \\ / | |\n | |\\|| ||/=*\\|| ||/=| |\n | |\\ | | / \\ | | / | |\n | | \\/ \\/][][\\/ \\/][| |\n | |/| |\\ /| |\\ | |\n | |_| |_||_| |_|| |\n | | ] [ ][ ] [ ]| |\n | \\|______|_||_|____|_/ |\n | |\n1\n | ___________________ |\n | /\\ /__\\ /\\ |\n | |<>| |<><>| |<>| |\n | |\\_) (_/\\_) (_/| |\n | | \\ / \\ / | |\n | |O\\|| ||/=O\\|| ||/*| |\n | | \\ | | / \\ | | / | |\n | |][\\/ \\/][][\\/ \\/][| |\n | | /| |\\ /| |\\ | |\n | ||_| |_||_| |_|| |\n | |[ ] [ ][ ] [ ]| |\n | \\_|_____|_||_|____|_/ |\n | |\n1\n | ___________________ |\n | /_\\ /__\\ /\\ |\n | |><>| |<><>| |<>| |\n | |/\\_) (_/\\_) (_/| |\n | | \\ / \\ / *| |\n | |=*\\|| ||/=O || ||**| |\n | | \\ | | / \\ | | /*| |\n | |[][\\/ \\/][][\\/ \\/][| |\n | | /| |\\ /| |\\ | |\n | |||_| |_||_| |_|| |\n | |][ ] [ ][ ] [ ]| |\n | \\|_|____|_||_|____|_/ |\n | |\n1\n | ___________________ |\n | /__\\ /__\\ /\\ |\n | |<><>| |<><>| |<>| |\n | |_/\\_) (_/\\_) (_/| |\n | | * \\ / \\ / | |\n | |/***|| ||/=* || ||/*| |\n | |/ *\\ | | / \\ | | / | |\n | |][][\\/ \\/][][\\/ \\/][| |\n | |\\ /| |\\ /| |\\ | |\n | |_||_| |_||_| |_|| |\n | | ][ ] [ ][ ] [ ]| |\n | \\_|_|___|_||_|____|_/ |\n | |\n1\n | ___________________ |\n | /__\\ /__\\ /\\ |\n | |<><>| |<><>| |<>| |\n | |_/\\_) (_/\\_) (_/| |\n | | *** \\ / * \\ / | |\n | |*****| ||/***|| ||/O| |\n | |/*** | | / *\\ | | / | |\n | |][][\\/ \\/][][\\/ \\/][| |\n | |\\ /| |\\ /| |\\ | |\n | |_||_| |_||_| |_|| |\n | | ][ ] [ ][ ] [ ]| |\n | \\_|_|___|_||_|____|_/ |\n | |\n1\n | ___________________ |\n | /__\\ /__\\ /\\ |\n | |<><>| |<><>| |<>| |\n | |_/\\_) (_/\\_) (_/| |\n | | * \\ / *** \\ / | |\n | |/***|| ||*****| ||/*| |\n | |/ *\\ | | /*** | | / | |\n | |][][\\/ \\/][][\\/ \\/][| |\n | |\\ /| |\\ /| |\\ | |\n | |_||_| |_||_| |_|| |\n | | ][ ] [ ][ ] [ ]| |\n | \\_|_|___|_||_|____|_/ |\n | |\n1\n | ___________________ |\n | /__\\ /__\\ /\\ |\n | |<><>| |<><>| |<>| |\n | |_/\\_) (_/\\_) (_/| |\n | | \\ / * \\ / *| |\n | |/=* || ||/***|| ||**| |\n | |/ \\ | | / *\\ | | /*| |\n | |][][\\/ \\/][][\\/ \\/][| |\n | |\\ /| |\\ /| |\\ | |\n | |_||_| |_||_| |_|| |\n | | ][ ] [ ][ ] [ ]| |\n | \\_|_|___|_||_|____|_/ |\n | |\n1\n | ___________________ |\n | /__\\ /__\\ /\\ |\n | |<><>| |<><>| |<>| |\n | |_/\\_) (_/\\_) (_/| |\n | | \\ / \\ / | |\n | |/=O || ||/=*\\|| ||/*| |\n | |/ \\ | | / \\ | | / | |\n | |][][\\/ \\/][][\\/ \\/][| |\n | |\\ /| |\\ /| |\\ | |\n | |_||_| |_||_| |_|| |\n | | ][ ] [ ][ ] [ ]| |\n | \\_|_|___|_||_|____|_/ |\n | |\n1\n | ___________________ |\n | /__\\ /__\\ /\\ |\n | |<><>| |<><>| |<>| |\n | |_/\\_) (_/\\_) (_/| |\n | | \\ / \\ / | |\n | |/=O || ||/=O\\|| ||/=| |\n | |/ \\ | | / \\ | | / | |\n | |][][\\/ \\/][][\\/ \\/][| |\n | |\\ /| |\\ /| |\\ | |\n | |_||_| |_||_| |_|| |\n | | ][ ] [ ][ ] [ ]| |\n | \\_|_|___|_||_|____|_/ |\n | |\n1\n | ___________________ |\n | /__\\ /__\\ /\\ |\n | |<><>| |<><>| |<>| |\n | |_/\\_) (_/\\_) (_/| |\n | | \\ / \\ / | |\n | |/=* || ||/=O\\|| ||/=| |\n | |/ \\ | | / \\ | | / | |\n | |][][\\/ \\/][][\\/ \\/][| |\n | |\\ /| |\\ /| |\\ | |\n | |_||_| |_||_| |_|| |\n | | ][ ] [ ][ ] [ ]| |\n | \\_|_|___|_||_|____|_/ |\n | |\n1\n | ___________________ |\n | /__\\ /__\\ /\\ |\n | |<><>| |<><>| |<>| |\n | |_/\\_) (_/\\_) (_/| |\n | | * \\ / \\ / | |\n | |/***|| ||/=*\\|| ||/=| |\n | |/ *\\ | | / \\ | | / | |\n | |][][\\/ \\/][][\\/ \\/][| |\n | |\\ /| |\\ /| |\\ | |\n | |_||_| |_||_| |_|| |\n | | ][ ] [ ][ ] [ ]| |\n | \\_|_|___|_||_|____|_/ |\n | |\n1\n | ___________________ |\n | /__\\ /__\\ /\\ |\n | |<><>| |<><>| |<>| |\n | |_/\\_) (_/\\_) (_/| |\n | | *** \\ / * \\ / | |\n | |*****| ||/***|| ||/=| |\n | |/*** | | / *\\ | | / | |\n | |][][\\/ \\/][][\\/ \\/][| |\n | |\\ /| |\\ /| |\\ | |\n | |_||_| |_||_| |_|| |\n | | ][ ] [ ][ ] [ ]| |\n | \\_|_|___|_||_|____|_/ |\n | |\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n1\n /~___\\ | |\n /_/o o| | |\n _\\ -/_ | |\n / \\ / \\ | |\n //__ __|\\\\ | |\n \\--([==o \\\\| | |\n | | \\\\ | |\n |====| \')| |\n | || | | |\n____________________( )( )_____| |\n | || | \\ |\n |_||_| \\ |\n [_][__\\ \\|_______________________________\n1\n /~___\\ | |\n /_/o o| | |\n _\\ -/_ | |\n / \\ / \\ | |\n //__ __|\\\\ | |\n \\--([==* -- | |\n | | \\\\ | |\n |====| \')| |\n | || | | |\n____________________( )( )_____| |\n | || | \\ |\n |_||_| \\ |\n [_][__\\ \\|_______________________________\n1\n /~___\\ | |\n /_/o o| | |\n _\\ -/_ | | ---\n / \\ / \\ | |\n //__ __*\\\\ | |\n \\--([=*** \\ -----\n | * \\\\ | |\n |====| \')| |\n | || | | |\n____________________( )( )_____| |\n | || | \\ |\n |_||_| \\ |\n [_][__\\ \\|_______________________________\n1\n /~___\\ | |\n /_/o o| | |\n _\\ -/_ | | -----\n / \\ / \\ | |\n //__ _***\\ | |\n \\--([*****\\ | |-----\n | *** \\\\ | |\n |====| \')| |\n | || | | |\n____________________( )( )_____| |\n | || | \\ |\n |_||_| \\ |\n [_][__\\ \\|_______________________________\n1\n /~___\\ | |\n /_/o o| | |\n _\\ -/_ | | -----\n / \\ / \\ | |\n //__ __* \\ | |\n \\--([=***\\\\ | | -----\n | * \\\\ | |\n |====| \')| |\n | || | | |\n____________________( )( )_____| |\n | || | \\ |\n |_||_| \\ |\n [_][__\\ \\|_______________________________\n1\n /~___\\ | |\n /_/o o| | |\n _\\ -/_ | | -----\n / \\ / \\ | |\n //__ __|\\\\ | |\n \\--([==* \\\\ | | -----\n | | \\\\ | |\n |====| \')| |\n | || | | |\n____________________( )( )_____| |\n | || | \\ |\n |_||_| \\ |\n [_][__\\ \\|_______________________________\n1\n /~___\\ | |\n /_/o o| | |\n _\\ -/_ | | -----\n / \\ / \\ | |\n //__ __|\\\\ | |\n \\--([==o \\\\ | | -----\n | | \\\\ | |\n |====| \')| |\n | || | | |\n____________________( )( )_____| |\n | || | \\ |\n |_||_| \\ |\n [_][__\\ \\|_______________________________\n1\n /~___\\ | |\n /_/o o| | |\n _\\ -/_ | | -----\n / \\ / \\ | |\n //__ __|\\\\ | |\n \\--([==o \\\\ | | -----\n | | \\\\ | |\n |====| \')| |\n | || | | |\n____________________( )( )_____| |\n | || | \\ |\n |_||_| \\ |\n [_][__\\ \\|_______________________________\n1\n /~___\\ | |\n /_/o o| | |\n _\\ -/_ | *--\n / \\ / \\ | |\n //__ __|\\\\ | |\n \\--([==o \\\\ | | -----\n | | \\\\ | |\n |====| \')| |\n | || | | |\n____________________( )( )_____| |\n | || | \\ |\n |_||_| \\ |\n [_][__\\ \\|_______________________________\n1\n /~___\\ | |\n /_/o o| | .* \'\n _\\ -/_ | ***\n / \\ / \\ | *\n //__ __|\\\\ | | \' ----\n \\--([==* -- | | -\n | | \\\\ | |\n |====| \')| |\n | || | | |\n____________________( )( )_____| |\n | || | \\ |\n |_||_| \\ |\n [_][__\\ \\|_______________________________\n1\n /~___\\ |: * # \'\n /_/- -| | ***\n _\\ -/_ | *****\n / \\ / \\ |# *** .\n //__ __*\\\\ | * # -----\n \\--([=***\\\\----- | \'\n | * \\\\ | |\n |====| \')| |\n | || | | |\n____________________( )( )_____| |\n | || | \\ |\n |_||_| \\ |\n [_][__\\ \\|_______________________________\n1\n /~___\\ \' | * #\n /_/- -| | *** \'\n _\\ o/_ \' *****\n / \\ / \\ | *** \'\n //__ _***\\ # * -----\n \\--([*****\\ | .-----\n | *** \\\\ | | #\n |====| \')| . | \'\n | || | | |\n____________________( )( )_____| |\n | || | \\ |\n |_||_| \\ |\n [_][__\\ \\|_______________________________\n1\n /~___\\ \' | *\n /_/0 0| | */|\\* \' \'\n _\\ o/_ |*|\\|| *\n / \\ / \\ \' | *\\|/*\n //__ __*\\\\ | * -----\n \\--([=***\\\\ | | ----- \'\n | * #\\ | |\n |====| \')| | \'\n | || | |\' | #\n____________________( )( )___._| |\n | || | \\ |\n |_||_| \\ |\n [_][__\\ \\|_______________________________\n1\n /~___\\ | |\n /_/o o| | /*\\ \'\n _\\ -/_ | |*|*\n / \\ / \\ | \\*/\n //__ __|\\\\ | | -----\n \\--([==* \\\\ | | -----\n | | \\\\ | |\n |====| \')| | \'\n | || |# | |\n____________________( )( )_____| |\n | || | \\ | #\n |_||_| \\ | \'\n [_][__\\\' \\|_______________________________\n1\n /~___\\ | |\n /_/o o| | /|\\\n _\\ -/_ | | ||\n / \\ / \\ | \\|/\n //__ __|\\\\ | | -----\n \\--([==o \\\\ | | -----\n | | \\\\ | |\n |====| \')| |\n | || | | |\n____________________( )( )_____| |\n | |# | \\ |\n |_||_| \\ |\n [_][__\\ \\|___________#___________________\n1\n /~___\\ | |\n /_/o o| | /|\\\n _\\ -/_ | | ||\n / \\ / \\ | \\|/\n //__ __|\\\\ | -----\n \\--([==o \\\\ | | -----\n | | \\\\ | |\n |====| \')| |\n | || | | |\n____________________( )( )_____| |\n | || | \\ |\n |_||_| \\ | #\n #[_][__\\ \\|_______________________________\n1\n /~___\\ | |\n /_/o o| | /|\\\n _\\ -/_ | | ||\n / \\ / \\ | \\|/\n //__ __|\\\\----- |\n \\--([==o \\\\ | | -----\n | | \\\\ | |\n |====| \')| |\n | || | | |\n____________________( )( )_____| |\n | || | \\ | #\n |_||_| \\ |\n [_][__\\ \\|_______________________________\n1\n /~___\\ | |\n /_/o o| | /|\\\n _\\ o/_ | | ||\n / \\ / \\ | \\|/\n //__ *---- | |\n \\--([==o \\\\ | | ---\n | | \\\\ | |\n |====| \')| |\n | || | | |\n____________________( )( )_____| |\n | || | \\ | #\n |_||_| \\ |\n [_][__\\ \\|_______________________________\n1\n /~___\\ | |\n /_/- o| | /|\\\n _\\ O/_ | | ||\n / \\*/ \\ | \\|/\n //__***|\\\\ | |\n \\--([*=o \\\\ | |\n | | \\\\ | |\n |====| \')| |\n | || | | |\n___________________( )( )_____| |\n | || | \\ |\n |_||_| \\ | #\n [_][__\\ \\|________________________________\n1\n /~___\\ | |\n /_/x x| | /|\\\n _\\ O/_ | | ||\n / *** \\ | \\|/\n //_*****\\\\ | |\n \\--(***o \\\\ | |\n | | \\\\ | |\n |====| \')| |\n | || | | |\n____________________( )( )_____| |\n | || | \\ |\n |_||_| \\ |\n [_][__\\ \\|____________________#__________\n1\n /~___\\ | |\n /_/x x| | /|\\\n _\\***_ | | ||\n / *****\\ | \\|/\n //*******\\ | |\n \\--***** \\\\ | |\n | ***| \\\\ | |\n |====| \')| |\n | || | | |\n____________________( )( )_____| |\n | || | \\ |\n |_||_| \\ | #\n [_][__\\ \\|_______________________________\n1\n /~___\\ | |\n /_/x x| | /|\\\n _\\ -/_ | | ||\n / *** \\ | \\|/\n //_*****\\\\ | |\n \\--(***o \\\\ | |\n | | \\\\ | |\n |====| \')| |\n | || | | |\n____________________( )( )_____| |\n | || | \\ |\n |_||_| \\ |\n [_][__\\ \\|______________________#________\n1\n /~___\\ | |\n /_/x x| | /|\\\n _\\ -/_ | | ||\n / \\*/ \\ | \\|/\n // ***|\\\\ | |\n \\\\ * | \\\\ | |\n \\\\ | \\\\ | |\n [==o=| \')| |\n /| || | | |\n____________________( )( )_____| |\n | || | \\ |\n |_||_| \\ |\n [_][__\\ \\|_______________________#_______\n3\n /~___\\ | |\n /_/x x| | /|\\\n _\\ -/_ | | ||\n / \\ / \\ | \\|/\n // |\\\\ | |\n || | \\\\ | |\n || | | \\\\ | |\n || |====| \')| |\n (\' | || | | |\n____________________( )( )_____| |\n [==o| || | \\ |\n / |_||_| \\ |\n [_][__\\ \\|________________________#______\n6\n\n\n\n\n\n\n\n\n\n\n\n\n\n10\n __ /~~\\ __\n /__\\ |<><>| /__\\\n |<><>| /_/\\_\\ |<><>|\n (_/\\_) /\\___/\\ (_/\\_)\n / \\ // [ ]|\\\\ / \\\n ||/(===o ||| [_]| \\\\ //| __ |\\\\\n | / \\ | ||| | \\\\ || |/ \\| \\\\\n \\/][][\\/ |||====| \\\\ || [][][] \\\\\n |\\ /| #/|\\ /I\\ # || |\\ /| \')\n |_||_| / | || I \\ \'] |_||_|\n [ ][ ] / | || | \\ [I [ ][ ]\n | || | / | || | \\ I | || |\n | || | / | || | \\ | || |\n6\n __ /~~\\ __\n /__\\ |<><>| /__\\\n |<><>| /_/\\_\\ |<><>|\n (_/\\_) /\\___/\\ (_/\\_)\n / \\ // [ ]|\\\\ / \\\n ||/(===o ||| [_]| \\\\ ||/(===o\\\n | / \\ | ||| | \\\\ | / \\| \\\\\n \\/][][\\/ |||====| \\\\ \\/][][] \\\\\n |\\ /| #/|\\ /I\\ # |\\ /| \')\n |_||_| / | || I \\ |_||_|\n [ ][ ] / | || | \\ [ ][ ]\n | || | / | || | \\ | || |\n | || | / | || | \\ | || |\n18\n __ /~~\\ __\n /__\\ |<><>| /__\\\n |<><>| /_/\\_\\ |<><>|\n (_/\\_) /\\___/\\ (_/\\_)\n / \\ // [ ]|\\\\ / \\\n ||/(===o //| [_]| \\\\ ||/(===o\n | / \\ | \\\\| | // | / \\||\n \\/][][\\/ \\#====|#/ \\/][][\\/\n |\\ /| /|\\ /I\\ |\\ /|\n |_||_| / | || I \\ |_||_|\n [ ][ ] / | || | \\ [ ][ ]\n | || | / | || | \\ | || |\n | || | / | || | \\ | || |\n4\n\n\n\n\n\n\n\n\n\n\n\n\n\n30\n /~~\\\n |<><>| Commander, tear this ship apart\n /_/\\_\\ until you\'ve found those plans.\n /\\___/\\\n // [ ]|\\\\\n //| [_]| \\\\\n \\\\| | //\n \\#====|#/\n /|\\ /I\\\n / | || I \\\n / | || | \\\n / | || | \\\n / | || | \\\n2\n /~~\\\n |<><>|\n /_/\\_\\\n /\\___/\\\n // [ ]|\\\\\n //| [_]| \\\\\n \\\\| | //\n \\#====|#/\n /|\\ /I\\\n / | || I \\\n / | || | \\\n / | || | \\\n / | || | \\\n30\n /~~\\\n |<><>| And bring me the passengers.\n /_/\\_\\ # I want them alive!\n /\\___/\\ //\n // [ ]|\\\\//\n //| [_]| \\/\n \\\\| |\n \\#====|\n /|\\ /I\\\n / | || I \\\n / | || | \\\n / | || | \\\n / | || | \\\n5\n /~~\\\n |<><>|\n /_/\\_\\\n /\\___/\\\n // [ ]|\\\\\n //| [_]| \\\\\n \\\\| | //\n \\#====|#/\n /|\\ /I\\\n / | || I \\\n / | || | \\\n / | || | \\\n / | || | \\\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n11\n /~\\\n |oo )\n _\\=/_\n / _ \\\n //|/.\\|\\\\\n \\\\ \\_/ ||\n \\|\\ /| ||\n # _ _/ #\n | | |\n | | |\n []|[]\n | | |\n_______________________________/_]_[_\\_____________________________\n11\n /~\\\n ( oo|\n _\\=/_\n / _ \\\n //|/.\\|\\\\\n \\\\ \\_/ ||\n \\|\\ /| ||\n # _ _/ #\n | | |\n | | |\n []|[]\n | | |\n_______________________________/_]_[_\\_____________________________\n11\n /~\\\n |oo )\n _\\=/_\n / _ \\\n //|/.\\|\\\\\n \\\\ \\_/ ||\n \\|\\ /| ||\n # _ _/ #\n | | |\n | | |\n []|[]\n | | |\n_______________________________/_]_[_\\_____________________________\n11\n /~\\\n ( oo|\n _\\=/_\n / _ \\\n //|/.\\|\\\\\n \\\\ \\_/ ||\n \\|\\ /| ||\n # _ _/ #\n | | |\n | | |\n []|[]\n | | |\n_______________________________/_]_[_\\_____________________________\n6\n /~\\\n |oo )\n _\\=/_\n / _ \\\n //|/.\\|\\\\\n || \\_/ ||\n || |\\ /| ||\n # \\_ _/ #\n | | |\n | | |\n []|[]\n | | |\n_______________________________/_]_[_\\_____________________________\n6\n /~\\\n R2-D2! |oo )\n Where are you? _\\=/_\n / _ \\\n //|/.\\|\\\\\n || \\_/ ||\n || |\\ /| ||\n # \\_ _/ #\n | | |\n | | |\n []|[]\n | | |\n_______________________________/_]_[_\\_____________________________\n9\n /~\\\n R2-D2! |oo )\n Where are you? # _\\=/_ #\n \\\\ / _ \\ //\n \\\\//|/.\\|\\\\//\n \\/ \\_/ \\/\n |\\ /|\n \\_ _/\n | | |\n | | |\n []|[]\n | | |\n_______________________________/_]_[_\\_____________________________\n9\n /~\\\n R2-D2! |oo )\n Where are you? # _\\=/_ #\n \\\\ / _ \\ //\n \\\\//|/.\\|\\\\//\n \\/ \\_/ \\/\n |\\ /|\n \\_ _/\n | | |\n | | |\n []|[]\n | | |\n_______________________________/_]_[_\\_____________________________\n8\n /~\\\n ( oo|\n # _\\=/_ #\n \\\\ / _ \\ //\n \\\\//|/.\\|\\\\//\n \\/ \\_/ \\/\n |\\ /|\n \\_ _/\n | | |\n | | |\n []|[]\n | | |\n_______________________________/_]_[_\\_____________________________\n6\n\n\n\n\n\n\n\n\n\n\n\n\n\n11\n ,===\n (@o o@\n \\ -/\n //~ ~~\\ ___\n / ( ) \\ /() \\\n /_/\\ /\\_| _|_____|_\n \\\\ \\\\ /| || | | === | |\n @ | | | @ |_| O |_|\n | | | || O ||\n | | | ||__*__||\n / | \\ |~ \\___/ ~|\n ~~~~~~~ /=\\ /=\\\n______________________(_)(__\\______[_]_____[_]_____________________\n11\n ,===\n (@o o@\n \\ -/\n //~ ~~\\ ___\n / ( ) \\ / ()\\\n /_/\\ /\\_| _|_____|_\n \\\\ \\\\ /| || | | === | |\n @| | | @ |_| O |_|\n | | | || O ||\n | | | ||__*__||\n / | \\ |~ \\___/ ~|\n ~~~~~~~ /=\\ /=\\\n______________________(_)(__\\______[_]_____[_]_____________________\n8\n\n ,===\n (@o o@\n / \\_-/ ___\n /| |) ) /() \\\n | \\ \\/__ _|_____|_\n | \\____@=| | === | |\n | | |_| O |_|\n | | | || O ||\n | | | ||__*__||\n / | \\ |~ \\___/ ~|\n ~~~~~~~ /=\\ /=\\\n_______________________(_)(__\\_____[_]_____[_]_____________________\n11\n\n ,===\n (@o o@\n / \\_-/ ___\n /| |) ) / ()\\\n | \\ \\/__ _|_____|_\n | \\____@=| | === | |\n | | |_| O |_|\n | | | || O ||\n | | | ||__*__||\n / | \\ |~ \\___/ ~|\n ~~~~~~~ /=\\ /=\\\n_______________________(_)(__\\_____[_]_____[_]_____________________\n7\n\n ,===\n (@o o@\n / \\_-/ ___\n /| |) ) /() \\\n | \\ \\/__ _|_____|_\n | \\____@=| | === | |\n | | |_| O |_|\n | | | || O ||\n | | | ||__*__||\n / | \\ |~ \\___/ ~|\n ~~~~~~~ /=\\ /=\\\n_______________________(_)(__\\_____[_]_____[_]_____________________\n6\n\n ===,\n @o o@)\n / \\-_/ ___\n /| |) ) /() \\\n | \\ \\/__ _|_____|_\n | \\____@=| | === | |\n | | |_| O |_|\n | | | || O ||\n | | | ||__*__||\n / | \\ |~ \\___/ ~|\n ~~~~~~~ /=\\ /=\\\n_______________________(_)(__\\_____[_]_____[_]_____________________\n16\n\n ,===\n (@o o@\n / \\_-/ ___\n /| |) ) /() \\\n | \\ \\/__ _|_____|_\n | \\____@=| | === | |\n | | |_| O |_|\n | | | || O ||\n | | | ||__*__||\n / | \\ |~ \\___/ ~|\n ~~~~~~~ /=\\ /=\\\n_______________________(_)(__\\_____[_]_____[_]_____________________\n7\n ===,\n @o o@)\n \\- /\n //~ ~~\\ ___\n / ( ) \\ /() \\\n /_/\\ /\\_| _|_____|_\n \\\\ \\\\ /| || | | === | |\n @| | | @ |_| O |_|\n | | | || O ||\n | | | ||__*__||\n / | \\ |~ \\___/ ~|\n ~~~~~~~ /=\\ /=\\\n_______________________(_)(__\\_____[_]_____[_]_____________________\n1\n ===,\n @o o@)\n \\- /\n //~ ~~\\ ___\n / ( ) \\ /() \\\n /_/\\ /\\_| _|_____|_\n \\\\ \\\\ /| || | | === | |\n @| | | @ |_| O |_|\n | | | || O ||\n | | | ||__*__||\n / | \\ |~ \\___/ ~|\n ~~~~~~~ /=\\ [_] /=\\\n_______________________(_)(__\\_____[_]_____[_]_____________________\n10\n ===,\n @o o@)\n \\- /\n //~ ~~\\ ___\n / ( ) \\ /() \\\n /_/\\ /\\_| _|_____|_\n \\\\ \\\\ /| || | | === | |\n @| | | @ |_| O |_|\n | | | || O ||\n | | | ||__*__||\n / | \\ |~ \\___/ ~|\n ~~~~~~~ /=\\ /=\\ /=\\\n_______________________(_)(__\\_____[_]_[_]_[_]_____________________\n13\n ,===\n (@o o@\n \\ -/\n //~ ~~\\ ___\n / ( ) \\ /() \\\n /_/\\ /\\_| _|_____|_\n \\\\ \\\\ /| || | | === | |\n @ | | | @ |_| O |_|\n | | | || O ||\n | | | ||__*__||\n / | \\ |~ \\___/ ~|\n ~~~~~~~ /=\\ /=\\ /=\\\n_______________________(_)(__\\_____[_]_[_]_[_]_____________________\n4\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n /() \\ //|/.\\|\\\\\n _|_____|_ \\\\ \\_/ ||\n | | === | | \\|\\ /| ||\n |_| O |_| # _ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n5\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n / ()\\ //|/.\\|\\\\\n _|_____|_ || \\_/ ||\n | | === | | || |\\ /| ||\n |_| O |_| # \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n20\n /~\\\n |oo ) At last!\n _\\=/_\n ___ / _ \\\n / ()\\ //|/.\\|\\\\\n _|_____|_ || \\_/ ||\n | | === | | || |\\ /| ||\n |_| O |_| # \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n4\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n / ()\\ //|/.\\|\\\\\n _|_____|_ || \\_/ ||\n | | === | | || |\\ /| ||\n |_| O |_| # \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n7\n /~\\\n |oo ) Where have\n _\\=/_ you been?\n ___ # / _ \\\n / ()\\ \\\\//|/.\\|\\\\\n _|_____|_ \\/ \\_/ ||\n | | === | | |\\ /| ||\n |_| O |_| \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n4\n /~\\\n |oo ) Where have\n _\\=/_ you been?\n ___ # / _ \\\n / ()\\ \\\\//|/.\\|\\\\\n _|_____|_ \\/ \\_/ ||\n | | === | | |\\ /| ||\n |_| O |_| \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n9\n /~\\\n |oo ) Where have\n _\\=/_ you been?\n ___ # / _ \\\n / ()\\ \\\\//|/.\\|\\\\\n _|_____|_ \\/ \\_/ ||\n | | === | | |\\ /| ||\n |_| O |_| \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n4\n /~\\\n |oo )\n _\\=/_\n ___ # / _ \\\n / ()\\ \\\\//|/.\\|\\\\\n _|_____|_ \\/ \\_/ ||\n | | === | | |\\ /| ||\n |_| O |_| \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n6\n /~\\\n |oo )\n _\\=/_\n ___ # / _ \\ #\n /() \\ \\\\//|/.\\|\\\\//\n _|_____|_ \\/ \\_/ \\/\n | | === | | |\\ /|\n |_| O |_| \\_ _/\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n6\n /~\\\n |oo )\n _\\=/_\n ___ # / _ \\\n / ()\\ \\\\//|/.\\|\\\\\n _|_____|_ \\/ \\_/ ||\n | | === | | |\\ /| ||\n |_| O |_| \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n3\n /~\\\n |oo )\n _\\=/_\n ___ # / _ \\\n /() \\ \\\\//|/.\\|\\\\\n _|_____|_ \\/ \\_/ ||\n | | === | | |\\ /| ||\n |_| O |_| \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n5\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n / ()\\ //|/.\\|\\\\\n _|_____|_ || \\_/ ||\n | | === | | || |\\ /| ||\n |_| O |_| # \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n3\n /~\\\n |oo )\n _\\=/_\n ___ # / _ \\\n / ()\\ \\\\//|/.\\|\\\\\n _|_____|_ \\/ \\_/ ||\n | | === | | |\\ /| ||\n |_| O |_| \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n6\n /~\\\n |oo )\n _\\=/_\n ___ # / _ \\ #\n /() \\ \\\\//|/.\\|\\\\//\n _|_____|_ \\/ \\_/ \\/\n | | === | | |\\ /|\n |_| O |_| \\_ _/\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n6\n /~\\\n |oo )\n _\\=/_\n ___ # / _ \\\n / ()\\ \\\\//|/.\\|\\\\\n _|_____|_ \\/ \\_/ ||\n | | === | | |\\ /| ||\n |_| O |_| \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n3\n /~\\\n |oo )\n _\\=/_\n ___ # / _ \\\n /() \\ \\\\//|/.\\|\\\\\n _|_____|_ \\/ \\_/ ||\n | | === | | |\\ /| ||\n |_| O |_| \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n5\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n / ()\\ //|/.\\|\\\\\n _|_____|_ || \\_/ ||\n | | === | | || |\\ /| ||\n |_| O |_| # \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n21\n /~\\\n |oo ) Secret mission?\n _\\=/_\n ___ / _ \\\n / ()\\ //|/.\\|\\\\\n _|_____|_ || \\_/ ||\n | | === | | || |\\ /| ||\n |_| O |_| # \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n3\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n /() \\ //|/.\\|\\\\\n _|_____|_ || \\_/ ||\n | | === | | || |\\ /| ||\n |_| O |_| # \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n12\n /~\\\n |oo ) What plans?\n _\\=/_\n ___ / _ \\\n / ()\\ //|/.\\|\\\\\n _|_____|_ || \\_/ ||\n | | === | | || |\\ /| ||\n |_| O |_| # \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n6\n /~\\\n |oo ) What plans?\n _\\=/_\n ___ / _ \\\n / ()\\ //|/.\\|\\\\\n _|_____|_ || \\_/ ||\n | | === | | || |\\ /| ||\n |_| O |_| # \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n8\n /~\\\n |oo ) What plans?\n _\\=/_\n ___ / _ \\\n / ()\\ //|/.\\|\\\\\n _|_____|_ || \\_/ ||\n | | === | | || |\\ /| ||\n |_| O |_| # \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n6\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n / ()\\ //|/.\\|\\\\\n _|_____|_ || \\_/ ||\n | | === | | || |\\ /| ||\n |_| O |_| # \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n4\n\n\n\n\n\n\n\n\n\n\n\n\n\n3\n /__\\ /__\\\n |<><>| |<><>|\n (_/\\_) (_/\\_)\n / \\ / \\\n //| __ |\\\\ ||/(===o\n // |/ \\| \\\\ | / \\ |\n // [][][] || \\/][][\\/\n |\' |\\ /| [\' |\\ /|\n |_||_| I] |_||_|\n [ ][ ] I [ ][ ]\n | || | | || |\n |_||_| |_||_|\n__________________________/__][_]_________[_][__\\__________________\n3\n /__\\ /__\\\n |<><>| |<><>|\n (_/\\_) (_/\\_)\n / \\ / \\\n //| __ |\\\\ ||/(===o\n // |/ \\| \\\\ | / \\ |\n // [][][] || \\/][][\\/\n |\' |\\ /| [\' |\\ /|\n |_||_| I] |_||_|\n [ ][ ] I [ ][ ]\n | || | | || |\n |_||_| |_||_|\n___________________________/__][_]_________[_][__\\_________________\n3\n /__\\ /__\\\n |><> | |<><>|\n (/\\__) (_/\\_)\n / \\ / \\\n //| __ |\\\\ ||/(===o\n // |/ \\| \\\\ | / \\ |\n // [][][] || \\/][][\\/\n |\' |\\ /| [\' |\\ /|\n |_||_| I] |_||_|\n [ ][ ] I [ ][ ]\n | || | | || |\n |_||_| |_||_|\n____________________________/__][_]_________[_][__\\________________\n3\n /__\\ /__\\\n |><> | |<><>|\n (/\\__) (_/\\_)\n / \\ / \\\n //| __ |\\\\ ||/(===o\n // |/ \\| \\\\ | / \\ |\n // [][][] || \\/][][\\/\n |\' |\\ /| [\' |\\ /|\n |_||_| I] |_||_|\n [ ][ ] I [ ][ ]\n | || | | || |\n |_||_| |_||_|\n_____________________________/__][_]_________[_][__\\_______________\n3\n /__\\ /__\\\n |><> | |<><>|\n (/\\__) (_/\\_)\n / \\ / \\\n //| __ |\\\\ ||/(===o\n // |/ \\| \\\\ | / \\ |\n // [][][] || \\/][][\\/\n |\' |\\ /| [\' |\\ /|\n |_||_| I] |_||_|\n [ ][ ] I [ ][ ]\n | || | | || |\n |_||_| |_||_|\n______________________________/__][_]_________[_][__\\______________\n3\n /__\\ /__\\\n |><> | |><> |\n (/\\__) (/\\__)\n / \\ / \\\n //| __ |\\\\ ||/(===o\n // |/ \\| \\\\ | / \\ |\n // [][][] || \\/][][\\/\n |\' |\\ /| [\' |\\ /|\n |_||_| I] |_||_|\n [ ][ ] I [ ][ ]\n | || | | || |\n |_||_| |_||_|\n_______________________________/__][_]_________[_][__\\_____________\n3\n /__\\ /__\\\n |><> | |><> |\n (/\\__) (/\\__)\n / \\ / \\\n\\ //| __ |\\\\ ||/(===o\n| // |/ \\| \\\\ | / \\ |\n| // [][][] || \\/][][\\/\n |\' |\\ /| [\' |\\ /|\n |_||_| I] |_||_|\n [ ][ ] I [ ][ ]\n | || | | || |\n |_||_| |_||_|\n________________________________/__][_]_________[_][__\\____________\n3\n /__\\ /__\\\n |><> | |><> |\n (/\\__) (/\\__)\n\\ / \\ / \\\n \\ //| __ |\\\\ ||/(===o\no| // |/ \\| \\\\ | / \\ |\n|| // [][][] || \\/][][\\/\n@ |\' |\\ /| [\' |\\ /|\n |_||_| I] |_||_|\n [ ][ ] I [ ][ ]\n | || | | || |\n |_||_| |_||_|\n_________________________________/__][_]_________[_][__\\___________\n3\n /__\\ /__\\\n@ |><> | |><> |\n (/\\__) (/\\__)\n~\\ / \\ / \\\n\\ \\ //| __ |\\\\ ||/(===o\n=o| // |/ \\| \\\\ | / \\ |\n || // [][][] || \\/][][\\/\n @ |\' |\\ /| [\' |\\ /|\n |_||_| I] |_||_|\n [ ][ ] I [ ][ ]\n\\ | || | | || |\n~ |_||_| |_||_|\n\\_________________________________/__][_]_________[_][__\\__________\n3\n= /__\\ /__\\\no@ |><> | |><> |\n/ (/\\__) (/\\__)\n~~\\ / \\ / \\\n)\\ \\ //| __ |\\\\ ||/(===o\n==o| // |/ \\| \\\\ | / \\ |\n| || // [][][] || \\/][][\\/\n| @ |\' |\\ /| [\' |\\ /|\n| |_||_| I] |_||_|\n| [ ][ ] I [ ][ ]\n \\ | || | | || |\n~~ |_||_| |_||_|\n_\\_________________________________/__][_]_________[_][__\\_________\n3\n== /__\\ /__\\\n o@ |><> | |><> |\n-/ (/\\__) (/\\__)\n ~~\\ / \\ / \\\n )\\ \\ //| __ |\\\\ ||/(===o\n@==o| // |/ \\| \\\\ | / \\ |\n | || // [][][] || \\/][][\\/\n | @ |\' |\\ /| [\' |\\ /|\n | |_||_| I] |_||_|\n | [ ][ ] I [ ][ ]\n \\ | || | | || |\n~~~ |_||_| |_||_|\n(_\\_________________________________/__][_]_________[_][__\\________\n3\n=== /__\\ /__\\\no o@ |><> | |><> |\n -/ (/\\__) (/\\__)\n ~~\\ / \\ / \\\n_ )\\ \\ //| __ |\\\\ ||/(===o\n/@==o| // |/ \\| \\\\ | / \\ |\n /| || // [][][] || \\/][][\\/\n| | @ |\' |\\ /| [\' |\\ /|\n| | |_||_| I] |_||_|\n| | [ ][ ] I [ ][ ]\n| \\ | || | | || |\n~~~~ |_||_| |_||_|\n)(_\\_________________________________/__][_]_________[_][__\\_______\n3\n,=== /__\\ /__\\\n@o o@ |><> | |><> |\n\\ -/ (/\\__) (/\\__)\n~ ~~\\ / \\ / \\\n__ )\\ \\ //| __ |\\\\ ||/(===o\n_/@==o| // |/ \\| \\\\ | / \\ |\n\\ /| || // [][][] || \\/][][\\/\n | | @ |\' |\\ /| [\' |\\ /|\n | | |_||_| I] |_||_|\n | | [ ][ ] I [ ][ ]\n | \\ | || | | || |\n~~~~~ |_||_| |_||_|\n_)(_\\_________________________________/__][_]_________[_][__\\______\n3\n ,=== /__\\ /__\\\n(@o o@ |><> | |><> |\n \\ -/ (/\\__) (/\\__)\n/~ ~~\\ / \\ / \\\n\\__ )\\ \\ //| __ |\\\\ ||/(===o\n\\_/@==o| // |/ \\| \\\\ | / \\ |\n\\\\ /| || // [][][] || \\/][][\\/\n| | | @ |\' |\\ /| [\' |\\ /|\n| | | |_||_| I] |_||_|\n| | | [ ][ ] I [ ][ ]\n | \\ | || | | || |\n~~~~~~ |_||_| |_||_|\n(_)(_\\_________________________________/__][_]_________[_][__\\_____\n3\n ,=== /__\\ /__\\\n (@o o@ |><> | |><> |\n \\ -/ (/\\__) (/\\__)\n//~ ~~\\ / \\ / \\\n \\__ )\\ \\ //| __ |\\\\ ||/(===o\n\\\\_/@==o| // |/ \\| \\\\ | / \\ |\n |\\ /| || // [][][] || \\/][][\\/\n | | | @ |\' |\\ /| [\' |\\ /|\n | | | |_||_| I] |_||_|\n | | | [ ][ ] I [ ][ ]\n/ | \\ | || | | || |\n~~~~~~~ |_||_| |_||_|\n_(_)(_\\_________________________________/__][_]_________[_][__\\____\n2\n ,=== /__\\ /__\\\n (@o o@ |><> | |><> |\n \\ -/ (/\\__) (/\\__)\n //~ ~~\\ / \\ / \\\n\\ \\__ )\\ \\ //| __ |\\\\ ||/(===o\n \\\\_/@==o| // |/ \\| \\\\ | / \\ |\n |\\ /| || // [][][] || \\/][][\\/\n | | | @ |\' |\\ /| [\' |\\ /|\n | | | |_||_| I] |_||_|\n | | | [ ][ ] I [ ][ ]\n / | \\ | || | | || |\n ~~~~~~~ |_||_| |_||_|\n__(_)(_\\_________________________________/__][_]_________[_][__\\___\n1\n ,=== /__\\ /__\\\n (@o o@ |><> | |><> |\n \\ -/ (/\\__) (/\\__)\n //~ ~~\\ / \\ / \\\n\\ \\__ )\\\\\\ //| __ |\\\\ ||/(===o\n \\\\_/@==o| // |/ \\| \\\\ | / \\ |\n |\\ /| || // [][][] || \\/][][\\/\n | | | @ |\' |\\ /| [\' |\\ /|\n | | | |_||_| I] |_||_|\n | | | [ ][ ] I [ ][ ]\n / | \\ | || | | || |\n ~~~~~~~ |_||_| |_||_|\n__(_)(_\\_________________________________/__][_]_________[_][__\\___\n7\n ,=== /__\\ /__\\\n (@o o@ |><> | |><> |\n \\ -/ (/\\__) (/\\__)\n //~ ~~\\ / \\ / \\\n\\ \\__ )\\ \\ //| __ |\\\\ ||/(===o\n \\\\_/@==o| // |/ \\| \\\\ | / \\ |\n |\\ /| || // [][][] || \\/][][\\/\n | | | @ |\' |\\ /| [\' |\\ /|\n | | | |_||_| I] |_||_|\n | | | [ ][ ] I [ ][ ]\n / | \\ | || | | || |\n ~~~~~~~ |_||_| |_||_|\n__(_)(_\\_________________________________/__][_]_________[_][__\\___\n18\n ,=== /__\\ /__\\\n (@o o@ There\'s one. |><> | |><> |\n \\ -/ (/\\__) (/\\__)\n //~ ~~\\ / \\ / \\\n\\ \\__ )\\ \\ //| __ |\\\\ ||/(===o\n \\\\_/@==o| // |/ \\| \\\\ | / \\ |\n |\\ /| || // [][][] || \\/][][\\/\n | | | @ |\' |\\ /| [\' |\\ /|\n | | | |_||_| I] |_||_|\n | | | [ ][ ] I [ ][ ]\n / | \\ | || | | || |\n ~~~~~~~ |_||_| |_||_|\n__(_)(_\\_________________________________/__][_]_________[_][__\\___\n3\n ,=== /__\\ /__\\\n (@o o@ |><> | |><> |\n \\ -/ (/\\__) (/\\__)\n //~ ~~\\ / \\ / \\\n\\ \\__ )\\ \\ //| __ |\\\\ ||/(===o\n \\\\_/@==o| // |/ \\| \\\\ | / \\ |\n |\\ /| || // [][][] || \\/][][\\/\n | | | @ |\' |\\ /| [\' |\\ /|\n | | | |_||_| I] |_||_|\n | | | [ ][ ] I [ ][ ]\n / | \\ | || | | || |\n ~~~~~~~ |_||_| |_||_|\n__(_)(_\\_________________________________/__][_]_________[_][__\\___\n8\n ,=== /__\\ /__\\\n (@o o@ Set for stun! |><> | |><> |\n \\ -/ (/\\__) (/\\__)\n //~ ~~\\ / \\ / \\\n\\ \\__ )\\ \\ /o===)\\|| ||/(===o\n \\\\_/@==o| // |/ \\ | | / \\ |\n |\\ /| || // [][][\\/ \\/][][\\/\n | | | @ |\' |\\ /| |\\ /|\n | | | |_||_| |_||_|\n | | | [ ][ ] [ ][ ]\n / | \\ | || | | || |\n ~~~~~~~ |_||_| |_||_|\n__(_)(_\\_________________________________/__][_]_________[_][__\\___\n9\n ,=== /__\\ /__\\\n (@o o@ Set for stun! |><> | |><> |\n \\ -/ (/\\__) (/\\__)\n //~ ~~\\ / \\ / \\\n\\ \\__ )\\ \\ o===)\\|| ||/(===o\n \\\\_/@==o| ||/ \\ | | / \\ |\n |\\ /| || \\/][][\\/ \\/][][\\/\n | | | @ |\\ /| |\\ /|\n | | | |_||_| |_||_|\n | | | [ ][ ] [ ][ ]\n / | \\ | || | | || |\n ~~~~~~~ |_||_| |_||_|\n__(_)(_\\_________________________________/__][_]_________[_][__\\___\n5\n ,=== /__\\ /__\\\n (@o o@ |><> | |><> |\n \\ -/ (/\\__) (/\\__)\n //~ ~~\\ / \\ / \\\n\\ \\__ )\\ \\ o===)\\|| ||/(===o\n \\\\_/@==o| ||/ \\ | | / \\ |\n |\\ /| || \\/][][\\/ \\/][][\\/\n | | | @ |\\ /| |\\ /|\n | | | |_||_| |_||_|\n | | | [ ][ ] [ ][ ]\n / | \\ | || | | || |\n ~~~~~~~ |_||_| |_||_|\n__(_)(_\\_________________________________/__][_]_________[_][__\\___\n1\n ,=== /__\\ /__\\\n (@o o@ |><> | |><> |\n \\ -/ (/\\__) (/\\__)\n //~ ~~\\ / \\ / \\\n\\ \\__ )\\ \\ *===)\\|| ||/(===o\n \\\\_/@==*| ||/ \\ | | / \\ |\n |\\ /| || \\/][][\\/ \\/][][\\/\n | | | @ |\\ /| |\\ /|\n | | | |_||_| |_||_|\n | | | [ ][ ] [ ][ ]\n / | \\ | || | | || |\n ~~~~~~~ |_||_| |_||_|\n__(_)(_\\_________________________________/__][_]_________[_][__\\___\n1\n ,=== /__\\ /__\\\n (@o o@ |><> | |><> |\n \\ -/ (/\\__) (/\\__)\n //~ ~~\\ | / \\ / \\\n\\ \\__ )\\ \\ | | o===)\\|| ||/(===o\n \\\\_/@=***---- | ||/ \\ | | / \\ |\n |\\ /| *| \\/][][\\/ \\/][][\\/\n | | | @ |\\ /| |\\ /|\n | | | |_||_| |_||_|\n | | | [ ][ ] [ ][ ]\n / | \\ | || | | || |\n ~~~~~~~ |_||_| |_||_|\n__(_)(_\\_________________________________/__][_]_________[_][__\\___\n1\n ,=== /__\\ /__\\\n (@o o@ |><> | |><> |\n \\ -/ | (/\\__) (/\\__)\n //~ ~~* | | / \\ / \\\n\\ \\__ )* * | | | o===)\\|| ||/(===o\n \\\\_/@***** ----- | | ||/ \\ | | / \\ |\n |\\ /|*** | \\/][][\\/ \\/][][\\/\n | | | * |\\ /| |\\ /|\n | | | |_||_| |_||_|\n | | | [ ][ ] [ ][ ]\n / | \\ | || | | || |\n ~~~~~~~ |_||_| |_||_|\n__(_)(_\\_________________________________/__][_]_________[_][__\\___\n1\n ,=== /__\\ /__\\\n (@o o@ | |><> | |><> |\n \\ -/ | | (/\\__) (/\\__)\n //~ ~~\\ | | | / \\ / \\\n\\ \\__ )\\ \\ | | | | o===)\\|| ||/(===o\n \\\\_/@=*** ----- | | | ||/ \\ | | / \\ |\n |\\ /| *| | | \\/][][\\/ \\/][][\\/\n | | | @ | |\\ /| |\\ /|\n | | | |_||_| |_||_|\n | | | [ ][ ] [ ][ ]\n / | \\ | || | | || |\n ~~~~~~~ |_||_| |_||_|\n__(_)(_\\_________________________________/__][_]_________[_][__\\___\n1\n ,=== | /__\\ /__\\\n (@o o@ | | |><> | |><> |\n \\ -/ | | | (/\\__) (/\\__)\n //~ ~~\\ | | | | / \\ / \\\n\\ \\__ )\\ \\ | | | | | o===)\\|| ||/(===o\n \\\\_/@==*| ----| | | ||/ \\ | | / \\ |\n |\\ /| || | | | \\/][][\\/ \\/][][\\/\n | | | @ | | |\\ /| |\\ /|\n | | | | |_||_| |_||_|\n | | | [ ][ ] [ ][ ]\n / | \\ | || | | || |\n ~~~~~~~ |_||_| |_||_|\n__(_)(_\\_________________________________/__][_]_________[_][__\\___\n1\n ,=== | | /__\\ /__\\\n (@o o@ | | | |><> | |><> |\n \\ -/ | | | | (/\\__) (/\\__)\n //~ ~~\\ | | | | | / \\ / \\\n\\ \\__ )\\ \\ | | | | | | o===)\\|| ||/(===o\n \\\\_/@==o| | | |---|- | ||/ \\ | | / \\ |\n |\\ /| || | | | | \\/][][\\/ \\/][][\\/\n | | | @ | | | |\\ /| |\\ /|\n | | | | | |_||_| |_||_|\n | | | | [ ][ ] [ ][ ]\n / | \\ | | || | | || |\n ~~~~~~~ |_||_| |_||_|\n__(_)(_\\_________________________________/__][_]_________[_][__\\___\n1\n ,=== | | | /__\\ /__\\\n (@o o@ | | | | |><> | |><> |\n \\ -/ | | | | | (/\\__) (/\\__)\n //~ ~~\\ | | | | | | / \\ / \\\n\\ \\__ )\\ \\ | | | | | | | o===)\\|| ||/(===o\n \\\\_/@==o| | | | | | --|-- ||/ \\ | | / \\ |\n |\\ /| || | | | | | \\/][][\\/ \\/][][\\/\n | | | @ | | | | |\\ /| |\\ /|\n | | | | | | |_||_| |_||_|\n | | | | | [ ][ ] [ ][ ]\n / | \\ | | | || | | || |\n ~~~~~~~ | |_||_| |_||_|\n__(_)(_\\_________________________________/__][_]_________[_][__\\___\n1\n ,=== | | | | /__\\ /__\\\n (@o o@ | | | | | |><> | |><> |\n \\ -/ | | | | | | (/\\__) (/\\__)\n //~ ~~\\ | | | | | | | / \\ / \\\n\\ \\__ )\\ \\ | | | | | | | o===)\\|| ||/(===o\n \\\\_/@==o| | | | | | | | ----* \\ | | / \\ |\n |\\ /| || | | | | | | \\/][][\\/ \\/][][\\/\n | | | @ | | | | | |\\ /| |\\ /|\n | | | | | | | |_||_| |_||_|\n | | | | | | [ ][ ] [ ][ ]\n / | \\ | | | | || | | || |\n ~~~~~~~ | | |_||_| |_||_|\n__(_)(_\\____|____________________________/__][_]_________[_][__\\___\n1\n ,=== | | | | | /__\\ /__\\\n (@o o@| | | | | | |><> | |><> |\n \\ -/ | | | | | | | (/\\__) (/\\__)\n //~ ~~| | | | | | | | / \\ / \\\n\\ \\__ )\\|\\ | | | | | | | o=*=)\\|| ||/(===o\n \\\\_/@==|| | | | | | | | |*** \\ | | / \\ |\n |\\ /| || | | | | | | \\/*[][\\/ \\/][][\\/\n | | | | | | | | | |\\ /| |\\ /|\n | | | | | | | | |_||_| |_||_|\n | | | | | | | [ ][ ] [ ][ ]\n / | \\| | | | | || | | || |\n ~~~~~~~| | | |_||_| |_||_|\n__(_)(_\\|___|____________________________/__][_]_________[_][__\\___\n1\n ,|== | | | | | /__\\ /__\\\n (@| -@| | | | | | |><> | |><> |\n \\|-/ | | | | | | | (/\\__) (/\\__)\n //~| ~~| | | | | | | / * \\ / \\\n\\ \\_| )\\|\\ | | | | | | o***)\\|| ||/(===o\n \\\\_|@==|| | | | | | | *****\\ | | / \\ |\n |\\|/| || | | | | | | \\***][\\/ \\/][][\\/\n | | | | | | | | | |* /| |\\ /|\n | | | | | | | | |_||_| |_||_|\n | | | | | | | [ ][ ] [ ][ ]\n / | \\| | | | | || | | || |\n ~~~|~~~| | | |_||_| |_||_|\n__(_|(_\\|___|____________________________/__][_]_________[_][__\\___\n1\n| ,|== | | | | | /__\\ /__\\\n| (@| -@| | | | | | |<><>| |><> |\n| \\|-/ | | | | | | | (_/\\_) (/\\__)\n|//~| ~~| | | | | | | / \\ / \\\n| \\_| )\\|\\ | | | | | | o=*=)\\|| ||/(===o\n|\\\\_|@==|| | | | | | | |*** \\ | | / \\ |\n| |\\|/| || | | | | | | \\/*[][\\/ \\/][][\\/\n| | | | | | | | | | | /| |\\ /|\n| | | | | | | | | |_||_| |_||_|\n| | | | | | | | [ ][ ] [ ][ ]\n|/ | \\| | | | | || | | || |\n|~~~|~~~| | | |_||_| |_||_|\n|_(_|(_\\|___|____________________________/__][_]_________[_][__\\___\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n5\n /__\\\n | <><|\n (__/\\)\n / \\\n ||/(===o\n | / \\ |\n \\/][][\\/\n | || |\n |_||_|\n [ ][ ]\n | || |\n |_||_|\n____________[_][__\\________________________________________________\n12\n /__\\\n | <><| Inform Lord Vader we have\n (__/\\) a prisoner.\n / \\\n ||/(===o\n | / \\ |\n \\/][][\\/\n | || |\n |_||_|\n [ ][ ]\n | || |\n |_||_|\n____________[_][__\\________________________________________________\n7\n /__\\\n |<><>| Inform Lord Vader we have\n (_/\\_) a prisoner.\n / \\\n ||/(===o\n | / \\ |\n \\/][][\\/\n | || |\n |_||_|\n [ ][ ]\n | || |\n |_||_|\n____________[_][__\\________________________________________________\n5\n /__\\\n |<><>|\n (_/\\_)\n / \\\n ||/(===o\n | / \\ |\n \\/][][\\/\n | || |\n |_||_|\n [ ][ ]\n | || |\n |_||_|\n____________[_][__\\________________________________________________\n4\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n /----------------------\\\n | |oo ) |\n | _\\=/_ |\n | ___ / _ \\ |\n | / ()\\ //|/.\\|\\\\|\n | _|_____|_ || \\_/ ||\n || | === | | || |\\ /| ||\n ||_| O |_| # \\_ _/ #|\n | || O || | | | |\n | ||__*__|| | | | |\n ||~ \\___/ ~| []|[] |\n \\----------------------/\n___________________________________________________________________\n10\n /----------------------\\\n | |oo ) | I\'m going to\n | _\\=/_ | regret this.\n | ___ / _ \\ |\n | / ()\\ //|/.\\|\\\\|\n | _|_____|_ || \\_/ ||\n || | === | | || |\\ /| ||\n ||_| O |_| # \\_ _/ #|\n | || O || | | | |\n | ||__*__|| | | | |\n ||~ \\___/ ~| []|[] |\n \\----------------------/\n___________________________________________________________________\n7\n /----------------------\\\n | ( oo| | I\'m going to\n | _\\=/_ | regret this.\n | ___ / _ \\ |\n | / ()\\ //|/.\\|\\\\|\n | _|_____|_ || \\_/ ||\n || | === | | || |\\ /| ||\n ||_| O |_| # \\_ _/ #|\n | || O || | | | |\n | ||__*__|| | | | |\n ||~ \\___/ ~| []|[] |\n \\----------------------/\n___________________________________________________________________\n7\n /----------------------\\\n | |oo ) | I\'m going to\n | _\\=/_ | regret this.\n | ___ / _ \\ |\n | / ()\\ //|/.\\|\\\\|\n | _|_____|_ || \\_/ ||\n || | === | | || |\\ /| ||\n ||_| O |_| # \\_ _/ #|\n | || O || | | | |\n | ||__*__|| | | | |\n ||~ \\___/ ~| []|[] |\n \\----------------------/\n___________________________________________________________________\n2\n /----------------------\\\n | |oo ) |\n | _\\=/_ |\n | ___ / _ \\ |\n | / ()\\ //|/.\\|\\\\|\n | _|_____|_ || \\_/ ||\n || | === | | || |\\ /| ||\n ||_| O |_| # \\_ _/ #|\n | || O || | | | |\n | ||__*__|| | | | |\n ||~ \\___/ ~| []|[] |\n \\----------------------/\n___________________________________________________________________\n1\n /----------------------\\\n |\\____________________/|\n | _\\=/_ |\n | ___ / _ \\ |\n | / ()\\ //|/.\\|\\\\|\n | _|_____|_ || \\_/ ||\n || | === | | || |\\ /| ||\n ||_| O |_| # \\_ _/ #|\n | || O || | | | |\n | ||__*__|| | | | |\n ||~ \\___/ ~| []|[] |\n \\----------------------/\n___________________________________________________________________\n1\n /----------------------\\\n | / \\ |\n |\\____________________/|\n | ___ / _ \\ |\n | / ()\\ //|/.\\|\\\\|\n | _|_____|_ || \\_/ ||\n || | === | | || |\\ /| ||\n ||_| O |_| # \\_ _/ #|\n | || O || | | | |\n | ||__*__|| | | | |\n ||~ \\___/ ~| []|[] |\n \\----------------------/\n___________________________________________________________________\n1\n /----------------------\\\n | / \\ |\n | / \\ |\n |\\____________________/|\n | / ()\\ //|/.\\|\\\\|\n | _|_____|_ || \\_/ ||\n || | === | | || |\\ /| ||\n ||_| O |_| # \\_ _/ #|\n | || O || | | | |\n | ||__*__|| | | | |\n ||~ \\___/ ~| []|[] |\n \\----------------------/\n___________________________________________________________________\n1\n /----------------------\\\n | / \\ |\n | / \\ |\n | / \\ |\n |\\____________________/|\n | _|_____|_ || \\_/ ||\n || | === | | || |\\ /| ||\n ||_| O |_| # \\_ _/ #|\n | || O || | | | |\n | ||__*__|| | | | |\n ||~ \\___/ ~| []|[] |\n \\----------------------/\n___________________________________________________________________\n1\n /----------------------\\\n | \\________/ |\n | / \\ |\n | / \\ |\n | / \\ |\n |\\____________________/|\n || | === | | || |\\ /| ||\n ||_| O |_| # \\_ _/ #|\n | || O || | | | |\n | ||__*__|| | | | |\n ||~ \\___/ ~| []|[] |\n \\----------------------/\n___________________________________________________________________\n1\n /----------------------\\\n | | || |\n | \\________/ |\n | / \\ |\n | / \\ |\n | / \\ |\n |\\____________________/|\n ||_| O |_| # \\_ _/ #|\n | || O || | | | |\n | ||__*__|| | | | |\n ||~ \\___/ ~| []|[] |\n \\----------------------/\n___________________________________________________________________\n1\n /----------------------\\\n | | || |\n | | | |\n | \\_______// |\n | / \\ |\n | / \\ |\n | / \\ |\n |\\____________________/|\n | || O || | | | |\n | ||__*__|| | | | |\n ||~ \\___/ ~| []|[] |\n \\----------------------/\n___________________________________________________________________\n1\n /----------------------\\\n | | || |\n | | _| |\n | |_ / | |\n | \\\\_____/_/ |\n | / \\ |\n | / \\ |\n | / \\ |\n |\\____________________/|\n | ||__*__|| | | | |\n ||~ \\___/ ~| []|[] |\n \\----------------------/\n___________________________________________________________________\n1\n /----------------------\\\n | / \\ |\n | | _| |\n | |_ / | |\n | |)\\ //|| |\n | \\_|___||_/ |\n | / \\ |\n | / \\ |\n | / \\ |\n |\\____________________/|\n ||~ \\___/ ~| []|[] |\n \\----------------------/\n___________________________________________________________________\n1\n /----------------------\\\n | \\ ________ / |\n | / \\ |\n | |_ / | |\n | |)\\ //|| |\n | |__|_ || | |\n | \\_|_|_||_/ |\n | / \\ |\n | / \\ |\n | / \\ |\n |\\____________________/|\n \\----------------------/\n___________________________________________________________________\n10\n /----------------------\\\n | \\ / |\n | \\ ________ / |\n | / /\\ |\n | |)\\ //|| |\n | |__|_ || | |\n | |= | | || || |\n | \\_|_|__#_/ |\n | / \\ |\n | / \\ |\n |/ \\ |\n \\----------------------/\n___________________________________________________________________\n10\n /----------------------\\\n | \\ / |\n | \\ ________ / |\n | / /\\ |\n | |)\\ //|| |\n | |__|_ || | |\n | |= | | || || |\n | \\_|_|_#__/ |\n | / \\ |\n | / \\ |\n |/ \\ |\n \\----------------------/\n___________________________________________________________________\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n13\n \\ ____________ /\n \\ \\ / __________ \\ / /\n \\ /___ ___\\ /\n / / / \\ / \\ \\ \\\n | / | || | \\ |\n | | \\___/ \\___/ | |\n | | | |\n | | ___ ___ | |\n | | / \\ / \\ | |\n | \\ | || | / |\n \\ \\ \\___/ \\___/ / /\n / \\__________/ \\\n / \\____________/ \\\n1\n \\ ____________ /\n \\ \\ / __________ \\ / /\n \\ * /___ ___\\ * /\n / / / \\ / \\ \\ \\\n | / | || | \\ |\n | | \\___/ \\___/ | |\n | | | |\n | | ___ ___ | |\n | | / \\ / \\ | |\n | \\ | || | / |\n \\ \\ \\___/ \\___/ / /\n / * \\__________/ * \\\n / \\____________/ \\\n1\n \\ ____________ /\n \\ \\ / __________ \\ / /\n \\ ** /___ ___\\/** /\n / ** / \\ / \\ ** \\\n | / | || | \\ |\n | | \\___/ \\___/ | |\n | | | |\n | | ___ ___ | |\n | | / \\ / \\ | |\n | \\ | || | / |\n \\ ** \\___/ \\___/ ** /\n / ** \\__________/ ** \\\n / \\____________/ \\\n1\n \\ ____________ /\n \\ \\ / __________ \\ / /\n \\ ****___ ___**** /\n /****/ \\ / \\****\\\n | /**| || |**\\ |\n | | \\___/ \\___/ | |\n | | | |\n | | ___ ___ | |\n | | / \\ / \\ | |\n | \\**| || |**/ |\n \\****\\___/ \\___/****/\n / ***\\__________/*** \\\n / \\____________/ \\\n1\n \\ ____________ /\n \\ \\ /**_________*\\ / /\n \\ *****__ __***** /\n /***** \\ / *****\\\n | **** || *****|\n | *** \\___/ \\___/ **|\n | | |*|\n | | ___ ___ | |\n | * / \\ / \\ ****|\n |****| || ******|\n \\*****___/ \\___*****/\n / *****________***** \\\n / \\***________*/ \\\n1\n \\ ____________ /\n \\ \\ /******__****\\ / /\n \\ ******* ******* /\n /****** \\ / *******\\\n |******* || *******|\n |******___/ \\___/ ****|\n |** ***|\n |*| ___ ___ ***|\n |**** / \\ / \\*****|\n |****** || *******|\n \\******__/ \\_*******/\n / *******_____****** \\\n / \\*****___****/ \\\n1\n \\ ____________ /\n \\ \\ /************\\ / /\n \\ ****************** /\n /********************\\\n |******* || *********|\n |******___/ \\_********|\n |***** *******|\n |***** ___ _********|\n |******** \\ /*********|\n |********* ||**********|\n \\********************/\n / ****************** \\\n / \\************/ \\\n1\n \\ ____________ /\n \\ \\ /************\\ / /\n \\ ****************** /\n /********************\\\n |**********************|\n |**********************|\n |**********************|\n |**********************|\n |**********************|\n |**********************|\n \\********************/\n / ****************** \\\n / \\************/ \\\n1\n \\ ____________ /\n \\ \\ /************\\ / /\n \\ ****************** /\n /********************\\\n |********* ************|\n |********/ \\ **********|\n |******| \\_/\\_*********|\n |*******|/ \\/ ********|\n |********\\ / **********|\n |********** ***********|\n \\********************/\n / ****************** \\\n / \\************/ \\\n1\n \\ ____________ /\n \\ \\ /************\\ / /\n \\ ********* .******* /\n /****** ______ ****\\\n |****** / _ _ \\ *****|\n |***** | / \\/ \\ |. ****|\n |***. | \\_/\\_/ | ****|\n |***** | / \\/ \\ | *****|\n |***** | \\_/\\_/ |******|\n |****** \\______/*******|\n \\******* .* *******/\n / ******** ******** \\\n / \\************/ \\\n1\n \\ ____________ /\n \\ \\ /** . *\\ / /\n \\ *** . * /\n /** . * *\\\n |*** .* **|\n |* ---- . *|\n |* . |()()| |\n |. | |. * |\n |* |()()| **|\n |** * .---- ***|\n \\*** . . ***/\n / **** . *** \\\n / \\***____*___*/ \\\n1\n \\ ____________ /\n \\ \\ / . * \\ / /\n \\ * . * /\n / . \\\n |* . |\n | ---- . |\n | . |()()| |\n |. | |. * |\n | |()()| . |\n | .---- |\n \\ * . . /\n / . ** \\\n / \\____________/ \\\n1\n \\ ____________ /\n \\ \\ / . \\ / /\n \\ . /\n / . * \\\n | . |\n | -- . |\n | . |OO| |\n |. * .|OO| . |\n | -- . |\n | . |\n \\ . . /\n / . \\\n / \\____________/ \\\n1\n \\ ____________ /\n \\ \\ / . \\ / /\n \\ . /\n / . \\\n | . |\n | -- . |\n | . |OO| |\n |. .|OO| . |\n | -- . |\n | . |\n \\ . . /\n / . \\\n / \\____________/ \\\n2\n \\ ____________ /\n \\ \\ / . \\ / /\n \\ . /\n / . \\\n | . |\n | _ . |\n | . (_) |\n |. . . |\n | . |\n | . |\n \\ . . /\n / . \\\n / \\____________/ \\\n2\n ____________\n / \\ / . \\ / \\\n \\ \\ . / /\n / \\ / \\ / \\\n | . |\n | o . |\n | . |\n |. . . |\n | . |\n | . |\n \\ / \\ . ./ \\ /\n / / . \\ \\\n \\ / \\____________/ \\ /\n2\n ____________\n / \\ / . \\ / \\\n \\ \\ . / /\n / \\ / \\ / \\\n | . |\n | " . |\n | . |\n |. . . |\n | . |\n | . |\n \\ / \\ . ./ \\ /\n / / . \\ \\\n \\ / \\____________/ \\ /\n2\n ____________\n / \\ / . \\ / \\\n \\ \\ . / /\n / \\ / \\ / \\\n | . . |\n | . |\n | . |\n |. . . |\n | . |\n | . |\n \\ / \\ . ./ \\ /\n / / . \\ \\\n \\ / \\____________/ \\ /\n5\n ____________\n / \\ / . \\ / \\\n \\ \\ . / /\n / \\ / \\ / \\\n | . |\n | . |\n | . |\n |. . . |\n | . |\n | . |\n \\ / \\ . ./ \\ /\n / / . \\ \\\n \\ / \\____________/ \\ /\n24\n ____________\n / \\ / . \\ / \\\n There goes \\ \\ . / /\n another one. / \\ / \\ / \\\n | . |\n | . |\n | . |\n |. . . |\n | . |\n | . |\n \\ / \\ . ./ \\ /\n / / . \\ \\\n \\ / \\____________/ \\ /\n2\n ____________\n / \\ / . \\ / \\\n \\ \\ . / /\n / \\ / \\ / \\\n | . |\n | . |\n | . |\n |. . . |\n | . |\n | . |\n \\ / \\ . ./ \\ /\n / / . \\ \\\n \\ / \\____________/ \\ /\n25\n ____________\n / \\ / . \\ / \\\n \\ \\ . / / Hold your fire!\n / \\ / \\ / \\\n | . |\n | . |\n | . |\n |. . . |\n | . |\n | . |\n \\ / \\ . ./ \\ /\n / / . \\ \\\n \\ / \\____________/ \\ /\n2\n ____________\n / \\ / . \\ / \\\n \\ \\ . / /\n / \\ / \\ / \\\n | . |\n | . |\n | . |\n |. . . |\n | . |\n | . |\n \\ / \\ . ./ \\ /\n / / . \\ \\\n \\ / \\____________/ \\ /\n24\n ____________\n / \\ / . \\ / \\\n \\ \\ . / / There\'s no\n / \\ / \\ / \\ life forms.\n | . |\n | . |\n | . |\n |. . . |\n | . |\n | . |\n \\ / \\ . ./ \\ /\n / / . \\ \\\n \\ / \\____________/ \\ /\n5\n ____________\n / \\ / . \\ / \\\n \\ \\ . / /\n / \\ / \\ / \\\n | . |\n | . |\n | . |\n |. . . |\n | . |\n | . |\n \\ / \\ . ./ \\ /\n / / . \\ \\\n \\ / \\____________/ \\ /\n9\n\n\n\n\n\n\n\n\n\n\n\n\n\n1\n ____________\n / __________ \\\n /__|O=<88>=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O=O<>| |><> |\n (_/\\_) (/\\__)\n / \\ / \\\n //| __ \\\\ ||/(===o\n // |/ \\| || | / \\ |\n //__[][][] || \\/][][\\/\n ____/|\' |\\ /|.\'| |\\ /|\n ,---,_______ / |_||_| \\ |_||_|\n/|O O| / [ ][ ] \\ [ ][ ]\n |O O| / | || | \\ | || |\n~~~~~ " _______|_||_|_______\\ |_||_|\n " " " " "/ [_][_] \\________________[_][__\\____\n37\n /__\\ /__\\\n |<><>| Someone was |><> |\n (_/\\_) in the pod. (/\\__)\n / \\ / \\\n //| __ \\\\ ||/(===o\n // |/ \\| || | / \\ |\n //__[][][] || \\/][][\\/\n ____/|\' |\\ /|.\'| |\\ /|\n ,---,_______ / |_||_| \\ |_||_|\n/|O O| / [ ][ ] \\ [ ][ ]\n |O O| / | || | \\ | || |\n~~~~~ " _______|_||_|_______\\ |_||_|\n " " " " "/ [_][_] \\________________[_][__\\____\n5\n /__\\ /__\\\n |<><>| |><> |\n (_/\\_) (/\\__)\n / \\ / \\\n //| __ \\\\ ||/(===o\n // |/ \\| || | / \\ |\n //__[][][] || \\/][][\\/\n ____/|\' |\\ /|.\'| |\\ /|\n ,---,_______ / |_||_| \\ |_||_|\n/|O O| / [ ][ ] \\ [ ][ ]\n |O O| / | || | \\ | || |\n~~~~~ " _______|_||_|_______\\ |_||_|\n " " " " "/ [_][_] \\________________[_][__\\____\n6\n /__\\ /__\\\n | <><| Look sir - |><> |\n (__/\\) droids. (/\\__)\n / \\ / \\\n //| __ \\\\ ||/(===o\n // |/ \\| || | / \\ |\n //__[][][] || \\/][][\\/\n ____/|\' |\\ /|.\'| |\\ /|\n ,---,_______ / |_||_| \\ |_||_|\n/|O O| / [ ][ ] \\ [ ][ ]\n |O O| / | || | \\ | || |\n~~~~~ " _______|_||_|_______\\ |_||_|\n " " " " "/ [_][__\\ \\________________[_][__\\____\n34\n /__\\ /__\\\n | <><| Look sir - |><> |\n (__/\\) droids. (/\\__)\n / \\ /O / \\\n //| __ \\\\// ||/(===o\n // |/ \\| \\/ | / \\ |\n //__[][][] \\/][][\\/\n ____/|\' |\\ /|. |\\ /|\n ,---,_______ / |_||_| \\ |_||_|\n/|O O| / [ ][ ] \\ [ ][ ]\n |O O| / | || | \\ | || |\n~~~~~ " _______|_||_|_______\\ |_||_|\n " " " " "/ [_][__\\ \\________________[_][__\\____\n6\n /__\\ /__\\\n | <><| |><> |\n (__/\\) (/\\__)\n / \\ /O / \\\n //| __ \\\\// ||/(===o\n // |/ \\| \\/ | / \\ |\n //__[][][] \\/][][\\/\n ____/|\' |\\ /|. |\\ /|\n ,---,_______ / |_||_| \\ |_||_|\n/|O O| / [ ][ ] \\ [ ][ ]\n |O O| / | || | \\ | || |\n~~~~~ " _______|_||_|_______\\ |_||_|\n " " " " "/ [_][__\\ \\________________[_][__\\____\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n\n\n\n\n\n\n\n .\n |\n _________ .|\n __/ o o o o \\ .||.\n_____________________________________________|__|__________|__|[]|_\n\n6\n\n\n\n\n\n\n\n\n |\n _________ .|\n __/ o o o o \\ .||.\n_____________________________________________|__|__________|__|[]|_\n\n4\n\n\n\n\n\n\n\n .\n |\n _________ .|\n __/ o o o o \\ .||.\n_____________________________________________|__|__________|__|[]|_\n\n2\n\n\n\n\n\n\n\n| .\n |\n _________ .|\n __/ o o o o \\ .||.\n_____________________________________________|__|__________|__|[]|_\n\n3\n\n\n\n\n\n\n\n|\n |\n _________ .|\n __/ o o o o \\ .||.\n_____________________________________________|__|__________|__|[]|_\n\n3\n\n\n\n\n\n\n_\n=|\n/ |\n _________ .|\n __/ o o o o \\ .||.\n_____________________________________________|__|__________|__|[]|_\n\n2\n\n\n\n\n\n\n_\n=| .\n/ |\n _________ .|\n __/ o o o o \\ .||.\n_____________________________________________|__|__________|__|[]|_\n\n4\n\n\n\n\n\n\n__\n =| .\n / |\n/ _________ .|\n __/ o o o o \\ .||.\n_____________________________________________|__|__________|__|[]|_\n\n1\n\n\n\n\n\n\n__\n =|\n / |\n/ _________ .|\n __/ o o o o \\ .||.\n_____________________________________________|__|__________|__|[]|_\n\n5\n\n\n\n\n\n\n___\n =|\n / |\n / _________ .|\n/ __/ o o o o \\ .||.\n_____________________________________________|__|__________|__|[]|_\n\n5\n\n\n\n\n\n\n____\n =| .\n / |\n / _________ .|\n_/ __/ o o o o \\ .||.\no____________________________________________|__|__________|__|[]|_\n\n1\n\n\n\n\n\n\n_____\n =| .\n / |\n / _________ .|\n__/ __/ o o o o \\ .||.\noo___________________________________________|__|__________|__|[]|_\n\n3\n\n\n\n\n\n\n_____\n =|\n / |\n / _________ .|\n__/ __/ o o o o \\ .||.\noo___________________________________________|__|__________|__|[]|_\n\n3\n\n\n\n\n\n\n______\n =|\n] / |\n / _________ .|\n___/ __/ o o o o \\ .||.\nooo__________________________________________|__|__________|__|[]|_\n\n2\n\n\n\n\n\n\n______\n =| .\n] / |\n / _________ .|\n___/ __/ o o o o \\ .||.\nooo__________________________________________|__|__________|__|[]|_\n\n4\n\n\n\n\n\n\n_______\n_ =| .\n_] / |\n / _________ .|\n____/ __/ o o o o \\ .||.\n_ooo_________________________________________|__|__________|__|[]|_\n\n1\n\n\n\n\n\n\n_______\n_ =|\n_] / |\n / _________ .|\n____/ __/ o o o o \\ .||.\n_ooo_________________________________________|__|__________|__|[]|_\n\n5\n\n\n\n\n\n\n________\n _ =|\n[_] / |\n / _________ .|\n_____/ __/ o o o o \\ .||.\n__ooo________________________________________|__|__________|__|[]|_\n\n5\n\n\n\n\n\n\n_________\n _ =| .\n [_] / |\n / _________ .|\n______/ __/ o o o o \\ .||.\no__ooo_______________________________________|__|__________|__|[]|_\n\n1\n\n\n\n\n\n\n__________\n _ =| .\n [_] / |\n / _________ .|\n_______/ __/ o o o o \\ .||.\noo__ooo______________________________________|__|__________|__|[]|_\n\n4\n\n\n\n\n\n\n__________\n _ =|\n [_] / |\n / _________ .|\n_______/ __/ o o o o \\ .||.\noo__ooo______________________________________|__|__________|__|[]|_\n\n2\n\n\n\n\n\n\n___________\n _ =|\n [_] / |\n / _________ .|\n________/ __/ o o o o \\ .||.\nooo__ooo_____________________________________|__|__________|__|[]|_\n\n3\n\n\n\n\n\n\n___________\n _ =| .\n [_] / |\n / _________ .|\n________/ __/ o o o o \\ .||.\nooo__ooo_____________________________________|__|__________|__|[]|_\n\n3\n\n\n\n\n\n\n ___________\n| _ =| .\n| [_] / |\n| / _________ .|\n|________/ __/ o o o o \\ .||.\n_ooo__ooo____________________________________|__|__________|__|[]|_\n\n2\n\n\n\n\n\n\n ___________\n| _ =|\n| [_] / |\n| / _________ .|\n|________/ __/ o o o o \\ .||.\n_ooo__ooo____________________________________|__|__________|__|[]|_\n\n4\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ __/ o o o o \\ .||.\n__ooo__ooo___________________________________|__|__________|__|[]|_\n\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ __/ o o o o \\ .||.\n__ooo__ooo___________________________________|__|__________|__|[]|_\n\n5\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ __/ o o o o \\ .||.\n___ooo__ooo__________________________________|__|__________|__|[]|_\n\n5\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ __/ o o o o \\ .||.\n____ooo__ooo_________________________________|__|__________|__|[]|_\n\n1\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ __/ o o o o \\ .||.\n_____ooo__ooo________________________________|__|__________|__|[]|_\n\n4\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ __/ o o o o \\ .||.\n_____ooo__ooo________________________________|__|__________|__|[]|_\n\n2\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ __/ o o o o \\ .||.\n______ooo__ooo_______________________________|__|__________|__|[]|_\n\n6\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ __/ o o o o \\ .||.\n______ooo__ooo_______________________________|__|__________|__|[]|_\n\n6\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ __/ o o o o \\ .||.\n______ooo__ooo_______________________________|__|__________|__|[]|_\n\n6\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ __/ o o o o \\ .||.\n______ooo__ooo_______________________________|__|__________|__|[]|_\n\n6\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ __/ o o o o \\ .||.\n______ooo__ooo_______________________________|__|__________|__|[]|_\n\n5\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ __/ o o o o \\ .||.\n______ooo__ooo_______________________________|__|__________|__|[]|_\n\n1\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + __/ o o o o \\ .||.\n______ooo__ooo______________________________||__|__________|__|[]|_\n\n6\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ + __/ o o o o \\ .||.\n______ooo__ooo______________________________||__|__________|__|[]|_\n\n3\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + __/ o o o o \\ .||.\n______ooo__ooo______________________________||__|__________|__|[]|_\n\n3\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + __/ o o o o \\ .||.\n______ooo__ooo_____________________________|_|__|__________|__|[]|_\n\n6\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ + __/ o o o o \\ .||.\n______ooo__ooo_____________________________|_|__|__________|__|[]|_\n\n1\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + __/ o o o o \\ .||.\n______ooo__ooo_____________________________|_|__|__________|__|[]|_\n\n5\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + __/ o o o o \\ .||.\n______ooo__ooo____________________________|__|__|__________|__|[]|_\n\n6\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ + __/ o o o o \\ .||.\n______ooo__ooo____________________________|__|__|__________|__|[]|_\n\n6\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo___________________________|__||__|__________|__|[]|_\n\n4\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo___________________________|__||__|__________|__|[]|_\n\n2\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo__________________________|__|_|__|__________|__|[]|_\n\n6\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo__________________________|__|_|__|__________|__|[]|_\n\n2\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo__________________________|__|_|__|__________|__|[]|_\n\n4\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo_________________________|__|__|__|__________|__|[]|_\n\n6\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo_________________________|__|__|__|__________|__|[]|_\n\n5\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo________________________|__|___|__|__________|__|[]|_\n\n1\n\n\n\n\n Luke! Luke!\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo________________________|__|___|__|__________|__|[]|_\n\n5\n\n\n\n\n Luke! Luke!\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo________________________|__|___|__|__________|__|[]|_\n\n1\n\n\n\n\n Luke! Luke!\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo_______________________|___|___|__|__________|__|[]|_\n\n6\n\n\n\n\n Luke! Luke!\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo_______________________|___|___|__|__________|__|[]|_\n\n4\n\n\n\n\n Luke! Luke!\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo_______________________|___|___|__|__________|__|[]|_\n\n2\n\n\n\n\n Luke! Luke!\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo______________________|_____|__|__|__________|__|[]|_\n\n4\n\n\n\n\n Luke! Luke!\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo______________________|_____|__|__|__________|__|[]|_\n\n2\n\n\n\n Tell uncle, if he gets\n a translator...\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo______________________|_____|__|__|__________|__|[]|_\n\n2\n\n\n\n Tell uncle, if he gets\n a translator...\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo______________________|_____|__|__|__________|__|[]|_\n\n4\n\n\n\n Tell uncle, if he gets\n a translator...\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo_____________________|______|__|__|__________|__|[]|_\n\n6\n\n\n\n Tell uncle, if he gets\n a translator...\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo_____________________|______|__|__|__________|__|[]|_\n\n6\n\n\n\n Tell uncle, if he gets\n a translator...\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo____________________|_______|__|__|__________|__|[]|_\n\n4\n\n\n\n Tell uncle, if he gets\n a translator...\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo____________________|_______|__|__|__________|__|[]|_\n\n2\n\n\n\n Tell uncle, if he gets\n a translator...\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo___________________|________|__|__|__________|__|[]|_\n\n5\n\n\n\n Tell uncle, if he gets\n a translator...\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo___________________|________|__|__|__________|__|[]|_\n\n1\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo___________________|________|__|__|__________|__|[]|_\n\n2\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo__________________|_________|__|__|__________|__|[]|_\n\n4\n\n\n\n ...be sure it speaks\n Bocce.\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo__________________|_________|__|__|__________|__|[]|_\n\n4\n\n\n\n ...be sure it speaks\n Bocce.\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo__________________|_________|__|__|__________|__|[]|_\n\n2\n\n\n\n ...be sure it speaks\n Bocce.\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo_________________|__________|__|__|__________|__|[]|_\n\n6\n\n\n\n ...be sure it speaks\n Bocce.\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo_________________|__________|__|__|__________|__|[]|_\n\n2\n\n\n\n ...be sure it speaks\n Bocce.\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo_________________|__________|__|__|__________|__|[]|_\n\n4\n\n\n\n ...be sure it speaks\n Bocce.\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo________________|___________|__|__|__________|__|[]|_\n\n6\n\n\n\n ...be sure it speaks\n Bocce.\n\n ___________\n | _ =| .\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo________________|___________|__|__|__________|__|[]|_\n\n1\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo________________|___________|__|__|__________|__|[]|_\n\n5\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] / |\n | / _________ .|\n |________/ + + __/ o o o o \\ .||.\n______ooo__ooo_______________|____________|__|__|__________|__|[]|_\n\n6\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | \\\\\n || | | | \\\\\n (` |====| \')\n | || |\n (_)(_) ___\n |_||_| / |\n |_||_| / |\n_____________[_][__\\______/ |\n20\n ====\n ~~o o Doesn\'t look like we have\n _\\ -/_ much of a choice...\n / \\ / \\\n //| | |\\\\\n || | | | \\\\\n || | | | \\\\\n (` |====| \')\n | || |\n (_)(_) ___\n |_||_| / |\n |_||_| / |\n_____________[_][__\\______/ |\n3\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | \\\\\n || | | | \\\\\n (` |====| \')\n | || |\n (_)(_) ___\n |_||_| / |\n |_||_| / |\n_____________[_][__\\______/ |\n2\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n \\\\| | | \\\\\n \\\\ | | \\\\\n )====| \')\n | || |\n (_)(_) ___\n |_||_| / |\n |_||_| / |\n_____________[_][__\\______/ |\n31\n ====\n ~~o o ...but I\'ll remind him.\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n \\\\| | | \\\\\n \\\\ | | \\\\\n )====| \')\n | || |\n (_)(_) ___\n |_||_| / |\n |_||_| / |\n_____________[_][__\\______/ |\n6\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n \\\\| | | \\\\\n \\\\ | | \\\\\n )====| \')\n | || |\n (_)(_) ___\n |_||_| / |\n |_||_| / |\n_____________[_][__\\______/ |\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n9\n /~\\ / / / \\\n |oo ) | | | |\n _____ _\\=/_ | | | |\n / \\ / _ \\ \\ \\ \\_____/\n | o o| //|/.\\|\\\\ \\ \\\n _|_____|_ || \\_/ || \\ \\\n | | === | | || |\\ /| || \\ \\ _____\n |_| o |_| # \\_ _/ # \\ \\ / \\\n || o || | | | \\ \\ | |\n ||__*__|| | | | \\ \\ | |\n |~ \\___/ ~| []|[] \\ \\ \\_____/\n /=\\ /=\\ /=\\ | | | \\ \\_____________\n------[_]-[_]-[_]--------/_]-[_\\--------------------\\______________\n6\n /~\\ / / / \\\n ( oo| | | | |\n _____ _\\=/_ | | | |\n / \\ / _ \\ \\ \\ \\_____/\n | o o| //|/.\\|\\\\ \\ \\\n _|_____|_ || \\_/ || \\ \\\n | | === | | || |\\ /| || \\ \\ _____\n |_| o |_| # \\_ _/ # \\ \\ / \\\n || o || | | | \\ \\ | |\n ||__*__|| | | | \\ \\ | |\n |~ \\___/ ~| []|[] \\ \\ \\_____/\n /=\\ /=\\ /=\\ | | | \\ \\_____________\n------[_]-[_]-[_]--------/_]-[_\\--------------------\\______________\n4\n\n\n\n\n\n\n\n\n\n\n\n\n\n30\n /""\\ ====\n / o o Luke! Take these two o o~~\n _\\ -/_ over to the garage. _\\- /_\n /\\\\ //\\ / \\ / \\\n // \\\\// \\\\ //| | |\\\\\n || | \\/ | \\\\ \\\\| | |//\n || | | \\\\ \\\\ | //\n \') |===== \') )===(|\n | \\/ | | || |\n | || | (_)(_)\n | || | |_||_|\n |-||-| |_||_|\n____________[_][__\\_________________________________/__][__\\_______\n30\n /""\\ ====\n / o o I want them cleaned o o~~\n _\\ -/_ up before dinner. _\\- /_\n /\\\\ //\\ / \\ / \\\n // \\\\// \\\\ //| | |\\\\\n || | \\/ | \\\\ \\\\| | |//\n || | | \\\\ \\\\ | //\n \') |===== \') )===(|\n | \\/ | | || |\n | || | (_)(_)\n | || | |_||_|\n |-||-| |_||_|\n____________[_][__\\_________________________________/__][__\\_______\n30\n /""\\ ====\n / o o But I was going o o~~\n _\\ -/_ into Toshi station _\\- /_\n /\\\\ //\\ to pick up some / \\ / \\\n // \\\\// \\\\ power converters. //| | |\\\\\n || | \\/ | \\\\ \\\\| | |//\n || | | \\\\ \\\\ | //\n \') |===== \') )===(|\n | \\/ | | || |\n | || | (_)(_)\n | || | |_||_|\n |-||-| |_||_|\n____________[_][__\\_________________________________/__][__\\_______\n5\n /""\\ ====\n / o o o o~~\n _\\ -/_ _\\- /_\n /\\\\ //\\ / \\ / \\\n // \\\\// \\\\ //| | |\\\\\n || | \\/ | \\\\ \\\\| | |//\n || | | \\\\ \\\\ | //\n \') |===== \') )===(|\n | \\/ | | || |\n | || | (_)(_)\n | || | |_||_|\n |-||-| |_||_|\n____________[_][__\\_________________________________/__][__\\_______\n29\n /""\\ ====\n / o o You can waste o o~~\n _\\ -/_ time with your _\\- /_\n /\\\\ //\\ friends later. / \\ / \\\n // \\\\// \\\\ //| | |\\\\\n || | \\/ | \\\\ \\\\| | |//\n || | | \\\\ \\\\ | //\n \') |===== \') )===(|\n | \\/ | | || |\n | || | (_)(_)\n | || | |_||_|\n |-||-| |_||_|\n____________[_][__\\_________________________________/__][__\\_______\n5\n /""\\ ====\n / o o o o~~\n _\\ -/_ _\\- /_\n /\\\\ //\\ / \\ / \\\n // \\\\// \\\\ //| | |\\\\\n || | \\/ | \\\\ \\\\| | |//\n || | | \\\\ \\\\ | //\n \') |===== \') )===(|\n | \\/ | | || |\n | || | (_)(_)\n | || | |_||_|\n |-||-| |_||_|\n____________[_][__\\_________________________________/__][__\\_______\n14\n /""\\ ====\n / o o All right. o o~~\n _\\ -/_ Come on. _\\- /_\n /\\\\ //\\ / \\ / \\\n // \\\\// \\\\ //| | |\\\\\n || | \\/ | \\\\ \\\\| | |//\n || | | \\\\ \\\\ | //\n \') |===== \') )===(|\n | \\/ | | || |\n | || | (_)(_)\n | || | |_||_|\n |-||-| |_||_|\n____________[_][__\\_________________________________/__][__\\_______\n5\n /""\\ ====\n / o o All right. ~~o o\n _\\ -/_ Come on. _\\ -/_\n /\\\\ //\\ / \\ / \\\n // \\\\// \\\\ //| | |\\\\\n || | \\/ | \\\\ \\\\| | |//\n || | | \\\\ \\\\ | //\n \') |===== \') )===(|\n | \\/ | | || |\n | || | (_)(_)\n | || | |_||_|\n |-||-| |_||_|\n____________[_][__\\_________________________________/__][__\\_______\n13\n /""\\ ====\n / o o All right. ~~o o\n _\\ -/_ Come on. _\\ -/_\n /\\\\ //\\ / \\ / \\\n // \\\\// \\\\ //| | |\\\\\n || | \\/ | \\\\ \\\\| | | \\\\\n || | | \\\\ \\\\ | | \\\\\n \') |===== \') )====| \')\n | \\/ | | || |\n | || | (_)(_)\n | || | |_||_|\n |-||-| |_||_|\n____________[_][__\\__________________________________[_][__\\_______\n3\n /""\\ ====\n / o o ~~o o\n _\\ -/_ _\\ -/_\n /\\\\ //\\ / \\ / \\\n // \\\\// \\\\ //| | |\\\\\n || | \\/ | \\\\ \\\\| | | \\\\\n || | | \\\\ \\\\ | | \\\\\n \') |===== \') )====| \')\n | \\/ | | || |\n | || | (_)(_)\n | || | |_||_|\n |-||-| |_||_|\n____________[_][__\\__________________________________[_][__\\_______\n6\n /""\\ ====\n / o o o o~~\n _\\ -/_ _\\- /_\n /\\\\ //\\ / \\ / \\\n // \\\\// \\\\ //| | |\\\\\n || | \\/ | \\\\ \\\\| | | \\\\\n || | | \\\\ \\\\ | | \\\\\n \') |===== \') )====| \')\n | \\/ | | || |\n | || | (_)(_)\n | || | |_||_|\n |-||-| |_||_|\n____________[_][__\\__________________________________[_][__\\_______\n30\n /""\\ ====\n / o o Come on Red! o o~~\n _\\ -/_ _\\- /_\n /\\\\ //\\ / \\ / \\\n // \\\\// \\\\ //| | |\\\\\n || | \\/ | \\\\ \\\\| | | \\\\\n || | | \\\\ \\\\ | | \\\\\n \') |===== \') )====| \')\n | \\/ | | || |\n | || | (_)(_)\n | || | |_||_|\n |-||-| |_||_|\n____________[_][__\\__________________________________[_][__\\_______\n1\n /""\\ ====\n / o o o o~~\n _\\ -/_ _\\- /_\n /\\\\ //\\ / \\ / \\\n // \\\\// \\\\ //| | |\\\\\n || | \\/ | \\\\ \\\\| | | \\\\\n || | | \\\\ \\\\ | | \\\\\n \') |===== \') )====| \')\n | \\/ | | || |\n | || | (_)(_)\n | || | |_||_|\n |-||-| |_||_|\n____________[_][__\\__________________________________[_][__\\_______\n9\n / / / \\\n | | | |\n _____ | | | |\n / \\ \\ \\ \\_____/\n | o o| \\ \\\n _|_____|_ \\ \\\n | | === | | \\ \\ _____\n |_| o |_| \\ \\ / \\\n || o || \\ \\ | |\n ||__*__|| \\ \\ | |\n |~ \\___/ ~| \\ \\ \\_____/\n /=\\ /=\\ /=\\ \\ \\_____________\n------[_]-[_]-[_]-----------------------------------\\______________\n6\n / / / \\\n | | | |\n _____ | | | |\n / \\ \\ \\ \\_____/\n |o o | \\ \\\n _|_____|_ \\ \\\n | | === | | \\ \\ _____\n |_| o |_| \\ \\ / \\\n || o || \\ \\ | |\n ||__*__|| \\ \\ | |\n |~ \\___/ ~| \\ \\ \\_____/\n /=\\ /=\\ /=\\ \\ \\_____________\n------[_]-[_]-[_]-----------------------------------\\______________\n2\n / / / \\\n | | | |\n _____ | | | |\n / \\ \\ \\ \\_____/\n | o o| \\ \\\n _|_____|_ \\ \\\n | | === | | \\ \\ _____\n |_| o |_| \\ \\ / \\\n || o || \\ \\ | |\n ||__*__|| \\ \\ | |\n |~ \\___/ ~| \\ \\ \\_____/\n /=\\ /=\\ /=\\ \\ \\_____________\n------[_]-[_]-[_]-----------------------------------\\______________\n1\n / / / \\\n | | | |\n __.__ | | | |\n / \\ \\ \\ \\_____/\n | o o| \\ \\\n _|_____|_ \\ \\\n | | === | | \\ \\ _____\n |_| o |_| \\ \\ / \\\n || o || \\ \\ | |\n ||__*__|| \\ \\ | |\n |~ \\___/ ~| \\ \\ \\_____/\n /=\\ /=\\ /=\\ \\ \\_____________\n------[_]-[_]-[_]-----------------------------------\\______________\n1\n . / / / \\\n . ** \' | | | |\n *||*_ | | | |\n / \\ \\ \\ \\_____/\n | o o| \\ \\\n _|_____|_ \\ \\\n | | === | | \\ \\ _____\n |_| o |_| \\ \\ / \\\n || o || \\ \\ | |\n ||__*__|| \\ \\ | |\n |~ \\___/ ~| \\ \\ \\_____/\n /=\\ /=\\ /=\\ \\ \\_____________\n------[_]-[_]-[_]-----------------------------------\\______________\n1\n . ** \' / / / \\\n **** | | | |\n . **||** | | | |\n / \\ \\ \\ \\_____/\n | o o| \\ \\\n _|_____|_ \\ \\\n | | === | | \\ \\ _____\n |_| o |_| \\ \\ / \\\n || o || \\ \\ | |\n ||__*__|| \\ \\ | |\n |~ \\___/ ~| \\ \\ \\_____/\n /=\\ /=\\ /=\\ \\ \\_____________\n------[_]-[_]-[_]-----------------------------------\\______________\n1\n **** / / / \\\n ****** | | | |\n **||** | | | |\n . / \\ \' \\ \\ \\_____/\n | o o| \\ \\\n _|_____|_ \\ \\\n . | | === | | \\ \\ _____\n |_| o |_| \\ \\ / \\\n || o || \\ \\ | |\n ||__*__|| \\ \\ | |\n |~ \\___/ ~| \\ \\ \\_____/\n /=\\ /=\\ /=\\ \\ \\_____________\n------[_]-[_]-[_]-----------------------------------\\______________\n1\n ** / / / \\\n **** | | | |\n *||*_ | | | |\n / \\ \\ \\ \\_____/\n | o o| \\ \\\n _|_____|_ \' \\ \\\n . | | === | | \\ \\ _____\n |_| o |_| \\ \\ / \\\n || o || \\ \\ | |\n . ||__*__|| \\ \\ | |\n |~ \\___/ ~| \\ \\ \\_____/\n /=\\ /=\\ /=\\ \\ \\_____________\n------[_]-[_]-[_]-----------------------------------\\______________\n1\n / / / \\\n ** | | | |\n _||__ | | | |\n / \\ \\ \\ \\_____/\n | o o| \\ \\\n _|_____|_ \\ \\\n | | === | | \\ \\ _____\n |_| o |_| \\ \\ / \\\n . || o || \' \\ \\ | |\n ||__*__|| \\ \\ | |\n |~ \\___/ ~| \\ \\ \\_____/\n . /=\\ /=\\ /=\\ \\ \\_____________\n------[_]-[_]-[_]-----------------------------------\\______________\n1\n / / / \\\n * | | | |\n _||__ | | | |\n / \\ \\ \\ \\_____/\n | o o| \\ \\\n _|_____|_ \\ \\\n | | === | | \\ \\ _____\n |_| o |_| \\ \\ / \\\n || o || \\ \\ | |\n ||__*__|| \\ \\ | |\n |~ \\___/ ~| \' \\ \\ \\_____/\n. /=\\ /=\\ /=\\ \\ \\_____________\n------[_]-[_]-[_]-----------------------------------\\______________\n1\n . / / / \\\n * | | | |\n _||__ | | | |\n / \\ \\ \\ \\_____/\n | o o| \\ \\\n _|_____|_ \\ \\\n | | === | | \\ \\ _____\n |_| o |_| \\ \\ / \\\n || o || \\ \\ | |\n ||__*__|| \\ \\ | |\n |~ \\___/ ~| \\ \\ \\_____/\n /=\\ /=\\ /=\\ \' \\ \\_____________\n------[_]-[_]-[_]-----------------------------------\\______________\n1\n . / / / \\\n . | | | |\n _||__ | | | |\n / \\ \\ \\ \\_____/\n | o o| \\ \\\n _|_____|_ \\ \\\n | | === | | \\ \\ _____\n |_| o |_| \\ \\ / \\\n || o || \\ \\ | |\n ||__*__|| \\ \\ | |\n |~ \\___/ ~| \\ \\ \\_____/\n /=\\ /=\\ /=\\ \\ \\_____________\n------[_]-[_]-[_]---------\'-------------------------\\______________\n1\n . / / / \\\n | | | |\n _||__ | | | |\n / \\ \\ \\ \\_____/\n | o o| \\ \\\n _|_____|_ \\ \\\n | | === | | \\ \\ _____\n |_| o |_| \\ \\ / \\\n || o || \\ \\ | |\n ||__*__|| \\ \\ | |\n |~ \\___/ ~| \' \\ \\ \\_____/\n /=\\ /=\\ /=\\ \\ \\_____________\n------[_]-[_]-[_]-----------------------------------\\______________\n1\n / / / \\\n | | | |\n _||__ | | | |\n / \\ \\ \\ \\_____/\n | o o| \\ \\\n _|_____|_ \\ \\\n | | === | | \\ \\ _____\n |_| o |_| \\ \\ / \\\n || o || \\ \\ | |\n ||__*__|| \' \\ \\ | |\n |~ \\___/ ~| \\ \\ \\_____/\n /=\\ /=\\ /=\\ \\ \\_____________\n------[_]-[_]-[_]-----------------------------------\\______________\n1\n / / / \\\n | | | |\n _||__ | | | |\n / \\ \\ \\ \\_____/\n | o o| \\ \\\n _|_____|_ \\ \\\n | | === | | \\ \\ _____\n |_| o |_| \\ \\ / \\\n || o || \\ \\ | |\n ||__*__|| \\ \\ | |\n |~ \\___/ ~| \' \\ \\ \\_____/\n /=\\ /=\\ /=\\ \\ \\_____________\n------[_]-[_]-[_]-----------------------------------\\______________\n1\n / / / \\\n | | | |\n _||__ | | | |\n / \\ \\ \\ \\_____/\n | o o| \\ \\\n _|_____|_ \\ \\\n | | === | | \\ \\ _____\n |_| o |_| \\ \\ / \\\n || o || \\ \\ | |\n ||__*__|| \\ \\ | |\n |~ \\___/ ~| \\ \\ \\_____/\n /=\\ /=\\ /=\\ \' \\ \\_____________\n------[_]-[_]-[_]-----------------------------------\\______________\n1\n / / / \\\n | | | |\n _||__ | | | |\n / \\ \\ \\ \\_____/\n | o o| \\ \\\n _|_____|_ \\ \\\n | | === | | \\ \\ _____\n |_| o |_| \\ \\ / \\\n || o || \\ \\ | |\n ||__*__|| \\ \\ | |\n |~ \\___/ ~| \\ \\ \\_____/\n /=\\ /=\\ /=\\ \\ \\_____________\n------[_]-[_]-[_]----------------------------\'------\\______________\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n4\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | | \\\\\n || |\\ /| || || | | | \\\\\n # \\_ _/ # (` |====| \')\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n6\n /~\\ ====\n ( oo| Uncle Owen! o o~~\n _\\=/_ This R2 unit has _\\- /_\n / _ \\ a bad motivator. / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | | \\\\\n || |\\ /| || || | | | \\\\\n # \\_ _/ # (` |====| \')\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n14\n /~\\ ====\n |oo ) Uncle Owen! o o~~\n _\\=/_ This R2 unit has _\\- /_\n / _ \\ a bad motivator. / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | | \\\\\n || |\\ /| || || | | | \\\\\n # \\_ _/ # (` |====| \')\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n12\n /~\\ ====\n |oo ) Uncle Owen! o o~~\n _\\=/_ This R2 unit has _\\- /_\n / _ \\ a bad motivator. / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | |//\n || |\\ /| || || | | //\n # \\_ _/ # (` |===(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n3\n /~\\ ====\n |oo ) o o~~\n _\\=/_ _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | |//\n || |\\ /| || || | | //\n # \\_ _/ # (` |===(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n12\n /~\\ ====\n ( oo| Excuse me sir! o o~~\n _\\=/_ _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | |//\n || |\\ /| || || | | //\n # \\_ _/ # (` |===(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n12\n /~\\ ====\n ( oo| Excuse me sir! o o~~\n _\\=/_ _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || \\\\| | |//\n || |\\ /| || \\| | //\n # \\_ _/ # )===(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n4\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || \\\\| | |//\n || |\\ /| || \\| | //\n # \\_ _/ # )===(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n8\n /~\\ ====\n ( oo| That R2 unit is in o o~~\n _\\=/_ prime condition. _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || \\\\| | |//\n || |\\ /| || \\| | //\n # \\_ _/ # )===(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n5\n /~\\ ====\n |oo ) That R2 unit is in o o~~\n _\\=/_ prime condition. _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || \\\\| | |//\n || |\\ /| || \\| | //\n # \\_ _/ # )===(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n5\n /~\\ ====\n |oo ) That R2 unit is in o o~~\n _\\=/_ prime condition. _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n // \\_/ || \\\\| | |//\n // |\\ /| || \\| | //\n # \\_ _/ # )===(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n19\n /~\\ ====\n |oo ) That R2 unit is in o o~~\n _\\=/_ prime condition. _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n // \\_/ || \\\\| | |//\n // |\\ /| || \\| | //\n # \\_ _/ # )===(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n7\n /~\\ ====\n |oo ) o o~~\n _\\=/_ _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n // \\_/ || \\\\| | |//\n // |\\ /| || \\| | //\n # \\_ _/ # )===(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n20\n\n\n\n ___\n / ()\\\n _|_____|_\n | | === | |\n |_| O |_|\n || O ||\n ||__*__||\n |~ \\___/ ~|\n /=\\ /=\\ /=\\\n________________[_]_[_]_[_]________________________________________\n1\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || \\\\| | |//\n || |\\ /| || \\| | //\n # \\_ _/ # )===(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n21\n /~\\ ====\n ( oo| Uncle Owen! o o~~\n _\\=/_ _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || \\\\| | |//\n || |\\ /| || \\| | //\n # \\_ _/ # )===(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n18\n /~\\ ====\n ( oo| What about o o~~\n _\\=/_ that one? _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || \\\\| | |//\n || |\\ /| || \\| | //\n # \\_ _/ # )===(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n12\n /~\\ ====\n |oo ) What about o o~~\n _\\=/_ that one? _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || \\\\| | |//\n || |\\ /| || \\| | //\n # \\_ _/ # )===(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n11\n /~\\ ====\n |oo ) What about o o~~\n _\\=/_ that one? _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || // | | |//\n || |\\ /| || // | | //\n # \\_ _/ # (\' |===(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n7\n /~\\ ====\n |oo ) o o~~\n _\\=/_ _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || \\\\| | |//\n || |\\ /| || \\| | //\n # \\_ _/ # )===(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n7\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n / ()\\ //|/.\\|\\\\\n _|_____|_ || \\_/ ||\n | | === | | || |\\ /| ||\n |_| O |_| # \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n4\n /~\\\n |oo ) Now don\'t you\n _\\=/_ forget this.\n ___ / _ \\\n / ()\\ //|/.\\|\\\\\n _|_____|_ || \\_/ ||\n | | === | | || |\\ /| ||\n |_| O |_| # \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n11\n /~\\\n |oo ) Now don\'t you\n _\\=/_ forget this.\n ___ / _ \\\n / ()\\ //|/.\\|\\\\\n _|_____|_ // \\_/ ||\n | | === | | // |\\ /| ||\n |_| O |_| # \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n17\n /~\\\n |oo ) Now don\'t you\n _\\=/_ forget this.\n ___ / _ \\\n / ()\\ //|/.\\|\\\\\n _|_____|_ || \\_/ ||\n | | === | | || |\\ /| ||\n |_| O |_| # \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n9\n /~\\\n |oo )\n _\\=/_\n ___ / _ \\\n / ()\\ //|/.\\|\\\\\n _|_____|_ || \\_/ ||\n | | === | | || |\\ /| ||\n |_| O |_| # \\_ _/ #\n || O || | | |\n ||__*__|| | | |\n |~ \\___/ ~| []|[]\n /=\\ /=\\ /=\\ | | |\n________________[_]_[_]_[_]________/_]_[_\\_________________________\n5\n\n\n\n\n\n\n\n\n\n\n\n\n\n2\n /_] [_\\ ====\n o o~~\n _\\- /_\n ___ / \\ / \\\n / ()\\ //| | |\\\\\n _|_____|_ // | | |//\n =================== | | === | | // | | //\n | | |_| O |_|(\' |===(|\n |_________________| || O || | || |\n | | ||__*__|| (_)(_)\n | | |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n______|_________________|_______[_]_[_]_[_]____/__][__\\____________\n2\n | | | ====\n /_] [_\\ o o~~\n _\\- /_\n ___ / \\ / \\\n / ()\\ //| | |\\\\\n _|_____|_ // | | |//\n =================== | | === | | // | | //\n | | |_| O |_|(\' |===(|\n |_________________| || O || | || |\n | | ||__*__|| (_)(_)\n | | |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n______|_________________|_______[_]_[_]_[_]____/__][__\\____________\n2\n []|[] ====\n | | | o o~~\n /_] [_\\ _\\- /_\n ___ / \\ / \\\n / ()\\ //| | |\\\\\n _|_____|_ // | | |//\n =================== | | === | | // | | //\n | | |_| O |_|(\' |===(|\n |_________________| || O || | || |\n | | ||__*__|| (_)(_)\n | | |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n______|_________________|_______[_]_[_]_[_]____/__][__\\____________\n2\n | | | ====\n []|[] o o~~\n | | | _\\- /_\n /_] [_\\ ___ / \\ / \\\n / ()\\ //| | |\\\\\n _|_____|_ // | | |//\n =================== | | === | | // | | //\n | | |_| O |_|(\' |===(|\n |_________________| || O || | || |\n | | ||__*__|| (_)(_)\n | | |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n______|_________________|_______[_]_[_]_[_]____/__][__\\____________\n2\n | | | ====\n | | | o o~~\n []|[] _\\- /_\n | | | ___ / \\ / \\\n /_] [_\\ / ()\\ //| | |\\\\\n _|_____|_ // | | |//\n =================== | | === | | // | | //\n | | |_| O |_|(\' |===(|\n |_________________| || O || | || |\n | | ||__*__|| (_)(_)\n | | |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n______|_________________|_______[_]_[_]_[_]____/__][__\\____________\n2\n # \\_ _/ # ====\n | | | o o~~\n | | | _\\- /_\n []|[] ___ / \\ / \\\n | | | / ()\\ //| | |\\\\\n /_] [_\\ _|_____|_ // | | |//\n =================== | | === | | // | | //\n | | |_| O |_|(\' |===(|\n |_________________| || O || | || |\n | | ||__*__|| (_)(_)\n | | |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n______|_________________|_______[_]_[_]_[_]____/__][__\\____________\n2\n || |\\ /| || ====\n # \\_ _/ # o o~~\n | | | _\\- /_\n | | | ___ / \\ / \\\n []|[] / ()\\ //| | |\\\\\n | | | _|_____|_ // | | |//\n =================== | | === | | // | | //\n | | |_| O |_|(\' |===(|\n |_________________| || O || | || |\n | | ||__*__|| (_)(_)\n | | |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n______|_________________|_______[_]_[_]_[_]____/__][__\\____________\n2\n || \\_/ || ====\n || |\\ /| || o o~~\n # \\_ _/ # _\\- /_\n | | | ___ / \\ / \\\n | | | / ()\\ //| | |\\\\\n []|[] _|_____|_ // | | |//\n =================== | | === | | // | | //\n | | |_| O |_|(\' |===(|\n |_________________| || O || | || |\n | | ||__*__|| (_)(_)\n | | |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n______|_________________|_______[_]_[_]_[_]____/__][__\\____________\n2\n //|/.\\|\\\\ ====\n || \\_/ || o o~~\n || |\\ /| || _\\- /_\n # \\_ _/ # ___ / \\ / \\\n | | | / ()\\ //| | |\\\\\n | | | _|_____|_ // | | |//\n =================== | | === | | // | | //\n | | |_| O |_|(\' |===(|\n |_________________| || O || | || |\n | | ||__*__|| (_)(_)\n | | |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n______|_________________|_______[_]_[_]_[_]____/__][__\\____________\n2\n / _ \\ ====\n //|/.\\|\\\\ o o~~\n || \\_/ || _\\- /_\n || |\\ /| || ___ / \\ / \\\n # \\_ _/ # / ()\\ //| | |\\\\\n | | | _|_____|_ // | | |//\n =================== | | === | | // | | //\n | | |_| O |_|(\' |===(|\n |_________________| || O || | || |\n | | ||__*__|| (_)(_)\n | | |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n______|_________________|_______[_]_[_]_[_]____/__][__\\____________\n2\n _\\=/_ ====\n / _ \\ Thank the maker! o o~~\n //|/.\\|\\\\ _\\- /_\n || \\_/ || ___ / \\ / \\\n || |\\ /| || / ()\\ //| | |\\\\\n # \\_ _/ # _|_____|_ // | | |//\n =================== | | === | | // | | //\n | | |_| O |_|(\' |===(|\n |_________________| || O || | || |\n | | ||__*__|| (_)(_)\n | | |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n______|_________________|_______[_]_[_]_[_]____/__][__\\____________\n2\n ( oo| ====\n _\\=/_ Thank the maker! o o~~\n / _ \\ _\\- /_\n //|/.\\|\\\\ ___ / \\ / \\\n || \\_/ || / ()\\ //| | |\\\\\n || |\\ /| || _|_____|_ // | | |//\n =================== | | === | | // | | //\n | | |_| O |_|(\' |===(|\n |_________________| || O || | || |\n | | ||__*__|| (_)(_)\n | | |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n______|_________________|_______[_]_[_]_[_]____/__][__\\____________\n2\n /~\\ ====\n ( oo| Thank the maker! o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ // | | |//\n =================== | | === | | // | | //\n | | |_| O |_|(\' |===(|\n |_________________| || O || | || |\n | | ||__*__|| (_)(_)\n | | |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n______|_________________|_______[_]_[_]_[_]____/__][__\\____________\n2\n ====\n /~\\ Thank the maker! o o~~\n ( oo| _\\- /_\n _\\=/_ ___ / \\ / \\\n / _ \\ / ()\\ //| | |\\\\\n //|/.\\|\\\\ _|_____|_ // | | |//\n =================== | | === | | // | | //\n | | |_| O |_|(\' |===(|\n |_________________| || O || | || |\n | | ||__*__|| (_)(_)\n | | |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n______|_________________|_______[_]_[_]_[_]____/__][__\\____________\n22\n ====\n Thank the maker! o o~~\n /~\\ _\\- /_\n ( oo| ___ / \\ / \\\n _\\=/_ / ()\\ //| | |\\\\\n / _ \\ _|_____|_ // | | |//\n =================== | | === | | // | | //\n | | |_| O |_|(\' |===(|\n |_________________| || O || | || |\n | | ||__*__|| (_)(_)\n | | |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n______|_________________|_______[_]_[_]_[_]____/__][__\\____________\n3\n ====\n o o~~\n /~\\ _\\- /_\n ( oo| ___ / \\ / \\\n _\\=/_ / ()\\ //| | |\\\\\n / _ \\ _|_____|_ // | | |//\n =================== | | === | | // | | //\n | | |_| O |_|(\' |===(|\n |_________________| || O || | || |\n | | ||__*__|| (_)(_)\n | | |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n______|_________________|_______[_]_[_]_[_]____/__][__\\____________\n15\n ====\n This oil bath o o~~\n /~\\ is going to _\\- /_\n ( oo| feel so good. ___ / \\ / \\\n _\\=/_ / ()\\ //| | |\\\\\n / _ \\ _|_____|_ // | | |//\n =================== | | === | | // | | //\n | | |_| O |_|(\' |===(|\n |_________________| || O || | || |\n | | ||__*__|| (_)(_)\n | | |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n______|_________________|_______[_]_[_]_[_]____/__][__\\____________\n12\n ====\n This oil bath o o~~\n /~\\ is going to _\\- /_\n |oo ) feel so good. ___ / \\ / \\\n _\\=/_ / ()\\ //| | |\\\\\n / _ \\ _|_____|_ // | | |//\n =================== | | === | | // | | //\n | | |_| O |_|(\' |===(|\n |_________________| || O || | || |\n | | ||__*__|| (_)(_)\n | | |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n______|_________________|_______[_]_[_]_[_]____/__][__\\____________\n5\n ====\n o o~~\n /~\\ _\\- /_\n |oo ) ___ / \\ / \\\n _\\=/_ / ()\\ //| | |\\\\\n / _ \\ _|_____|_ // | | |//\n =================== | | === | | // | | //\n | | |_| O |_|(\' |===(|\n |_________________| || O || | || |\n | | ||__*__|| (_)(_)\n | | |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n______|_________________|_______[_]_[_]_[_]____/__][__\\____________\n1\n ====\n o o~~\n /~\\ _\\- /_\n ( oo| ___ / \\ / \\\n _\\=/_ / ()\\ //| | |\\\\\n / _ \\ _|_____|_ // | | |//\n =================== | | === | | // | | //\n | | |_| O |_|(\' |===(|\n |_________________| || O || | || |\n | | ||__*__|| (_)(_)\n | | |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n______|_________________|_______[_]_[_]_[_]____/__][__\\____________\n4\n\n\n\n\n\n\n\n\n\n\n\n\n\n31\n ====\n o o~~ Well, my\n _\\- /_ little friend...\n ___ / \\ / \\\n / ()\\ //| | |\\\\\n _|_____|_ // | | |//\n | | === | | // | | //\n |_| O |_|(\' |===(|\n || O || | || |\n ||__*__|| (_)(_)\n ------- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n6\n ====\n o o~~\n _\\- /_\n ___ / \\ / \\\n / ()\\ //| | |\\\\\n _|_____|_ // | | |//\n | | === | | // | | //\n |_| O |_|(\' |===(|\n || O || | || |\n ||__*__|| (_)(_)\n ------- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n15\n ====\n o o~~ ...you\'ve got\n _\\- /_ something jammed\n ___ / \\ / \\ in here real good.\n / ()\\ //| | |\\\\\n _|_____|_ // | | |//\n | | === | | // | | //\n |_| O |_|(\' |===(|\n || O || | || |\n ||__*__|| (_)(_)\n ------- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n16\n ====\n o o~~ ...you\'ve got\n _\\- /_ something jammed\n ___ / \\ / \\ in here real good.\n /() \\ //| | |\\\\\n _|_____|_ // | | |//\n | | === | | // | | //\n |_| O |_|(\' |===(|\n || O || | || |\n ||__*__|| (_)(_)\n ------- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n5\n ====\n o o~~\n _\\- /_\n ___ / \\ / \\\n /() \\ //| | |\\\\\n _|_____|_ // | | |//\n ,@ | | === | | // | | //\n /=- |_| O |_|(\' |===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n4\n ====\n o o~~\n _\\O /_\n ___ / \\ / \\\n /() \\ //| | |\\\\\n _|_____|_ // | | |//\n ,@ | | === | | // | | //\n /=- |_| O |_|(\' |===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n14\n ====\n Help me, o o~~\n Obi-Wan Kenobi! _\\O /_\n ___ / \\ / \\\n /() \\ //| | |\\\\\n _|_____|_ // | | |//\n ,@ | | === | | // | | //\n /=- |_| O |_|(\' |===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n15\n ====\n You\'re my only o o~~\n hope! _\\- /_\n ___ / \\ / \\\n /() \\ //| | |\\\\\n _|_____|_ // | | |//\n ,@ | | === | | // | | //\n /=- |_| O |_|(\' |===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n6\n ====\n o o~~\n _\\- /_\n ___ / \\ / \\\n /() \\ //| | |\\\\\n _|_____|_ // | | |//\n ,@ | | === | | // | | //\n /=- |_| O |_|(\' |===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n14\n ====\n Help me, o o~~\n Obi-Wan Kenobi! _\\- /_\n ___ / \\ / \\\n /() \\ //| | |\\\\\n _|_____|_ // | | |//\n ,@ | | === | | // | | //\n /=- |_| O |_|(\' |===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n15\n ====\n You\'re my only o o~~\n hope! _\\- /_\n ___ / \\ / \\\n /() \\ //| | |\\\\\n _|_____|_ // | | |//\n ,@ | | === | | // | | //\n /=- |_| O |_|(\' |===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n5\n ====\n o o~~\n _\\- /_\n ___ / \\ / \\\n /() \\ //| | |\\\\\n _|_____|_ // | | |//\n ,@ | | === | | // | | //\n /=- |_| O |_|(\' |===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n5\n ====\n o o~~ Who is she?\n _\\- /_\n ___ / \\ / \\\n /() \\ //| | |\\\\\n _|_____|_ // | | |//\n ,@ | | === | | // | | //\n /=- |_| O |_|(\' |===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n1\n ====\n o o~~ Who is she?\n _\\- /_\n ___ / \\ / \\\n / ()\\ //| | |\\\\\n _|_____|_ // | | |//\n ,@ | | === | | // | | //\n /=- |_| O |_|(\' |===(|\n || || O || | || |\n || ||__ __|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n14\n ====\n o o~~ Who is she?\n _\\- /_\n ___ / \\ / \\\n / ()\\ //| | |\\\\\n _|_____|_ // | | |//\n ,@ | | === | | // | | //\n /=- |_| O |_|(\' |===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n5\n ====\n o o~~ Who is she?\n _\\- /_\n ___ / \\ / \\\n /() \\ //| | |\\\\\n _|_____|_ // | | |//\n ,@ | | === | | // | | //\n /=- |_| O |_|(\' |===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n1\n ====\n o o~~ Who is she?\n _\\- /_\n ___ / \\ / \\\n / ()\\ //| | |\\\\\n _|_____|_ // | | |//\n ,@ | | === | | // | | //\n /=- |_| O |_|(\' |===(|\n || || O || | || |\n || ||__ __|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n14\n ====\n o o~~ Who is she?\n _\\- /_\n ___ / \\ / \\\n / ()\\ //| | |\\\\\n _|_____|_ // | | |//\n ,@ | | === | | // | | //\n /=- |_| O |_|(\' |===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n6\n ====\n o o~~ She\'s\n _\\- /_ beautiful!\n ___ / \\ / \\\n / ()\\ //| | |\\\\\n _|_____|_ // | | |//\n ,@ | | === | | // | | //\n /=- |_| O |_|(\' |===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n11\n ====\n o o~~ She\'s\n _\\- /_ beautiful!\n ___ / \\ / \\\n /() \\ //| | |\\\\\n _|_____|_ // | | |//\n ,@ | | === | | // | | //\n /=- |_| O |_|(\' |===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n8\n ====\n o o~~ She\'s\n _\\- /_ beautiful!\n ___ / \\ / \\\n / ()\\ //| | |\\\\\n _|_____|_ // | | |//\n ,@ | | === | | // | | //\n /=- |_| O |_|(\' |===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n9\n ====\n o o~~ She\'s\n _\\- /_ beautiful!\n ___ / \\ / \\\n / ()\\ //| | |\\\\\n _|_____|_ \\\\| | |//\n ,@ | | === | | \\\\ | //\n /=- |_| O |_| (===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n5\n ====\n o o~~\n _\\- /_\n ___ / \\ / \\\n / ()\\ //| | |\\\\\n _|_____|_ \\\\| | |//\n ,@ | | === | | \\\\ | //\n /=- |_| O |_| (===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n10\n ====\n He says it\'s o o~~\n nothing sir. _\\- /_\n ___ / \\ / \\\n / ()\\ //| | |\\\\\n _|_____|_ \\\\| | |//\n ,@ | | === | | \\\\ | //\n /=- |_| O |_| (===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n18\n ====\n He says it\'s o o~~\n nothing sir. _\\- /_\n ___ / \\ / \\\n /() \\ //| | |\\\\\n _|_____|_ \\\\| | |//\n ,@ | | === | | \\\\ | //\n /=- |_| O |_| (===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n28\n ====\n Old data. o o~~\n Pay it no mind. _\\- /_\n ___ / \\ / \\\n /() \\ //| | |\\\\\n _|_____|_ \\\\| | |//\n ,@ | | === | | \\\\ | //\n /=- |_| O |_| (===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n5\n ====\n o o~~\n _\\- /_\n ___ / \\ / \\\n /() \\ //| | |\\\\\n _|_____|_ \\\\| | |//\n ,@ | | === | | \\\\ | //\n /=- |_| O |_| (===(|\n || || O || | || |\n || ||__*__|| (_)(_)\n --~~--- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n3\n ====\n o o~~\n _\\o /_\n ___ / \\ / \\\n /() \\ //| | |\\\\\n _|_____|_ \\\\| | |//\n | | === | | \\\\ | //\n |_| O |_| (===(|\n || O || | || |\n ||__*__|| (_)(_)\n ------- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n11\n ====\n o o~~\n _\\- /_\n ___ / \\ / \\\n /() \\ //| | |\\\\\n _|_____|_ \\\\| | |//\n | | === | | \\\\ | //\n |_| O |_| (===(|\n || O || | || |\n ||__*__|| (_)(_)\n ------- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n10\n ====\n o o~~ Where\'d she go?\n _\\- /_\n ___ / \\ / \\\n /() \\ //| | |\\\\\n _|_____|_ \\\\| | |//\n | | === | | \\\\ | //\n |_| O |_| (===(|\n || O || | || |\n ||__*__|| (_)(_)\n ------- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n17\n ====\n o o~~ Where\'d she go?\n _\\- /_\n ___ / \\ / \\\n /() \\ //| | |\\\\\n _|_____|_ // | | | \\\\\n | | === | | // | | | \\\\\n |_| O |_|(\' |====| `)\n || O || | || |\n ||__*__|| (_)(_)\n ------- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n8\n ====\n o o~~ Where\'d she go?\n _\\- /_\n ___ / \\ / \\\n /() \\ //| | |\\\\\n _|_____|_ \\\\| | |//\n | | === | | \\\\ | //\n |_| O |_| )===(|\n || O || | || |\n ||__*__|| (_)(_)\n ------- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n9\n ====\n o o~~ Bring her back!\n _\\- /_\n ___ / \\ / \\\n /() \\ //| | |\\\\\n _|_____|_ \\\\| | |//\n | | === | | \\\\ | //\n |_| O |_| )===(|\n || O || | || |\n ||__*__|| (_)(_)\n ------- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n21\n ====\n o o~~ Bring her back!\n _\\- /_\n ___ / \\ / \\\n / ()\\ //| | |\\\\\n _|_____|_ \\\\| | |//\n | | === | | \\\\ | //\n |_| O |_| )===(|\n || O || | || |\n ||__*__|| (_)(_)\n ------- |~ \\___/ ~| |_||_|\n | | /=\\ /=\\ /=\\ |_||_|\n_________|_____|______[_]_[_]_[_]____/__][__\\______________________\n6\n\n\n\n\n\n\n\n\n\n\n\n\n\n5\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ // | | |//\n || |\\ /| || | | === | | // | | //\n # \\_ _/ # |_| O |_|(\' |===(|\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] ------- |~ \\___/ ~| |_||_|\n | | | | | /=\\ /=\\ /=\\ |_||_|\n_____/_]_[_\\_________|_____|______[_]_[_]_[_]____/__][__\\__________\n1\n /~\\ ====\n ( oo| See what you o o~~\n _\\=/_ can do with him. _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ // | | |//\n || |\\ /| || | | === | | // | | //\n # \\_ _/ # |_| O |_|(\' |===(|\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] ------- |~ \\___/ ~| |_||_|\n | | | | | /=\\ /=\\ /=\\ |_||_|\n_____/_]_[_\\_________|_____|______[_]_[_]_[_]____/__][__\\__________\n14\n /~\\ ====\n ( oo| See what you o o~~\n _\\=/_ can do with him. _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ // | | |//\n || |\\ /| || | | === | | // | | //\n # \\_ _/ # |_| O |_|(\' |===(|\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] ------- |~ \\___/ ~| |_||_|\n | | | | | /=\\ /=\\ /=\\ |_||_|\n_____/_]_[_\\_________|_____|______[_]_[_]_[_]____/__][__\\__________\n13\n /~\\ ====\n ( oo| See what you o o~~\n _\\=/_ can do with him. _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ /() \\ //| | |\\\\\n || \\_/ || _|_____|_ // | | |//\n || |\\ /| || | | === | | // | | //\n # \\_ _/ # |_| O |_|(\' |===(|\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] ------- |~ \\___/ ~| |_||_|\n | | | | | /=\\ /=\\ /=\\ |_||_|\n_____/_]_[_\\_________|_____|______[_]_[_]_[_]____/__][__\\__________\n3\n /~\\ ====\n ( oo| See what you o o~~\n _\\=/_ can do with him. _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ /() \\ //| | |\\\\\n || \\_/ || _|_____|_ // | | |//\n || |\\ /| || | | === | | // | | //\n # \\_ _/ # |_| O |_|(\' |===(|\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] ------- |~ \\___/ ~| |_||_|\n | | | | | /=\\ /=\\ /=\\ |_||_|\n_____/_]_[_\\_________|_____|______[_]_[_]_[_]____/__][__\\__________\n2\n /~\\ ====\n ( oo| See what you o o~~\n _\\=/_ can do with him. _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ /() \\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(|\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] ------- |~ \\___/ ~| |_||_|\n | | | | | /=\\ /=\\ /=\\ |_||_|\n_____/_]_[_\\_________|_____|______[_]_[_]_[_]____/__][__\\__________\n8\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ /() \\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(|\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] ------- |~ \\___/ ~| |_||_|\n | | | | | /=\\ /=\\ /=\\ |_||_|\n_____/_]_[_\\_________|_____|______[_]_[_]_[_]____/__][__\\__________\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n5\n /""\\ ====\n / o o o o~~\n _\\ -/_ _\\- /_\n /\\\\ //\\ / \\ / \\\n | \\\\// \\/() //| | |\\\\\n || \\/ |\\/ \\\\| |__|//\n ------------------------------(---||//-----\n / ||) \\\n / == \\\n / \\\n / \\\n / \\\n -------------------------------------------------------\n29\n /""\\ ====\n / o o o o~~ If these new\n _\\ -/_ _\\- /_ droids do work\n /\\\\ //\\ / \\ / \\ out...\n | \\\\// \\/() //| | |\\\\\n || \\/ |\\/ \\\\| |__|//\n ------------------------------(---||//-----\n / ||) \\\n / == \\\n / \\\n / \\\n / \\\n -------------------------------------------------------\n16\n /""\\ ====\n / o o o o~~ ...I want to\n _\\ -/_ _\\- /_ transmit my\n /\\\\ //\\ / \\ / \\ application\n | \\\\// \\/() //| | |\\\\ to the...\n || \\/ |\\/ \\\\| |__|//\n ------------------------------(---||//-----\n / ||) \\\n / == \\\n / \\\n / \\\n / \\\n -------------------------------------------------------\n16\n /""\\ ====\n / o o o o~~ ...I want to\n _\\ -/_ _\\- /_ transmit my\n /\\\\ //\\ / \\ / \\ application\n | \\\\// \\ //| | |\\\\ to the...\n || \\/ |\\\\ \\\\| |__|//\n --------------\\()-------------(---||//-----\n / ||) \\\n / == \\\n / \\\n / \\\n / \\\n -------------------------------------------------------\n16\n /""\\ ====\n / o o o o~~ ...Academy\n _\\ -/_ _\\- /_ this year.\n /\\\\ //\\ / \\ / \\\n | \\\\// \\ //| | |\\\\\n || \\/ |\\\\ \\\\| |__|//\n --------------\\()-------------(---||//-----\n / ||) \\\n / == \\\n / \\\n / \\\n / \\\n -------------------------------------------------------\n6\n /""\\ ====\n / o o o o~~\n _\\ -/_ _\\- /_\n /\\\\ //\\ / \\ / \\\n | \\\\// \\ //| | |\\\\\n || \\/ |\\\\ \\\\| |__|//\n --------------\\()-------------(---||//-----\n / ||) \\\n / == \\\n / \\\n / \\\n / \\\n -------------------------------------------------------\n16\n /""\\ ====\n But harvest / o o o o~~\n is when I need _\\ -/_ _\\- /_\n you the most! /\\\\ //\\ / \\ / \\\n | \\\\// \\ //| | |\\\\\n || \\/ |\\\\ \\\\| |__|//\n --------------\\()-------------(---||//-----\n / ||) \\\n / == \\\n / \\\n / \\\n / \\\n -------------------------------------------------------\n15\n /""\\ ====\n But harvest / o o o o~~\n is when I need _\\ -/_ _\\- /_\n you the most! /\\\\ //\\ / \\ / \\\n | \\\\// \\ //| | |\\\\\n || \\/ |\\\\ \\\\__| |//\n --------------\\()-------------(||---//-----\n / || ) \\\n / == \\\n / \\\n / \\\n / \\\n -------------------------------------------------------\n5\n /""\\ ====\n / o o o o~~\n _\\ -/_ _\\- /_\n /\\\\ //\\ / \\ / \\\n | \\\\// \\ //| | |\\\\\n || \\/ |\\\\ \\\\__| |//\n --------------\\()-------------(||---//-----\n / || ) \\\n / == \\\n / \\\n / \\\n / \\\n -------------------------------------------------------\n29\n /""\\ ====\n / o o o o~~ But it\'s a\n _\\ -/_ _\\- /_ whole \'nother\n /\\\\ //\\ / \\ / \\ year!\n | \\\\// \\ //| | |\\\\\n || \\/ |\\\\ \\\\__| |//\n --------------\\()-------------(||---//-----\n / || ) \\\n / == \\\n / \\\n / \\\n / \\\n -------------------------------------------------------\n4\n /""\\ ====\n / o o o o~~\n _\\ -/_ _\\- /_\n /\\\\ //\\ / \\ / \\\n | \\\\// \\ //| | |\\\\\n || \\/ |\\\\ \\\\__| |//\n --------------\\()-------------(||---//-----\n / || ) \\\n / == \\\n / \\\n / \\\n / \\\n -------------------------------------------------------\n1\n /""\\ ====\n / o o o o~~\n _\\ -/_ _\\- /_\n /\\\\ //\\ / \\ / \\\n | \\\\// \\ //| | |\\\\\n || \\/ |\\\\ \\\\__| |//\n --------------\\()-------------(||---//-----\n / || ) \\\n / == \\\n / \\\n / \\\n /\n -------------------------------------------------------\n6\n\n\n\n\n\n\n\n\n\n\n\n\n\n3\n /""\\ ====\n / o o o o~~\n _\\ -/_ _\\- /_\n /\\\\ //\\ __ / \\ / \\\n | \\\\// \\ || //| | |\\\\\n || \\/ |\\\\ || \\\\| | |//\n -------------------------------==---------- \\\\ | //\n | | )===(|\n | | | || |\n | | (_)(_)\n | | |_||_|\n | | |_||_|\n______|_________________________________________|___/__][__\\_______\n41\n /""\\ ====\n / o o Where are o o~~\n _\\ -/_ you going? _\\- /_\n /\\\\ //\\ __ / \\ / \\\n | \\\\// \\ || //| | |\\\\\n || \\/ |\\\\ || \\\\| | |//\n -------------------------------==---------- \\\\ | //\n | | )===(|\n | | | || |\n | | (_)(_)\n | | |_||_|\n | | |_||_|\n______|_________________________________________|___/__][__\\_______\n4\n /""\\ ====\n / o o o o~~\n _\\ -/_ _\\- /_\n /\\\\ //\\ __ / \\ / \\\n | \\\\// \\ || //| | |\\\\\n || \\/ |\\\\ || \\\\| | |//\n -------------------------------==---------- \\\\ | //\n | | )===(|\n | | | || |\n | | (_)(_)\n | | |_||_|\n | | |_||_|\n______|_________________________________________|___/__][__\\_______\n31\n /""\\ Looks like I\'m ====\n / o o going nowhere! o o~~\n _\\ -/_ _\\- /_\n /\\\\ //\\ __ / \\ / \\\n | \\\\// \\ || //| | |\\\\\n || \\/ |\\\\ || \\\\| | |//\n -------------------------------==---------- \\\\ | //\n | | )===(|\n | | | || |\n | | (_)(_)\n | | |_||_|\n | | |_||_|\n______|_________________________________________|___/__][__\\_______\n3\n /""\\ ====\n / o o o o~~\n _\\ -/_ _\\- /_\n /\\\\ //\\ __ / \\ / \\\n | \\\\// \\ || //| | |\\\\\n || \\/ |\\\\ || \\\\| | |//\n -------------------------------==---------- \\\\ | //\n | | )===(|\n | | | || |\n | | (_)(_)\n | | |_||_|\n | | |_||_|\n______|_________________________________________|___/__][__\\_______\n30\n /""\\ I have to go finish ====\n / o o cleaning those droids. o o~~\n _\\ -/_ _\\- /_\n /\\\\ //\\ __ / \\ / \\\n | \\\\// \\ || //| | |\\\\\n || \\/ |\\\\ || \\\\| | |//\n -------------------------------==---------- \\\\ | //\n | | )===(|\n | | | || |\n | | (_)(_)\n | | |_||_|\n | | |_||_|\n______|_________________________________________|___/__][__\\_______\n5\n /""\\ ====\n / o o o o~~\n _\\ -/_ _\\- /_\n /\\\\ //\\ __ / \\ / \\\n | \\\\// \\ || //| | |\\\\\n || \\/ |\\\\ || \\\\| | |//\n -------------------------------==---------- \\\\ | //\n | | )===(|\n | | | || |\n | | (_)(_)\n | | |_||_|\n | | |_||_|\n______|_________________________________________|___/__][__\\_______\n9\n\n\n\n\n\n\n\n\n\n\n\n\n\n5\n ====\n o o~~\n _\\- /_\n\\ / \\ / \\\n \\ //| | |\\\\\n____\\___________________ \\\\| | |//\n \\ \\ \\| | //\n \\ \\ )===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n14\n ====\n ~~o o\n _\\ -/_\n\\ / \\ / \\\n \\ //| | |\\\\\n____\\___________________ \\\\| | |//\n \\ \\ \\| | //\n \\ \\ )===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n10\n ====\n o o~~\n _\\- /_\n\\ / \\ / \\\n \\ //| | |\\\\\n____\\___________________ \\\\| | |//\n \\ \\ \\| | //\n \\ \\ )===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n5\n ====\n o o~~\n _\\- /_\n\\ / \\ / \\\n \\ //| | |\\\\\n____\\___________________ // | | |//\n \\ \\ // | | //\n \\ \\ -(] |===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n2\n ====\n o o~~\n _\\- /_\n\\ / \\ / \\\n \\ //| | |\\\\\n____\\___________________ // | | |//\n \\ \\ // | | //\n \\ \\ *(] |===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n1\n ====\n o o~~\n _\\- /_\n\\ / \\ / \\\n \\ //| | |\\\\\n____\\_______/~\\_________ // | | |//\n \\ \\ // | | //\n \\ \\ *(] |===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n1\n ====\n o o~~\n _\\- /_\n\\ / \\ / \\\n \\ /~\\ //| | |\\\\\n____\\______( oo|________ // | | |//\n \\ \\ // | | //\n \\ \\ -(] |===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n1\n ====\n o o~~\n _\\- /_\n\\ /~\\ / \\ / \\\n \\ ( oo| //| | |\\\\\n____\\_______\\=/_________ // | | |//\n \\ \\ // | | //\n \\ \\ -(] |===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n1\n ====\n o o~~\n /~\\ _\\- /_\n\\ ( oo| / \\ / \\\n \\ _\\=/_ //| | |\\\\\n____\\_____/_____\\_______ // | | |//\n \\ \\ // | | //\n \\ \\ -(] |===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n1\n ====\n /~\\ o o~~\n ( oo| _\\- /_\n\\ _\\=/_ / \\ / \\\n \\ / _ \\ //| | |\\\\\n____\\____//|/_\\|\\\\______ // | | |//\n \\ \\ // | | //\n \\ \\ -(] |===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n1\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n\\ / _ \\ / \\ / \\\n \\ //|/.\\|\\\\ //| | |\\\\\n____\\___||__\\_/__||_____ // | | |//\n \\ \\ // | | //\n \\ \\ -(] |===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n3\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n\\ / _ \\ / \\ / \\\n \\ //|/.\\|\\\\ //| | |\\\\\n____\\___||__\\_/__||_____ // | | |//\n \\ \\ // | | //\n \\ \\ *(] |===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n4\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n\\ / _ \\ / \\ / \\\n \\ //|/.\\|\\\\ //| | |\\\\\n____\\___||__\\_/__||_____ // | | |//\n \\ \\ // | | //\n \\ \\ -(] |===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n30\n /~\\ ====\n ( oo| What are you doing o o~~\n _\\=/_ hiding back there? _\\- /_\n\\ / _ \\ / \\ / \\\n \\ //|/.\\|\\\\ //| | |\\\\\n____\\___||__\\_/__||_____ // | | |//\n \\ \\ // | | //\n \\ \\ -(] |===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n6\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n\\ / _ \\ / \\ / \\\n \\ //|/.\\|\\\\ //| | |\\\\\n____\\___||__\\_/__||_____ // | | |//\n \\ \\ // | | //\n \\ \\ -(] |===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n30\n /~\\ ====\n ( oo| It wasn\'t my fault o o~~\n _\\=/_ sir... _\\- /_\n\\ / _ \\ / \\ / \\\n \\ //|/.\\|\\\\ //| | |\\\\\n____\\___||__\\_/__||_____ // | | |//\n \\ \\ // | | //\n \\ \\ -(] |===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n30\n /~\\ ====\n ( oo| ...he kept babbling o o~~\n _\\=/_ about his mission. _\\- /_\n\\ / _ \\ / \\ / \\\n \\ //|/.\\|\\\\ //| | |\\\\\n____\\___||__\\_/__||_____ // | | |//\n \\ \\ // | | //\n \\ \\ -(] |===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n5\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n\\ / _ \\ / \\ / \\\n \\ //|/.\\|\\\\ //| | |\\\\\n____\\___||__\\_/__||_____ // | | |//\n \\ \\ // | | //\n \\ \\ -(] |===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n20\n /~\\ ====\n ( oo| Oh no! o o~~\n _\\=/_ _\\- /_\n\\ / _ \\ / \\ / \\\n \\ //|/.\\|\\\\ //| | |\\\\\n____\\___||__\\_/__||_____ // | | |//\n \\ \\ // | | //\n \\ \\ -(] |===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n9\n /~\\ ====\n ( oo| Oh no! o o~~\n _\\=/_ _\\- /_\n\\ / _ \\ / \\ / \\\n \\ //|/.\\|\\\\ //| | |\\\\\n____\\___||__\\_/__||_____ \\\\| | |//\n \\ \\ \\| | //\n \\ \\ )===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n6\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n\\ / _ \\ / \\ / \\\n \\ //|/.\\|\\\\ //| | |\\\\\n____\\___||__\\_/__||_____ \\\\| | |//\n \\ \\ \\| | //\n \\ \\ )===(|\n \\ \\ | || |\n \\ \\ (_)(_)\n___________________\\_____________\\ |_||_|\n | |_||_|\n_____________________________|_____________________/__][__\\________\n5\n\n\n\n\n\n\n\n\n\n\n\n\n\n4\n /~\\ ====\n |oo ) ([__])"\n _\\=/_ | \\-/||\n / _ \\ ||\\ /||\n //|/.\\|\\\\ \\/ | \\/\n // \\_/ || | | |\n // |\\ /| || | | |\n # \\_ _/ # |====|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n10\n /~\\ ====\n ( oo| ([__])"\n _\\=/_ | \\-/||\n / _ \\ ||\\ /||\n //|/.\\|\\\\ \\/ | \\/\n // \\_/ || | | |\n // |\\ /| || | | |\n # \\_ _/ # |====|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n6\n /~\\ ====\n ( oo| ([__])"\n _\\=/_ | \\-/||\n / _ \\ ||\\ /||\n //|/.\\|\\\\ \\/ | \\/\n || \\_/ || | | |\n || |\\ /| || | | |\n # \\_ _/ # |====|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n4\n\n\n\n\n\n\n\n\n\n\n\n\n\n1\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ __/\n --- __>_______________. <__\n -- / \\___________________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.000.0 \\______________/\n\n1\n _______________________________________\n / \\\n | |\n --| /|\n --| / |\n -- \\__ / __/\n --- __>__________. | <__\n -- / \\___________________|____\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.010.0 \\______________/\n\n1\n _______________________________________\n / \\\n | ____|\n --| / |\n --| / |\n -- \\__ / __/\n --- __>_____. | <__\n -- / \\___________________|_________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.020.0 \\______________/\n\n1\n _______________________________________\n / \\\n | _________|\n --| / |\n --| / |\n -- \\__ / __/\n --- __>. | <__\n -- / \\___________________|______________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.040.0 \\______________/\n\n1\n _______________________________________\n / \\\n | __________ |\n --| / \\ |\n --| / \\|\n -- \\__ / __/\n --- __> | <__\n -- /___________________|___________________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.050.0 \\______________/\n\n1\n _______________________________________\n / \\\n | __________ |\n --| / \\ |\n --| / \\ |\n -- \\__ / \\__/\n --- __> | <__\n -- /______________|______________________|_\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.060.0 \\______________/\n\n1\n _______________________________________\n / \\\n | __________ |\n --| / \\ |\n --| / \\ |\n -- \\__ / \\ __/\n --- __> | | <__\n -- /_________|______________________|______\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.070.0 \\______________/\n\n1\n _______________________________________\n / \\\n | __________ |\n --| / \\ |\n --| / \\ |\n -- \\__ / \\ __/\n --- __> | | <__\n -- /____|______________________|___________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.080.0 \\______________/\n\n1\n _______________________________________\n / \\\n | __________ |\n --| / \\ |\n --| / \\ |\n -- \\/_ \\ __/\n --- __> | <__\n -- /______________________|________________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.090.1 \\______________/\n\n1\n _______________________________________\n / \\\n | ___________ |\n --| \\ |\n --| \\ |\n -- \\__ \\ __/\n --- __> | <__\n -- /_________________|_____________________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.100.1 \\______________/\n\n1\n _______________________________________\n / \\\n |_______ |\n --| \\ |\n --| \\ |\n -- \\__ \\ __/\n --- __> | <__\n -- /____________|__________________________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.110.1 \\______________/\n\n1\n _______________________________________\n / \\\n |__ |\n --| \\ |\n --| \\ |\n -- \\__ \\ __/\n --- __> | <__\n -- /_______|_______________________________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.120.1 \\______________/\n\n1\n _______________________________________\n / \\\n | |\n --| |\n --|\\ |\n -- \\_\\ __/\n --- __> <__\n -- /__|____________________________________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.130.1 \\______________/\n\n1\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ __/\n --- __> <__\n -- /_______________________________________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.140.1 \\______________/\n\n1\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ __/\n --- __> <__\n -- /_______________________________________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.150.1 \\______________/\n\n1\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ __/\n --- __> <__\n -- /_______________________________________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.160.1 \\______________/\n\n1\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ __/\n --- __> <__\n -- /_______________________________________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.170.1 \\______________/\n\n1\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ __/\n --- __> <__\n -- /_______________________________________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.180.1 \\______________/\n\n1\n _______________________________________\n / " \\\n | |" |\n --| |"| |\n --| ]|"|[ |\n -- \\__ ]|"_[/\n --- __> ]|<__\n -- /__________________________________]|"|[\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.190.2 \\______________/\n\n1\n _______________________________________\n / " \\\n | |" |\n --| |"| |\n --| ]|"|[ |\n -- \\__ ]|"|[ __/\n --- __> ]|"|[ <__\n -- /_____________________________]|"|[_____\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.200.2 \\______________/\n\n1\n _______________________________________\n / " \\\n | |" |\n --| |"| |\n --| ]|"|[ |\n -- \\__ ]|"|[ __/\n --- __> ]|"|[ <__\n -- /________________________]|"|[__________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.210.2 \\______________/\n\n1\n _______________________________________\n / " \\\n | |" |\n --| |"| |\n --| ]|"|[ |\n -- \\__ ]|"|[ __/\n --- __> ]|"|[ <__\n -- /___________________]|"|[_______________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.220.2 \\______________/\n\n1\n _______________________________________\n / " \\\n | |" |\n --| |"| |\n --| ]|"|[ |\n -- \\__ ]|"|[ __/\n --- __> ]|"|[ <__\n -- /______________]|"|[____________________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.230.2 \\______________/\n\n1\n _______________________________________\n / " \\\n | |" |\n --| |"| |\n --| ]|"|[ |\n -- \\__ ]|"|[ __/\n --- __> ]|"|[ <__\n -- /_________]|"|[_________________________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.240.2 \\______________/\n\n1\n _______________________________________\n / " \\\n | |" |\n --| |"| |\n --| ]|"|[ |\n -- \\__ ]|"|[ __/\n --- __> ]|"|[ <__\n -- /____]|"|[______________________________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.250.2 \\______________/\n\n1\n _______________________________________\n / " \\\n | |" |\n --| |"| |\n --|]|"|[ |\n -- \\|_|[ __/\n --- __>[ <__\n -- /|"|[___________________________________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.260.2 \\______________/\n\n1\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ __/\n --- __> <__\n -- /_______________________________________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.270.2 \\______________/\n\n1\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ __/\n --- __> ,<__\n -- /__________________________________/ \\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.280.2 \\______________/\n\n1\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ __/\n --- __> ,_____<__\n -- /_____________________________/ \\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.290.3 \\______________/\n\n1\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ __/\n --- __> ,__________<__\n -- /________________________/ \\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.300.3 \\______________/\n\n1\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ __/\n --- __> ,_______________<__\n -- /___________________/ \\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.310.3 \\______________/\n\n1\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ __/\n --- __> ,____________________<__\n -- /______________/ \\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.320.3 \\______________/\n\n1\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ __/\n --- __> ,______________________. <__\n -- /_________/ \\____\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.330.3 \\______________/\n\n1\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ __/\n --- __> .______________________. <__\n -- /____/ \\_________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.340.3 \\______________/\n\n1\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ __/\n --- __>____________________. <__\n -- / \\______________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.350.0 \\______________/\n\n1\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ __/\n --- __>_______________. <__\n -- / \\___________________\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.000.0 \\______________/\n\n4\n\n\n\n\n\n\n\n\n\n\n\n\n\n4\n /~\\ ====\n |oo ) o o~~\n _\\=/_ _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n // \\_/ || || | | |//\n // |\\ /| || ||__ | //\n # \\_ _/ # ([__]==(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n8\n /~\\ ====\n |oo ) Pardon me sir... o o~~\n _\\=/_ _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n // \\_/ || || | | |//\n // |\\ /| || ||__ | //\n # \\_ _/ # ([__]==(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n13\n /~\\ ====\n ( oo| Pardon me sir... o o~~\n _\\=/_ _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n // \\_/ || || | | |//\n // |\\ /| || ||__ | //\n # \\_ _/ # ([__]==(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n10\n /~\\ ====\n ( oo| Pardon me sir... o o~~\n _\\=/_ _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n // \\_/ || || | | |//\n // |\\ /| || ||__ | //\n # \\_ _/ # ([__]==(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n8\n /~\\ ====\n ( oo| ...but couldn\'t we o o~~\n _\\=/_ go after him? _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n // \\_/ || || | | |//\n // |\\ /| || ||__ | //\n # \\_ _/ # ([__]==(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n20\n /~\\ ====\n ( oo| ...but couldn\'t we o o~~\n _\\=/_ go after him? _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | |//\n || |\\ /| || ||__ | //\n # \\_ _/ # ([__]==(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n5\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | |//\n || |\\ /| || ||__ | //\n # \\_ _/ # ([__]==(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n9\n /~\\ ====\n ( oo| It\'s too dangerous o o~~\n _\\=/_ with all the _\\- /_\n / _ \\ Sand People around. / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | |//\n || |\\ /| || ||__ | //\n # \\_ _/ # ([__]==(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n11\n /~\\ ====\n ( oo| It\'s too dangerous ~~o o\n _\\=/_ with all the _\\ -/_\n / _ \\ Sand People around. / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | |//\n || |\\ /| || ||__ | //\n # \\_ _/ # ([__]==(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n6\n /~\\ ====\n ( oo| It\'s too dangerous o o~~\n _\\=/_ with all the _\\- /_\n / _ \\ Sand People around. / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | |//\n || |\\ /| || ||__ | //\n # \\_ _/ # ([__]==(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n8\n /~\\ ====\n ( oo| It\'s too dangerous o o~~\n _\\=/_ with all the _\\- /_\n / _ \\ Sand People around. / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | |//\n || |\\ /| || ||__ | //\n # \\_ _/ # ([__]==(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n5\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | |//\n || |\\ /| || ||__ | //\n # \\_ _/ # ([__]==(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n15\n /~\\ ====\n ( oo| We\'ll have to o o~~\n _\\=/_ wait until morning. _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | |//\n || |\\ /| || ||__ | //\n # \\_ _/ # ([__]==(|\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n11\n /~\\ ====\n ( oo| We\'ll have to o o~~\n _\\=/_ wait until morning. _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | | ||\n || |\\ /| || ||__ | | ||\n # \\_ _/ # ([__]===| \')\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n7\n /~\\ ====\n ( oo| We\'ll have to o o~~\n _\\=/_ wait until morning. _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | | ||\n || |\\ /| || ||__ | | ||\n # \\_ _/ # ([__]===| \')\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n6\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | | ||\n || |\\ /| || ||__ | | ||\n # \\_ _/ # ([__]===| \')\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n____________/_]_[_\\____________________________/__][__\\____________\n9\n\n\n\n\n\n\n\n\n\n\n\n\n\n2\n\n\n\n\n\n __________ ___\n / \\ ______________ /\n/ \\________/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n\n\n\n\n __________ ____\n/ \\ ______________ /\n \\________/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n\n\n\n\n__________ _____\n \\ ______________ /\n \\________/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n1\n\n\n\n\n\n_________ ______\n \\ ______________ /\n \\________/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n1\n\n Look, there\'s a droid\n on the scanner.\n\n\n_________ ______\n \\ ______________ /\n \\________/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Look, there\'s a droid\n on the scanner.\n\n\n________ _______\n \\ ______________ /\n \\________/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Look, there\'s a droid\n on the scanner.\n\n\n_______ ________\n \\ ______________ /\n \\________/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Look, there\'s a droid\n on the scanner.\n\n\n_____ __________\n \\ ______________ /\n \\________/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Look, there\'s a droid\n on the scanner.\n\n\n____ ___________\n \\ ______________ /\n \\________/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Look, there\'s a droid\n on the scanner.\n\n\n___ ____________\n \\ ______________ /\n \\________/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Look, there\'s a droid\n on the scanner.\n\n\n__ _____________\n \\ ______________ /\n \\________/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Look, there\'s a droid\n on the scanner.\n\n\n_ ______________\n \\ ______________ /\n \\________/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Look, there\'s a droid\n on the scanner.\n\n\n _______________\n\\ ______________ /\n \\________/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Look, there\'s a droid\n on the scanner.\n\n\n ________________\n ______________ /\n\\________/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Look, there\'s a droid\n on the scanner.\n\n\n _________________\n ______________ /\n________/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Look, there\'s a droid\n on the scanner.\n\n\n _________________\n ______________ /\n_______/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Look, there\'s a droid\n on the scanner.\n\n\n ___________________\n ______________ /\n______/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n\n\n\n\n ____________________\n ______________ /\n_____/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Hit the accelerator!\n\n\n\n _____________________\n ______________ /\n____/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Hit the accelerator!\n\n\n\n ______________________\n ______________ /\n___/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Hit the accelerator!\n\n\n\n _______________________\n ______________ /\n__/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Hit the accelerator!\n\n\n\n _______________________\n ______________ / \\\n_/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Hit the accelerator!\n\n\n\n _______________________\n ______________ / \\_\n/ \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Hit the accelerator!\n\n\n\n _______________________\n______________ / \\__\n \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Hit the accelerator!\n\n\n\n _______________________\n_____________ / \\___\n \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Hit the accelerator!\n\n\n\n _______________________\n____________ / \\____\n \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Hit the accelerator!\n\n\n\n _______________________\n___________ / \\_____\n \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n Hit the accelerator!\n\n\n\n _______________________\n__________ / \\______\n \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n\n\n\n\n _______________________\n_________ / \\_______\n \\ /\n \\______________________/\n =_+_\n_________====\'_____________________________________________________\n\n\n2\n\n\n\n\n\n _______________________\n________ / \\________\n \\ /\n \\______________________/\n =_+_\n__________====\'____________________________________________________\n\n\n2\n\n\n\n\n\n _______________________\n_______ / \\_________\n \\ /\n \\______________________/\n =_+_\n___________====\'___________________________________________________\n\n\n2\n\n\n\n\n\n _______________________\n______ / \\__________\n \\ /\n \\______________________/\n =_+_\n____________====\'__________________________________________________\n\n\n2\n\n\n\n\n\n _______________________\n_____ / \\___________\n \\ /\n \\______________________/\n =_+_\n_____________====\'_________________________________________________\n\n\n2\n\n\n\n\n\n _______________________\n____ / \\____________\n \\ /\n \\______________________/\n =_+_\n______________====\'________________________________________________\n\n\n2\n\n\n\n\n\n _______________________\n___ / \\_____________\n \\ /\n \\______________________/\n =_+_\n_______________====\'_______________________________________________\n\n\n2\n\n\n\n\n\n _______________________\n__ / \\______________\n \\ /\n \\______________________/\n =_+_\n________________====\'______________________________________________\n\n\n2\n\n\n\n\n\n _______________________\n_ / \\_______________\n \\ /\n \\______________________/\n =_+_\n_________________====\'_____________________________________________\n\n\n2\n\n\n\n\n\n _______________________\n / \\________________\n\\ /\n \\______________________/\n =_+_\n__________________====\'____________________________________________\n\n\n2\n\n\n\n\n\n _______________________\n / \\_________________\n /\n\\______________________/\n =_+_\n___________________====\'___________________________________________\n\n\n2\n\n\n\n\n\n _______________________\n / \\__________________\n /\n______________________/\n =_+_\n_____________________====\'_________________________________________\n\n\n2\n\n\n\n\n\n _______________________\n / \\___________________\n /\n_____________________/\n =_+_\n_______________________====\'_______________________________________\n\n\n2\n\n\n\n\n\n _______________________\n / \\___________________\n /\n____________________/\n =_+_\n_________________________====\'_____________________________________\n\n\n2\n\n\n\n\n\n _______________________\n / \\_____________________\n /\n___________________/\n =_+_\n___________________________====\'___________________________________\n\n\n2\n\n\n\n\n\n _______________________\n / \\______________________\n /\n__________________/\n =_+_\n_____________________________====\'_________________________________\n\n\n1\n\n\n\n\n\n _______________________\n / \\_______________________\n /\n_________________/\n =_+_\n_______________________________====\'_______________________________\n\n\n2\n\n\n\n\n\n _______________________\n / \\________________________\n /\n________________/\n =_+_\n_________________________________====\'_____________________________\n\n\n2\n\n\n\n\n\n _______________________\n / \\_________________________\n /\n_______________/\n =_+_\n___________________________________====\'___________________________\n\n\n2\n\n\n\n\n\n _______________________\n / \\__________________________\n /\n______________/\n =_+_\n_____________________________________====\'_________________________\n\n\n4\n\n\n\n\n\n\n\n\n\n\n\n\n\n7\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ // | | |//\n || |\\ /| || | | === | | // | | //\n # \\_ _/ # |_| O |_|(\' |===(|\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n10\n /~\\ Where do you think ====\n ( oo| you\'re going? o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ // | | |//\n || |\\ /| || | | === | | // | | //\n # \\_ _/ # |_| O |_|(\' |===(|\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n15\n /~\\ Where do you think ====\n ( oo| you\'re going? o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(|\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n6\n /~\\ Where do you think ====\n ( oo| you\'re going? o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n \\\\ \\_/ // _|_____|_ \\\\| | |//\n \\\\\\ /// | | === | | \\\\ | //\n #_ _# |_| O |_| )===(|\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n5\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(|\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n7\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ /() \\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(|\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n5\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(|\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n5\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ /() \\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(|\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n10\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(|\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n16\n /~\\ What\'s wrong with ====\n ( oo| him now? o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(|\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n17\n /~\\ What\'s wrong with ====\n ( oo| him now? o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ (, / \\ / \\ ,)\n //|/.\\|\\\\ / ()\\ \\\\//| | |\\\\//\n || \\_/ || _|_____|_ \\/ | | | \\/\n || |\\ /| || | | === | | | | |\n # \\_ _/ # |_| O |_| |====|\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n1\n /~\\ What\'s wrong with ====\n ( oo| him now? o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ || | | | ||\n || |\\ /| || | | === | | || | | | ||\n # \\_ _/ # |_| O |_| (\' |====| \')\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n6\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ || | | | ||\n || |\\ /| || | | === | | || | | | ||\n # \\_ _/ # |_| O |_| (\' |====| \')\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n21\n /~\\ There are several ====\n ( oo| creatures... o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ || | | | ||\n || |\\ /| || | | === | | || | | | ||\n # \\_ _/ # |_| O |_| (\' |====| \')\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n10\n /~\\ ...approaching from ====\n ( oo| the southeast. o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ /() \\ //| | |\\\\\n || \\_/ || _|_____|_ || | | | ||\n || |\\ /| || | | === | | || | | | ||\n # \\_ _/ # |_| O |_| (\' |====| \')\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n10\n /~\\ ...approaching from ====\n ( oo| the southeast. o o~~\n _\\=/_ _\\o /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ /() \\ //| | |\\\\\n || \\_/ || _|_____|_ || | | | ||\n || |\\ /| || | | === | | || | | | ||\n # \\_ _/ # |_| O |_| (\' |====| \')\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n6\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ || | | | ||\n || |\\ /| || | | === | | || | | | ||\n # \\_ _/ # |_| O |_| (\' |====| \')\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n20\n /~\\ ====\n ( oo| Sand People! o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ || | | | ||\n || |\\ /| || | | === | | || | | | ||\n # \\_ _/ # |_| O |_| (\' |====| \')\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n12\n /~\\ ====\n ( oo| Or worse! o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ || | | | ||\n || |\\ /| || | | === | | || | | | ||\n # \\_ _/ # |_| O |_| (\' |====| \')\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n14\n /~\\ ====\n |oo ) Or worse! o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ || | | | ||\n || |\\ /| || | | === | | || | | | ||\n # \\_ _/ # |_| O |_| (\' |====| \')\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n6\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ || | | | ||\n || |\\ /| || | | === | | || | | | ||\n # \\_ _/ # |_| O |_| (\' |====| \')\n | | | || O || | || |\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____________[_]_[_]_[_]____/__][__\\____________\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n10\n\n /\n |\n /\n\\ /~\\ ==== /\n \\ |oo ) ([__])" ______/\n \\ _\\=/_ | \\-/ | /\n | _______ / _ \\ ||\\ /|| /\n \\____/ \\___//|/.\\|\\\\_______\\/_|_\\/_________/\n\n\n\n\n15\n\n Well there are two /\n Banthas down there... |\n /\n\\ /~\\ ==== /\n \\ |oo ) ([__])" ______/\n \\ _\\=/_ | \\-/ | /\n | _______ / _ \\ ||\\ /|| /\n \\____/ \\___//|/.\\|\\\\_______\\/_|_\\/_________/\n\n\n\n\n14\n\n Well there are two /\n Banthas down there... |\n /\n\\ /~\\ ==== /\n \\ ( oo| ([__])" ______/\n \\ _\\=/_ | \\-/ | /\n | _______ / _ \\ ||\\ /|| /\n \\____/ \\___//|/.\\|\\\\_______\\/_|_\\/_________/\n\n\n\n\n20\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ /~~~~\\ ,, ,, /~~~~\\ __/\n --- __> {~~~~~~|{} {}|~~~~~~} <__\n -- /_________||~~||___________||~~||_______\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.120.1 \\______________/\n\n16\n\n ...but I don\'t see /\n any... wait a second! |\n /\n\\ /~\\ ==== /\n \\ ( oo| ([__])" ______/\n \\ _\\=/_ | \\-/ | /\n | _______ / _ \\ ||\\ /|| /\n \\____/ \\___//|/.\\|\\\\_______\\/_|_\\/_________/\n\n\n\n\n11\n\n ...but I don\'t see /\n any... wait a second! |\n /\n\\ /~\\ ==== /\n \\ |oo ) ([__])" ______/\n \\ _\\=/_ | \\-/ | /\n | _______ / _ \\ ||\\ /|| /\n \\____/ \\___//|/.\\|\\\\_______\\/_|_\\/_________/\n\n\n\n\n6\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ /~~~~\\ ,, ,, /~~~~\\ __/\n --- __> {~~~~~~|{} {}|~~~~~~} <__\n -- /_________||~~||___________||~~||_______\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.120.1 \\______________/\n\n6\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ /~~~~\\ ,, ,, /~~~~\\ __/\n --- __> {~~~~~~|{}+ {}|~~~~~~} <__\n -- /_________||~~||___|_______||~~||_______\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.120.1 \\______________/\n\n15\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ /~~~~\\ ,, ,, /~~~~\\ __/\n --- __> {~~~~~~|{} + {}|~~~~~~} <__\n -- /_________||~~||____|______||~~||_______\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.120.1 \\______________/\n\n21\n\n They\'re Sand People /\n all right! |\n /\n\\ /~\\ ==== /\n \\ |oo ) ([__])" ______/\n \\ _\\=/_ | \\-/ | /\n | _______ / _ \\ ||\\ /|| /\n \\____/ \\___//|/.\\|\\\\_______\\/_|_\\/_________/\n\n\n\n\n20\n\n I can see one of /\n of them now! |\n /\n\\ /~\\ ==== /\n \\ |oo ) ([__])" ______/\n \\ _\\=/_ | \\-/ | /\n | _______ / _ \\ ||\\ /|| /\n \\____/ \\___//|/.\\|\\\\_______\\/_|_\\/_________/\n\n\n\n\n1\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ /~~~~\\ ,, ,, /~~~~\\ __/\n --- __> {~~~~~~|{} + {}|~~~~~~} <__\n -- /_________||~~||____|______||~~||_______\\\n --| |\n --| |\n | .-------. |\n \\ _____________/ 0.120.1 \\______________/\n\n1\n _______________________________________\n / \\\n | |\n --| |\n --| |\n -- \\__ /~~~~\\ ,, ,, /~~~~\\ __/\n --- __> {~~~~~~|{} + {}|~~~~~~} <__\n -- /_________||~~||____|______||~~||_______\\\n --| ############################ |\n --| ############################## |\n | ###########.-------.############ |\n \\ _____________/ 0.120.1 \\______________/\n\n1\n _______________________________________\n / \\\n | |\n --| |\n --| ############################ |\n -- \\__ ############################## __/\n --- __> ################################<__\n -- /___##################################__\\\n --| #################################### |\n --| ###################################### |\n | ###############.-------.################|\n \\ _____________/ 0.120.1 \\______________/\n\n1\n _______________________________________\n / ############################## \\\n | ################################ |\n --| ################################## |\n --| #################################### |\n -- \\_######################################/\n --- __>#################################<__\n -- /#######################################\\\n --|#########################################|\n --|#########################################|\n |################.-------.################|\n \\ _____________/ 0.120.1 \\______________/\n\n1\n _______________________________________\n / ######################################\\\n | ########################################|\n --|#########################################|\n --|#########################################|\n -- \\#######################################/\n --- __>#################################<__\n -- /#######################################\\\n --|#########################################|\n --|#########################################|\n |################.-------.################|\n \\ _____________/ 0.120.1 \\______________/\n\n1\n _______________________________________\n /#######################################\\\n |#########################################|\n --|#########################################|\n --|#########################################|\n -- \\#######################################/\n --- __>#################################<__\n -- /#######################################\\\n --|#########################################|\n --|#########################################|\n |################.-------.################|\n \\ _____________/ 0.120.1 \\______________/\n\n1\n\n I can see one of /\n of them now! |\n /\n\\ /~\\ ==== /\n \\ |oo ) ([__])" ______/\n \\ _\\=/_ | \\-/ | /\n | _______ / _ \\ ||\\ /|| /\n \\____/ \\___//|/.\\|\\\\_______\\/_|_\\/_________/\n\n\n\n /~~\\ ,\n1\n\n I can see one of /\n of them now! |\n /\n\\ /~\\ ==== /\n \\ |oo ) ([__])" ______/\n \\ _\\=/_ | \\-/ | /\n | _______ / _ \\ ||\\ /|| /\n \\____/ \\___//|/.\\|\\\\_______\\/_|_\\/_________/\n\n /~~\\ ,\n ( o o| /(*)\n \\\'#\'_// `\n1\n\n /\n |\n /\n\\ /~\\ ==== /\n \\ |oo ) ([__])" ______/\n \\ _\\=/_ | \\-/ | /\n | _______ / _ \\ ||\\ /|| /\n \\____/~~\\ \\___//|/.\\|\\\\_______\\/_|_\\/_________/\n ( o o| /(*)\n _ \'#\'_// `\n /\\-<=>//\n / / // \\\n1\n\n /\n |\n /\n\\ /~\\ ==== /\n \\ /~~\\ , |oo ) ([__])" ______/\n \\ ( o o| /(*) _\\=/_ | \\-/ | /\n | _\\\'#\'_//_` / _ \\ ||\\ /|| /\n \\__/\\-<=>// \\___//|/.\\|\\\\_______\\/_|_\\/_________/\n / / // \\\n \\ \\ //|\\ \\\n \\(//|| \\()\n |//==|\n1\n\n /\n /~~\\ , |\n ( o o| /(*) /\n\\ _\\\'#\'_// ` /~\\ ==== /\n \\ /\\-<=>// |oo ) o o~~ ______/\n \\ / / // \\ _\\=/_ _\\o /_ /\n | \\ \\ //|\\ \\ / _ \\ / \\ / \\ /\n \\___\\(//|| \\()__//|/.\\|\\\\______//|_|_|_\\\\_______/\n |//==|\n // ||\n // / |\n // / |\n2\n /~~\\ ,\n ( o o| /(*) /\n _\\\'#\'_// ` |\n /\\-<=>// /\n\\ / / // \\ /~\\ ==== /\n \\ \\ \\ //|\\ \\ |oo ) o o~~ ______/\n \\ \\(//|| \\() _\\=/_ _\\o /_ /\n | |//==|___ / _ \\ / \\ / \\ /\n \\___// || \\___//|/.\\|\\\\______//|_|_|_\\\\_______/\n // / |\n // / |\n ^/ |\n /________\\\n2\n /~~\\ ,\n ( o o| /(*) /\n _\\\'#\'_ // ` |\n /\\-<=> // /\n\\ | | //\\ /~\\ ==== /\n \\ \\ \\ //\\ \\ |oo ) o o~~ ______/\n \\ \\_(//| \\() _\\=/_ _\\o /_ /\n | | //=|___ / _ \\ / \\ / \\ /\n \\___|// || \\___//|/.\\|\\\\______//|_|_|_\\\\_______/\n // / |\n /// |\n .^ |\n /________\\\n8\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n /~~\\ ,\n ( o o| /(*)\n _\\\'#\'_ || ` _______\n /\\-<=>\\ || / \\________________\n / / \\ \\ || /\n / / ||\\ \\ || / ==== /~\\\n /_/ | || \\(|) / x x~~ |-- )\n (\' |====| || | _\\- /_ _\\=/_\n | || || / / \\ / \\ / _ ()\n | / | || | //| | |\\\\ //|/.\\|\n |/ | || / || | | | || || \\_/\n / | `V / || |====| || || |\\-/|\n________________/________\\_______/____(`_[_][_]_(\'______#_[]_[]__()\n3\n /~~\\\n ( o o| ,\n _\\\'#\'_ /(*) _______\n /\\-<=>\\ || ` / \\________________\n / / \\ \\ || /\n / / ||\\ \\ || / ==== /~\\\n /_/ | || \\(|) / x x~~ |-- )\n (\' |====| || | _\\- /_ _\\=/_\n | || || / / \\ / \\ / _ ()\n | / | || | //| | |\\\\ //|/.\\|\n |/ | || / || | | | || || \\_/\n / | || / || |====| || || |\\-/|\n________________/________\\___`V__/____(`_[_][_]_(\'______#_[]_[]__()\n3\n /~~\\ ,\n ( o o| /(*)\n _\\\'#\'_ || ` _______\n /\\-<=>\\ || / \\________________\n / / \\ \\ || /\n / / ||\\ \\ || / ==== /~\\\n /_/ | || \\(|) / x x~~ |-- )\n (\' |====| || | _\\- /_ _\\=/_\n | || || / / \\ / \\ / _ ()\n | / | || | //| | |\\\\ //|/.\\|\n |/ | || / || | | | || || \\_/\n / | `V / || |====| || || |\\-/|\n________________/________\\_______/____(`_[_][_]_(\'______#_[]_[]__()\n3\n /~~\\\n ( o o| ,\n _\\\'#\'_ /(*) _______\n /\\-<=>\\ || ` / \\________________\n / / \\ \\ || /\n / / ||\\ \\ || / ==== /~\\\n /_/ | || \\(|) / x x~~ |-- )\n (\' |====| || | _\\- /_ _\\=/_\n | || || / / \\ / \\ / _ ()\n | / | || | //| | |\\\\ //|/.\\|\n |/ | || / || | | | || || \\_/\n / | || / || |====| || || |\\-/|\n________________/________\\___`V__/____(`_[_][_]_(\'______#_[]_[]__()\n3\n /~~\\ ,\n ( o o| /(*)\n _\\\'#\'_ || ` _______\n /\\-<=>\\ || / \\________________\n / / \\ \\ || /\n / / ||\\ \\ || / ==== /~\\\n /_/ | || \\(|) / x x~~ |-- )\n (\' |====| || | _\\- /_ _\\=/_\n | || || / / \\ / \\ / _ ()\n | / | || | //| | |\\\\ //|/.\\|\n |/ | || / || | | | || || \\_/\n / | `V / || |====| || || |\\-/|\n________________/________\\_______/____(`_[_][_]_(\'______#_[]_[]__()\n3\n /~~\\\n ( o o| ,\n _\\\'#\'_ /(*) _______\n /\\-<=>\\ || ` / \\________________\n / / \\ \\ || /\n / / ||\\ \\ || / ==== /~\\\n /_/ | || \\(|) / x x~~ |-- )\n (\' |====| || | _\\- /_ _\\=/_\n | || || / / \\ / \\ / _ ()\n | / | || | //| | |\\\\ //|/.\\|\n |/ | || / || | | | || || \\_/\n / | || / || |====| || || |\\-/|\n________________/________\\___`V__/____(`_[_][_]_(\'______#_[]_[]__()\n3\n /~~\\ ,\n ( o o| /(*)\n _\\\'#\'_ || ` _______\n /\\-<=>\\ || / \\________________\n / / \\ \\ || /\n / / ||\\ \\ || / ==== /~\\\n /_/ | || \\(|) / x x~~ |-- )\n (\' |====| || | _\\- /_ _\\=/_\n | || || / / \\ / \\ / _ ()\n | / | || | //| | |\\\\ //|/.\\|\n |/ | || / || | | | || || \\_/\n / | `V / || |====| || || |\\-/|\n________________/________\\_______/____(`_[_][_]_(\'______#_[]_[]__()\n7\n /~~\\\n ( o o| ,\n _\\\'#\'_ /(*) _______\n /\\-<=>\\ || ` / \\________________\n / / \\ \\ || /\n / / ||\\ \\ || / ==== /~\\\n /_/ | || \\(|) / x x~~ |-- )\n (\' |====| || | _\\- /_ _\\=/_\n | || || / / \\ / \\ / _ ()\n | / | || | //| | |\\\\ //|/.\\|\n |/ | || / || | | | || || \\_/\n / | || / || |====| || || |\\-/|\n________________/________\\___`V__/____(`_[_][_]_(\'______#_[]_[]__()\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ + + =_._ _______________/\n_____________|_____|______|_|_====\'_--+__/\n\n\n4\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ + +=_._ _______________/\n_____________|_____|______|__|====\'_--+__/\n\n\n4\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ + +=_._ _______________/\n_____________|_____|______|_~|====\'_--+__/\n\n\n4\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ + ~+=_._ _______________/\n_____________|_____|______|__|====\'_--+__/\n\n\n6\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ + +=_._ _______________/\n_____________|_____|______|_~|====\'_--+__/\n\n\n8\n\n ARGHHHHOOOOOOO!!!\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ + +=_._ _______________/\n_____________|_____|______|_~|====\'_--+__/\n\n\n1\n\n ARGHHHHOOOOOOO!!!\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ + +=_._ _______________/\n_____________|_____|______|__|====\'_--+__/\n ~\n\n4\n\n ARGHHHHOOOOOOO!!!\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ + + =_._ _______________/\n_____________|_____|______|_|_====\'_--+__/\n ~\n\n1\n\n ARGHHHHOOOOOOO!!!\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/ +\n ___ ________|\n / \\ + + =_._ _______________/\n_____________|_____|______|_|_====\'_--+__/\n ~\n\n1\n\n ARGHHHHOOOOOOO!!!\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/ +\n ___ _______|_\n / \\ + + =_._ _______________/\n_____________|_____|______|_|_====\'_--+__/\n ~\n\n1\n\n ARGHHHHOOOOOOO!!!\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/ +\n ___ ______|__\n / \\ + + =_._ _______________/\n_____________|_____|______|_|_====\'_--+__/\n ~\n\n1\n\n ARGHHHHOOOOOOO!!!\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/ +\n ___ _____|___\n / \\ + + =_._ _______________/\n_____________|_____|______|_|_====\'_--+__/\n ~\n\n1\n\n ARGHHHHOOOOOOO!!!\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/ +\n ___ ____|____\n / \\ + + =_._ _______________/\n_____________|_____|______|_|_====\'_--+__/\n ~\n\n1\n\n ARGHHHHOOOOOOO!!!\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/ +\n ___ ___|_____\n / \\ + + =_._ _______________/\n_____________|_____|______|_|_====\'_--+__/\n ~\n\n1\n\n ARGHHHHOOOOOOO!!!\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/ +\n ___ __|______\n / \\ + + =_._ _______________/\n_____________|_____|_____|_|__====\'_--+__/\n ~\n\n1\n\n ARGHHHHOOOOOOO!!!\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/ +\n ___ _|_______\n / \\ + + =_._ _______________/\n_____________|_____|____|_|___====\'_--+__/\n ~\n\n1\n\n ARGHHHHOOOOOOO!!!\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/ +\n ___ |________\n / \\ + + =_._ _______________/\n_____________|_____|___|_|____====\'_--+__/\n ~\n\n1\n\n ARGHHHHOOOOOOO!!!\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/ +\n ___ |________\n / \\ + + =_._ _______________/\n_____________|_____|__|_|_____====\'_--+__/\n ~\n\n1\n\n ARGHHHHOOOOOOO!!!\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/ +\n ___ |________\n / \\ + + =_._ _______________/\n_____________|_____|_|_|______====\'_--+__/\n ~\n\n1\n\n ARGHHHHOOOOOOO!!!\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/ +\n ___ |________\n / \\ + + =_._ _______________/\n_____________|_____||_|_______====\'_--+__/\n ~\n\n1\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/ +\n ___ |________\n / \\+ + =_._ _______________/\n_____________|_____|_|________====\'_--+__/\n ~\n\n1\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/ +\n ___ |________\n / + + =_._ _______________/\n_____________|____|_|_________====\'_--+__/\n ~\n\n1\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/ +\n ___ |________\n / +\\+ =_._ _______________/\n_____________|___|_|__________====\'_--+__/\n ~\n\n1\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/ +\n ___ |________\n / + =_._ _______________/\n_____________|____||__________====\'_--+__/\n ~\n\n1\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/ +\n ___ |________\n / +\\ =_._ _______________/\n_____________|___|_|__________====\'_--+__/\n ~\n\n4\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/ +\n ___ |________\n / \\ =_._ _______________/\n_____________|_____|__________====\'_--+__/\n ~\n\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n10\n ==== / ,_____________/\n ("o o) / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ |\n / \\/ \\ / |\n| /| | |\\ | / ==== /\n|| | | | || / x x~~ /\n(\' | | | `) | _\\- /_ /\n | | | / / \\ / \\ |\n | /| | | //| | |\\\\ |\n / || \\ / || | | | || /\n /|_|| \\ | || |====| || |\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_______________________\n3\n ==== / ,_____________/\n ("o o) / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ |\n / \\/ \\ / |\n| /| | |\\ \\ / ==== /\n|| | | | \\ \\ / x x~~ /\n(\' | | | `() | _\\- /_ /\n | | | / / \\ / \\ |\n | /| | | //| | |\\\\ |\n / || \\ / || | | | || /\n /|_|| \\ | || |====| || |\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_______________________\n2\n ==== / ,_____________/\n ("o o) / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ |\n / \\/ \\ / | ()\n| /| | |\\ \\ / ==== /\n|| | | | \\ \\ / x x~~ /\n(\' | | | `() | _\\- /_ /\n | | | / / \\ / \\ |\n | /| | | //| | |\\\\ |\n / || \\ / || | | | || /\n /|_|| \\ | || |====| || |\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_______________________\n21\n ==== / ,_____________/\n ("- -) / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ |\n / \\/ \\ / | ()\n| /| | |\\ \\ / ==== /\n|| | | | \\ \\ / x x~~ /\n(\' | | | `() | _\\- /_ /\n | | | / / \\ / \\ |\n | /| | | //| | |\\\\ |\n / || \\ / || | | | || /\n /|_|| \\ | || |====| || |\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_______________________\n8\n ==== / ,_____________/\n ("- -) / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ |\n / \\/ \\ / | ()\n| /| | |\\ \\ / ==== /\n|| | | | \\ \\ / - -~~ /\n(\' | | | `() | _\\- /_ /\n | | | / / \\ / \\ |\n | /| | | //| | |\\\\ |\n / || \\ / || | | | || /\n /|_|| \\ | || |====| || |\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_______________________\n1\n ==== / ,_____________/\n ("o o) / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ |\n / \\/ \\ / | ()\n| /| | |\\ \\ / ==== /\n|| | | | \\ \\ / - -~~ /\n(\' | | | `() | _\\- /_ /\n | | | / / \\ / \\ |\n | /| | | //| | |\\\\ |\n / || \\ / || | | | || /\n /|_|| \\ | || |====| || |\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_______________________\n4\n ==== / ,_____________/\n ("o o) / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ |\n / \\/ \\ / | ()\n| /| | |\\ \\ / ==== /\n|| | | | \\ \\ / - -~~ /\n(\' | | | `() | _\\- /_ /\n | | | / / \\ / \\ |\n | /| | | //| | |\\\\ |\n / || \\ / || | | | || /\n /|_|| \\ | || |====| || |\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_______________________\n3\n ==== / ,_____________/\n ("o o) / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ |\n / \\/ \\ / | ()\n| /| | |\\ \\ / ==== /\n|| | | | \\ \\ / - -~~ /\n(\' | | | `() | _\\- /_ /\n | | | / / \\ / \\ |\n | /| | | //| | |\\\\ |\n / || \\ / || | | | || /\n /|_|| \\ | || |====| || |\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_______________________\n7\n ==== / ,_____________/\n ("o o) Hello there. / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ |\n / \\/ \\ / | ()\n| /| | |\\ \\ / ==== /\n|| | | | \\ \\ / - -~~ /\n(\' | | | `() | _\\- /_ /\n | | | / / \\ / \\ |\n | /| | | //| | |\\\\ |\n / || \\ / || | | | || /\n /|_|| \\ | || |====| || |\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_______________________\n1\n ==== / ,_____________/\n ("o o) Hello there. / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ |\n / \\/ \\ / | ()\n| /| | |\\ \\ / ==== /\n|| | | | \\ \\ / - -~~ /\n(\' | | | `() | _\\- /_ /\n | | | / / \\ / \\ |\n | /| | | //| | |\\\\ |\n / || \\ / || | | | || /\n /|_|| \\ | || |====| || |\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/______________________\n5\n ==== / ,_____________/\n ("o o) Hello there. / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ |\n / \\/ \\ / | ()\n| /| | |\\ \\ / ==== /\n|| | | | \\ \\ / - -~~ /\n(\' | | | `() | _\\- /_ /\n | | | / / \\ / \\ |\n | /| | | //| | |\\\\ |\n / || \\ / || | | | || /\n /|_|| \\ | || |====| || |\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_______________________\n7\n ==== / ,_____________/\n ("o o) Hello there. / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ |\n / \\/ \\ / | ()\n| /| | |\\ \\ / ==== /\n|| | | | \\ \\ / - -~~ /\n(\' | | | `() | _\\- /_ /\n | | | / / \\ / \\ |\n | /| | | //| | |\\\\ |\n / || \\ / || | | | || /\n /|_|| \\ | || |====| || |\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_______________________\n5\n ==== / ,_____________/\n ("o o) Hello there. / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ |\n / \\/ \\ / | ()\n| /| | |\\ \\ / ==== /\n|| | | | \\ \\ / - -~~ /\n(\' | | | `() | _\\- /_ /\n | | | / / \\ / \\ |\n | /| | | //| | |\\\\ |\n / || \\ / || | | | || /\n /|_|| \\ | || |====| || |\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_______________________\n21\n ==== / ,_____________/\n ("o o) Oh, don\'t worry... / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ |\n / \\/ \\ / | ()\n| /| | |\\ \\ / ==== /\n|| | | | \\ \\ / - -~~ /\n(\' | | | `() | _\\- /_ /\n | | | / / \\ / \\ |\n | /| | | //| | |\\\\ |\n / || \\ / || | | | || /\n /|_|| \\ | || |====| || |\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_______________________\n15\n ==== / ,_____________/\n ("o o) ...he\'ll be alright. / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ |\n / \\/ \\ / | ()\n| /| | |\\ \\ / ==== /\n|| | | | \\ \\ / - -~~ /\n(\' | | | `() | _\\- /_ /\n | | | / / \\ / \\ |\n | /| | | //| | |\\\\ |\n / || \\ / || | | | || /\n /|_|| \\ | || |====| || |\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_______________________\n25\n ==== / ,_____________/\n ("o o) ...he\'ll be alright. / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ | ___\n / \\/ \\ / | /() \\\n| /| | |\\ \\ / ==== / _|_____|_\n|| | | | \\ \\ / - -~~ / | | === | |\n(\' | | | `() | _\\- /_ / |_| O |_|\n | | | / / \\ / \\ | || O ||\n | /| | | //| | |\\\\ | ||__*__||\n / || \\ / || | | | || / |~ \\___/ ~|\n /|_|| \\ | || |====| || | /=\\ /=\\ /=\\\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_________[_]_[_]_[_]___\n10\n ==== / ,_____________/\n ("o o) ...he\'ll be alright. / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ | ___\n / \\/ \\ / | /() \\\n| /| | |\\ \\ / ==== / _|_____|_\n|| | | | \\ \\ / o o~~ / | | === | |\n(\' | | | `() | _\\- /_ / |_| O |_|\n | | | / / \\ / \\ | || O ||\n | /| | | //| | |\\\\ | ||__*__||\n / || \\ / || | | | || / |~ \\___/ ~|\n /|_|| \\ | || |====| || | /=\\ /=\\ /=\\\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_________[_]_[_]_[_]___\n10\n ==== / ,_____________/\n ("o o) / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ | ___\n / \\/ \\ / | /() \\\n| /| | |\\ \\ / ==== / _|_____|_\n|| | | | \\ \\ / o o~~ / | | === | |\n(\' | | | `() | _\\- /_ / |_| O |_|\n | | | / / \\ / \\ | || O ||\n | /| | | //| | |\\\\ | ||__*__||\n / || \\ / || | | | || / |~ \\___/ ~|\n /|_|| \\ | || |====| || | /=\\ /=\\ /=\\\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_________[_]_[_]_[_]___\n16\n ==== / ,_____________/\n ("o o) Ben? / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ | ___\n / \\/ \\ / | /() \\\n| /| | |\\ \\ / ==== / _|_____|_\n|| | | | \\ \\ / o o~~ / | | === | |\n(\' | | | `() | _\\- /_ / |_| O |_|\n | | | / / \\ / \\ | || O ||\n | /| | | //| | |\\\\ | ||__*__||\n / || \\ / || | | | || / |~ \\___/ ~|\n /|_|| \\ | || |====| || | /=\\ /=\\ /=\\\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_________[_]_[_]_[_]___\n4\n ==== / ,_____________/\n ("o o) / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ | ___\n / \\/ \\ / | /() \\\n| /| | |\\ \\ / ==== / _|_____|_\n|| | | | \\ \\ / o o~~ / | | === | |\n(\' | | | `() | _\\- /_ / |_| O |_|\n | | | / / \\ / \\ | || O ||\n | /| | | //| | |\\\\ | ||__*__||\n / || \\ / || | | | || / |~ \\___/ ~|\n /|_|| \\ | || |====| || | /=\\ /=\\ /=\\\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_________[_]_[_]_[_]___\n20\n ==== / ,_____________/\n ("o o) Ben Kenobi? / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ | ___\n / \\/ \\ / | /() \\\n| /| | |\\ \\ / ==== / _|_____|_\n|| | | | \\ \\ / o o~~ / | | === | |\n(\' | | | `() | _\\- /_ / |_| O |_|\n | | | / / \\ / \\ | || O ||\n | /| | | //| | |\\\\ | ||__*__||\n / || \\ / || | | | || / |~ \\___/ ~|\n /|_|| \\ | || |====| || | /=\\ /=\\ /=\\\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_________[_]_[_]_[_]___\n3\n ==== / ,_____________/\n ("o o) / /\n _\\ -/_ _______ / |\n / \\ / \\ / \\______/ | ___\n / \\/ \\ / | /() \\\n| /| | |\\ \\ / ==== / _|_____|_\n|| | | | \\ \\ / o o~~ / | | === | |\n(\' | | | `() | _\\- /_ / |_| O |_|\n | | | / / \\ / \\ | || O ||\n | /| | | //| | |\\\\ | ||__*__||\n / || \\ / || | | | || / |~ \\___/ ~|\n /|_|| \\ | || |====| || | /=\\ /=\\ /=\\\n_/_[_]|____\\_|_____(`_[_][_]_(\'____________/_________[_]_[_]_[_]___\n6\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n32\n\n\n Tell me, young Luke,\n what brings you\n out this far?\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n5\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n20\n\n\n Oh, this little droid!\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n1\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n32\n\n\n He claims to be the property\n of an Obi-Wan Kenobi.\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n7\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n20\n\n\n Obi-Wan Kenobi.\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n6\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n16\n\n\n Obi-Wan?\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n7\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n31\n\n Now that\'s a name\n I\'ve not heard\n in a long time.\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n1\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n22\n\n A long time.\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n2\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n20\n\n\n You know him?\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n3\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n21\n\n\n Of course I know him.\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n21\n\n\n He\'s me!\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n2\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n7\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n ==== ==== / ,_____________/\n ("o o) o o~~ / /\n _\\ -/_ _ _\\- /_ / |\n / \\ / \\ / / \\ / \\_____/ | ___\n / \\/ \\ / //| | |\\\\ | /() \\\n| /| | |\\ | / \\\\| | |// / _|_____|_\n|| | | | || / \\\\ | // / | | === | |\n(\' | | | `) | )===(| / |_| O |_|\n | | | / | || | | || O ||\n | /| | | (_)(_) | ||__*__||\n / || \\ / |_||_| / |~ \\___/ ~|\n /|_|| \\ | |_||_| | /=\\ /=\\ /=\\\n_/_[_]|____\\_|_________/__][__\\____________/_________[_]_[_]_[_]___\n6\n ==== ==== / ,_____________/\n ("o o) o o~~ / /\n _\\ -/_ _ _\\- /_ / |\n / \\ / \\ / / \\ / \\_____/ | ___\n / \\/ \\ / //| | |\\\\ | / ()\\\n| /| | |\\ | / \\\\| | |// / _|_____|_\n|| | | | || / \\\\ | // / | | === | |\n(\' | | | `) | )===(| / |_| O |_|\n | | | / | || | | || O ||\n | /| | | (_)(_) | ||__*__||\n / || \\ / |_||_| / |~ \\___/ ~|\n /|_|| \\ | |_||_| | /=\\ /=\\ /=\\\n_/_[_]|____\\_|_________/__][__\\____________/_________[_]_[_]_[_]___\n6\n ==== ==== / ,_____________/\n ("o o) o o~~ / /\n _\\ -/_ _ _\\- /_ / |\n / \\ / \\ / / \\ / \\_____/ | ___\n / \\/ \\ / //| | |\\\\ | /() \\\n| /| | |\\ | / \\\\| | |// / _|_____|_\n|| | | | || / \\\\ | // / | | === | |\n(\' | | | `) | )===(| / |_| O |_|\n | | | / | || | | || O ||\n | /| | | (_)(_) | ||__*__||\n / || \\ / |_||_| / |~ \\___/ ~|\n /|_|| \\ | |_||_| | /=\\ /=\\ /=\\\n_/_[_]|____\\_|_________/__][__\\____________/_________[_]_[_]_[_]___\n6\n ==== ==== / ,_____________/\n ("o o) o o~~ / /\n _\\ -/_ _ _\\- /_ / |\n / \\ / \\ / / \\ / \\_____/ | ___\n / \\/ \\ / //| | |\\\\ | / ()\\\n| /| | |\\ | / \\\\| | |// / _|_____|_\n|| | | | || / \\\\ | // / | | === | |\n(\' | | | `) | )===(| / |_| O |_|\n | | | / | || | | || O ||\n | /| | | (_)(_) | ||__*__||\n / || \\ / |_||_| / |~ \\___/ ~|\n /|_|| \\ | |_||_| | /=\\ /=\\ /=\\\n_/_[_]|____\\_|_________/__][__\\____________/_________[_]_[_]_[_]___\n2\n ==== ==== / ,_____________/\n ("o o) o o~~ / /\n _\\ -/_ _ _\\- /_ / |\n / \\ / \\ / / \\ / \\_____/ | ___\n / \\/ \\ / //| | |\\\\ | /() \\\n| /| | |\\ | / \\\\| | |// / _|_____|_\n|| | | | || / \\\\ | // / | | === | |\n(\' | | | `) | )===(| / |_| O |_|\n | | | / | || | | || O ||\n | /| | | (_)(_) | ||__*__||\n / || \\ / |_||_| / |~ \\___/ ~|\n /|_|| \\ | |_||_| | /=\\ /=\\ /=\\\n_/_[_]|____\\_|_________/__][__\\____________/_________[_]_[_]_[_]___\n6\n ==== ==== / ,_____________/\n ("o o) o o~~ / /\n _\\ -/_ _ _\\- /_ / |\n / \\ / \\ / / \\ / \\_____/ | ___\n / \\/ \\ / //| | |\\\\ | / ()\\\n| /| | |\\ | / \\\\| | |// / _|_____|_\n|| | | | || / \\\\ | // / | | === | |\n(\' | | | `) | )===(| / |_| O |_|\n | | | / | || | | || O ||\n | /| | | (_)(_) | ||__*__||\n / || \\ / |_||_| / |~ \\___/ ~|\n /|_|| \\ | |_||_| | /=\\ /=\\ /=\\\n_/_[_]|____\\_|_________/__][__\\____________/_________[_]_[_]_[_]___\n1\n ==== ==== / ,_____________/\n ("o o) ~~o o / /\n _\\ -/_ _ _\\ -/_ / |\n / \\ / \\ / / \\ / \\_____/ | ___\n / \\/ \\ / //| | |\\\\ | / ()\\\n| /| | |\\ | / \\\\| | |// / _|_____|_\n|| | | | || / \\\\ | // / | | === | |\n(\' | | | `) | )===(| / |_| O |_|\n | | | / | || | | || O ||\n | /| | | (_)(_) | ||__*__||\n / || \\ / |_||_| / |~ \\___/ ~|\n /|_|| \\ | |_||_| | /=\\ /=\\ /=\\\n_/_[_]|____\\_|_________/__][__\\____________/_________[_]_[_]_[_]___\n7\n ==== ==== / ,_____________/\n ("o o) ~~o o / /\n _\\ -/_ _ _\\ -/_ / |\n / \\ / \\ / / \\ / \\_____/ | ___\n / \\/ \\ / //| | |\\\\ | /() \\\n| /| | |\\ | / \\\\| | |// / _|_____|_\n|| | | | || / \\\\ | // / | | === | |\n(\' | | | `) | )===(| / |_| O |_|\n | | | / | || | | || O ||\n | /| | | (_)(_) | ||__*__||\n / || \\ / |_||_| / |~ \\___/ ~|\n /|_|| \\ | |_||_| | /=\\ /=\\ /=\\\n_/_[_]|____\\_|_________/__][__\\____________/_________[_]_[_]_[_]___\n7\n ==== ==== / ,_____________/\n ("o o) o o~~ / /\n _\\ -/_ _ _\\- /_ / |\n / \\ / \\ / / \\ / \\_____/ | ___\n / \\/ \\ / //| | |\\\\ | /() \\\n| /| | |\\ | / \\\\| | |// / _|_____|_\n|| | | | || / \\\\ | // / | | === | |\n(\' | | | `) | )===(| / |_| O |_|\n | | | / | || | | || O ||\n | /| | | (_)(_) | ||__*__||\n / || \\ / |_||_| / |~ \\___/ ~|\n /|_|| \\ | |_||_| | /=\\ /=\\ /=\\\n_/_[_]|____\\_|_________/__][__\\____________/_________[_]_[_]_[_]___\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n20\n\n\n I think we better get indoors.\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n9\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n16\n\n\n Threepio!\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n1\n\n\n\n\n\n ______________________\n ______________ /\n___/ \\________________________/\n ___ _________\n / \\ =_._ + + _______________/\n_____________|_____|__________====\'_|_|__/\n ~\n\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n13\n ====\n ~~o o __\n _\\ -/_ ___ ______/\n / \\ / \\ \\_______________________/\n //| | |\\\\\n || | | | \\\\ /~\\\n || | | | \\\\ |-- )\n \') |====| \') _\\=/_\n / | || | / _ ()\n | (_)(_) //|/.\\|\n / |_||_| || \\_/\n / |_||_| || |\\-/| __ _\n_______________/_______[_][__\\________#_[]_[]__()__|_#_____________\n5\n ====\n ~~o o __\n _\\ -/_ ___ ______/\n / \\ / \\ \\_______________________/\n //| | |\\\\\n || | | | \\\\ /~\\\n || | | | \\\\ |oo )\n \') |====| \') _\\=/_\n / | || | / _ ()\n | (_)(_) //|/.\\|\n / |_||_| || \\_/\n / |_||_| || |\\-/| __ _\n_______________/_______[_][__\\________#_[]_[]__()__|_#_____________\n16\n ====\n ~~o o __\n _\\ -/_ ___ ______/\n / \\ / \\ \\_______________________/\n //| | |\\\\\n || | | | \\\\ /~\\ I must have taken\n || | | | \\\\ |oo ) a bad step.\n \') |====| \') _\\=/_\n / | || | / _ ()\n | (_)(_) //|/.\\|\n / |_||_| || \\_/\n / |_||_| || |\\-/| __ _\n_______________/_______[_][__\\________#_[]_[]__()__|_#_____________\n12\n ====\n ~~o o __\n _\\ -/_ ___ ______/\n / \\ / \\ \\_______________________/\n //| | |\\\\\n || | | | \\\\ /~\\ I must have taken\n || | | | \\\\ ( oo| a bad step.\n \') |====| \') _\\=/_\n / | || | / _ ()\n | (_)(_) //|/.\\|\n / |_||_| || \\_/\n / |_||_| || |\\-/| __ _\n_______________/_______[_][__\\________#_[]_[]__()__|_#_____________\n6\n ====\n ~~o o __\n _\\ -/_ ___ ______/\n / \\ / \\ \\_______________________/\n //| | |\\\\\n || | | | \\\\ /~\\\n || | | | \\\\ ( oo|\n \') |====| \') _\\=/_\n / | || | / _ ()\n | (_)(_) //|/.\\|\n / |_||_| || \\_/\n / |_||_| || |\\-/| __ _\n_______________/_______[_][__\\________#_[]_[]__()__|_#_____________\n15\n ====\n ~~o o __\n _\\ -/_ ___ ______/\n / \\ / \\ \\_______________________/\n //| | |\\\\\n || | | | \\\\ /~\\ Leave me.\n || | | | \\\\ ( oo| I\'m done for!\n \') |====| \') _\\=/_\n / | || | / _ ()\n | (_)(_) //|/.\\|\n / |_||_| || \\_/\n / |_||_| || |\\-/| __ _\n_______________/_______[_][__\\________#_[]_[]__()__|_#_____________\n11\n ====\n ~~o o __\n _\\ -/_ ___ ______/\n / \\ / \\ \\_______________________/\n //| | |\\\\\n || | | | \\\\ /~\\ Leave me.\n || | | | \\\\ |oo ) I\'m done for!\n \') |====| \') _\\=/_\n / | || | / _ ()\n | (_)(_) //|/.\\|\n / |_||_| || \\_/\n / |_||_| || |\\-/| __ _\n_______________/_______[_][__\\________#_[]_[]__()__|_#_____________\n6\n ====\n ~~o o __\n _\\ -/_ ___ ______/\n / \\ / \\ \\_______________________/\n //| | |\\\\\n || | | | \\\\ /~\\\n || | | | \\\\ |oo )\n \') |====| \') _\\=/_\n / | || | / _ ()\n | (_)(_) //|/.\\|\n / |_||_| || \\_/\n / |_||_| || |\\-/| __ _\n_______________/_______[_][__\\________#_[]_[]__()__|_#_____________\n19\n ====\n What kind of ~~o o __\n talk is that! _\\ -/_ ___ ______/\n / \\ / \\ \\_______________________/\n //| | |\\\\\n || | | | \\\\ /~\\\n || | | | \\\\ |oo )\n \') |====| \') _\\=/_\n / | || | / _ ()\n | (_)(_) //|/.\\|\n / |_||_| || \\_/\n / |_||_| || |\\-/| __ _\n_______________/_______[_][__\\________#_[]_[]__()__|_#_____________\n7\n ====\n ~~o o __\n _\\ -/_ ___ ______/\n / \\ / \\ \\_______________________/\n //| | |\\\\\n || | | | \\\\ /~\\\n || | | | \\\\ |oo )\n \') |====| \') _\\=/_\n / | || | / _ ()\n | (_)(_) //|/.\\|\n / |_||_| || \\_/\n / |_||_| || |\\-/| __ _\n_______________/_______[_][__\\________#_[]_[]__()__|_#_____________\n4\n\n\n\n\n\n\n\n\n\n\n\n\n\n21\n\n\n___\n \\\n \\____\n \\__\n \\ ________\n \\ =_._ / o o o \\__\n______________\\_______________====\'______|_________|__|_______\n \\\n |\n \\\n \\\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ () \\\\ / \\ / \\\n //|/.\\| |)\\//| | |\\\\\n || \\_/ ||\\/ | | | ||\n || |\\ /| # | | | ||\n # \\_ _/ |====| \')\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n_______________________/_]_[_\\______/__][__\\_______________________\n4\n /~\\ ====\n ( oo| ~~o o\n _\\=/_ _\\ -/_\n / _ () \\\\ / \\ / \\\n //|/.\\| |)\\//| | |\\\\\n || \\_/ ||\\/ | | | ||\n || |\\ /| # | | | ||\n # \\_ _/ |====| \')\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n_______________________/_]_[_\\______/__][__\\_______________________\n13\n /~\\ ====\n ( oo| ~~o o You fought\n _\\=/_ _\\ -/_ in the clone wars?\n / _ () \\\\ / \\ / \\\n //|/.\\| |)\\//| | |\\\\\n || \\_/ ||\\/ | | | ||\n || |\\ /| # | | | ||\n # \\_ _/ |====| \')\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n_______________________/_]_[_\\______/__][__\\_______________________\n9\n /~\\ ====\n ( oo| ~~o o You fought\n _\\=/_ _\\ -/_ in the clone wars?\n / _ () \\\\ / \\ / \\\n //|/.\\| |)\\//| | |\\\\\n || \\_/ ||\\/ | | | ||\n || |\\ /| # | | | ||\n # \\_ _/ |====| \')\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n_______________________/_]_[_\\______/__][__\\_______________________\n3\n /~\\ ====\n ( oo| ~~o o\n _\\=/_ _\\ -/_\n / _ () \\\\ / \\ / \\\n //|/.\\| |)\\//| | |\\\\\n || \\_/ ||\\/ | | | ||\n || |\\ /| # | | | ||\n # \\_ _/ |====| \')\n | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n_______________________/_]_[_\\______/__][__\\_______________________\n5\n\n\n\n\n\n\n\n\n\n\n\n\n\n5\n ====\n (o o")\n _\\- /_\n ___ / \\ / \\\n /() \\ / \\/ \\\n _|_____|_ | /| | |\\ |\n | | === | | || | | | ||\n |_| O |_| (\' | | | `)\n || O || | | |\n ||__*__|| | |\\ |\n |~ \\___/ ~| / || \\\n /=\\ /=\\ /=\\ / ||_|\\\n_______________[_]_[_]_[_]____________/____|[_]_\\__________________\n10\n ====\n (o o") Yes.\n _\\- /_\n ___ / \\ / \\\n /() \\ / \\/ \\\n _|_____|_ | /| | |\\ |\n | | === | | || | | | ||\n |_| O |_| (\' | | | `)\n || O || | | |\n ||__*__|| | |\\ |\n |~ \\___/ ~| / || \\\n /=\\ /=\\ /=\\ / ||_|\\\n_______________[_]_[_]_[_]____________/____|[_]_\\__________________\n12\n ====\n (o o") Yes.\n _\\- /_\n ___ / \\ / \\\n / ()\\ / \\/ \\\n _|_____|_ | /| | |\\ |\n | | === | | || | | | ||\n |_| O |_| (\' | | | `)\n || O || | | |\n ||__*__|| | |\\ |\n |~ \\___/ ~| / || \\\n /=\\ /=\\ /=\\ / ||_|\\\n_______________[_]_[_]_[_]____________/____|[_]_\\__________________\n6\n ====\n (o o")\n _\\- /_\n ___ / \\ / \\\n / ()\\ / \\/ \\\n _|_____|_ | /| | |\\ |\n | | === | | || | | | ||\n |_| O |_| (\' | | | `)\n || O || | | |\n ||__*__|| | |\\ |\n |~ \\___/ ~| / || \\\n /=\\ /=\\ /=\\ / ||_|\\\n_______________[_]_[_]_[_]____________/____|[_]_\\__________________\n19\n ====\n (o o") I was once\n _\\- /_ a Jedi Knight\n ___ / \\ / \\ the same as\n / ()\\ / \\/ \\ your father.\n _|_____|_ | /| | |\\ |\n | | === | | || | | | ||\n |_| O |_| (\' | | | `)\n || O || | | |\n ||__*__|| | |\\ |\n |~ \\___/ ~| / || \\\n /=\\ /=\\ /=\\ / ||_|\\\n_______________[_]_[_]_[_]____________/____|[_]_\\__________________\n26\n ====\n (o o") I was once\n _\\- /_ a Jedi Knight\n ___ / \\ / \\ the same as\n /() \\ / \\/ \\ your father.\n _|_____|_ | /| | |\\ |\n | | === | | || | | | ||\n |_| O |_| (\' | | | `)\n || O || | | |\n ||__*__|| | |\\ |\n |~ \\___/ ~| / || \\\n /=\\ /=\\ /=\\ / ||_|\\\n_______________[_]_[_]_[_]____________/____|[_]_\\__________________\n6\n ====\n (o o")\n _\\- /_\n ___ / \\ / \\\n /() \\ / \\/ \\\n _|_____|_ | /| | |\\ |\n | | === | | || | | | ||\n |_| O |_| (\' | | | `)\n || O || | | |\n ||__*__|| | |\\ |\n |~ \\___/ ~| / || \\\n /=\\ /=\\ /=\\ / ||_|\\\n_______________[_]_[_]_[_]____________/____|[_]_\\__________________\n5\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | | ||\n || |\\ /| || || | | | ||\n # \\_ _/ # (\' |====| \')\n | | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n_______________________/_]_[_\\______/__][__\\_______________________\n3\n /~\\ ====\n ( oo| ~~o o\n _\\=/_ _\\ -/_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | | ||\n || |\\ /| || || | | | ||\n # \\_ _/ # (\' |====| \')\n | | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n_______________________/_]_[_\\______/__][__\\_______________________\n10\n /~\\ ====\n ( oo| ~~o o I wish I\'d\n _\\=/_ _\\ -/_ known him.\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | | ||\n || |\\ /| || || | | | ||\n # \\_ _/ # (\' |====| \')\n | | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n_______________________/_]_[_\\______/__][__\\_______________________\n4\n /~\\ ====\n ( oo| ~~o o I wish I\'d\n _\\=/_ _\\ -/_ known him.\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | | ||\n || |\\ /| || || | | | ||\n # \\_ _/ # (\' |====| \')\n | | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n_______________________/_]_[_\\______/__][__\\_______________________\n3\n /~\\ ====\n ( oo| ~~o o I wish I\'d\n _\\=/_ _\\ -/_ known him.\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | | ||\n || |\\ /| || || | | | ||\n # \\_ _/ # (\' |====| \')\n | | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n_______________________/_]_[_\\______/__][__\\_______________________\n14\n /~\\ ====\n ( oo| ~~o o I wish I\'d\n _\\=/_ _\\ -/_ known him.\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | | ||\n || |\\ /| || || | | | ||\n # \\_ _/ # (\' |====| \')\n | | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n_______________________/_]_[_\\______/__][__\\_______________________\n6\n /~\\ ====\n ( oo| ~~o o\n _\\=/_ _\\ -/_\n / _ \\ / \\ / \\\n //|/.\\|\\\\ //| | |\\\\\n || \\_/ || || | | | ||\n || |\\ /| || || | | | ||\n # \\_ _/ # (\' |====| \')\n | | | | | || |\n | | | (_)(_)\n []|[] |_||_|\n | | | |_||_|\n_______________________/_]_[_\\______/__][__\\_______________________\n1\n\n\n\n\n\n\n\n\n\n\n\n\n\n5\n ====\n (o o")\n _\\- /_\n ___ / \\ / \\\n /() \\ / \\/ \\\n _|_____|_ | /| | |\\ |\n | | === | | || | | | ||\n |_| O |_| ===(= | | | `)\n || O || | | |\n ||__*__|| | |\\ |\n |~ \\___/ ~| / || \\\n /=\\ /=\\ /=\\ / ||_|\\\n_______________[_]_[_]_[_]____________/____|[_]_\\__________________\n25\n ====\n (o o") I have\n _\\- /_ something here\n ___ / \\ / \\ for you.\n /() \\ / \\/ \\\n _|_____|_ | /| | |\\ |\n | | === | | || | | | ||\n |_| O |_| ===(= | | | `)\n || O || | | |\n ||__*__|| | |\\ |\n |~ \\___/ ~| / || \\\n /=\\ /=\\ /=\\ / ||_|\\\n_______________[_]_[_]_[_]____________/____|[_]_\\__________________\n4\n ====\n (o o")\n _\\- /_\n ___ / \\ / \\\n /() \\ / \\/ \\\n _|_____|_ | /| | |\\ |\n | | === | | || | | | ||\n |_| O |_| ===(= | | | `)\n || O || | | |\n ||__*__|| | |\\ |\n |~ \\___/ ~| / || \\\n /=\\ /=\\ /=\\ / ||_|\\\n_______________[_]_[_]_[_]____________/____|[_]_\\__________________\n4\n\n\n\n\n\n\n\n\n\n\n\n\n\n3\n ==== ====\n ~~o o (o o")\n _\\ -/_ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | || | /| | |\\ |\n || | | | || || | | | ||\n (\' |====| \') ===(= | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n9\n ==== ====\n What is it? ~~o o (o o")\n _\\ -/_ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | || | /| | |\\ |\n || | | | || || | | | ||\n (\' |====| \') ===(= | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n1\n ==== ====\n What is it? ~~o o (o o")\n _\\ -/_ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | || | /| | |\\ |\n || | | | || || | | | ||\n (\' |====| \') ===(= | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n5\n ==== ====\n What is it? ~~o o (o o")\n _\\ -/_ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | || / /| | |\\ |\n || | | | || // | | | ||\n (\' |====| \') ===(= | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n3\n ==== ====\n What is it? ~~o o (o o")\n _\\ -/_ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | || / /| | |\\ |\n || | | | || // | | | ||\n (\' |====| \') ===(= | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n4\n ==== ====\n What is it? ~~o o (o o")\n _\\ -/_ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | \\\\ / /| | |\\ |\n || | | | \\\\ // | | | ||\n (\' |====| \')==(= | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n3\n ==== ====\n What is it? ~~o o (o o")\n _\\ -/_ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | \\\\ / /| | |\\ |\n || | | | \\\\ // | | | ||\n (\' |====| =)==(` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n2\n ==== ====\n What is it? ~~o o (o o")\n _\\ -/_ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | \\\\ / /| | |\\ |\n || | | | \\\\ // | | | ||\n (\' |====| =)===(` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n4\n ==== ====\n What is it? ~~o o (o o")\n _\\ -/_ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | || / /| | |\\ |\n || | | | || // | | | ||\n (\' |====| =)=== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n5\n ==== ====\n ~~o o (o o")\n _\\ -/_ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | || / /| | |\\ |\n || | | | || || | | | ||\n (\' |====| =)=== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n14\n ==== ====\n ~~o o (o o") Your father\'s\n _\\ -/_ _\\- /_ lightsabre!\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | || / /| | |\\ |\n || | | | || || | | | ||\n (\' |====| =)=== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n12\n ==== ====\n ~~o o (o o") Your father\'s\n _\\ o/_ _\\- /_ lightsabre!\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | || / /| | |\\ |\n || | | | || || | | | ||\n (\' |====| =)=== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n4\n ==== ====\n ~~o o (o o")\n _\\ o/_ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | || / /| | |\\ |\n || | | | || || | | | ||\n (\' |====| =)=== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n5\n\n\n\n\n\n\n\n\n\n\n\n\n\n4\n ====\n ~~o o\n _\\ o/_\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n6\n ====\n ~~o o This is the\n _\\ o/_ weapon of a\n / \\ / \\ Jedi Knight.\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n4\n ====\n ~~o o This is the\n _\\ -/_ weapon of a\n / \\ / \\ Jedi Knight.\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n1\n ====\n ~~o o This is the\n _\\ -/_ weapon of a\n / \\ / \\ Jedi Knight.\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===***\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n1\n ====\n ~~o o This is the\n _\\ -/_ weapon of a\n / \\ / \\ Jedi Knight.\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===******\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n1\n ====\n ~~o o This is the\n _\\ -/_ weapon of a\n / \\ / \\ Jedi Knight.\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===*********\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n1\n ====\n ~~o o This is the\n _\\ -/_ weapon of a\n / \\ / \\ Jedi Knight.\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===************\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n7\n ====\n ~~o o This is the\n _\\ -/_ weapon of a\n / \\ / \\ Jedi Knight.\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===*************\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n5\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===*************\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n6\n ====\n ~~o o Not as clumsy\n _\\ -/_ or random as\n / \\ / \\ a blaster.\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===*************\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n10\n ====\n ~~o o Not as clumsy\n _\\ -/_ or random as\n / \\ / \\ a blaster.\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====|=)===*************\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n3\n ====\n ~~o o Not as clumsy\n _\\ -/_ or random as\n / \\ / \\ a blaster.\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===*************\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n3\n ====\n ~~o o Not as clumsy\n _\\ -/_ or random as\n / \\ / \\ a blaster.\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====|=)===*************\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n1\n ====\n ~~o o Not as clumsy\n _\\ -/_ or random as\n / \\ / \\ a blaster.\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===*************\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n1\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===*************\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n14\n ====\n ~~o o An elegant\n _\\ -/_ weapon for a\n / \\ / \\ more civilised\n //| | |\\\\ day.\n || | | | ||\n || | | | ||\n (\' |====| =)===*************\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n6\n ====\n ~~o o An elegant\n _\\ -/_ weapon for a\n / \\ / \\ more civilised\n //| | |\\\\ day.\n || | | | ||\n || | | | ||\n (\' |====|=)===*************\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n5\n ====\n ~~o o An elegant\n _\\ -/_ weapon for a\n / \\ / \\ more civilised\n //| | |\\\\ day.\n || | | | ||\n || | | | ||\n (\' |====| =)===*************\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n2\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===*************\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n1\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===**********\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n1\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===*******\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n1\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===****\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n1\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===*\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n5\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n20\n ====\n ~~o o How did my\n _\\ -/_ father die?\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n2\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n49\n ====\n ~~o o A young Jedi called\n _\\ -/_ Darth Vader, who was a\n / \\ / \\ pupil of mine until\n //| | |\\\\ he turned to evil,...\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n1\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n49\n ====\n ~~o o ...helped the Empire\n _\\ -/_ hunt down and destroy\n / \\ / \\ the Jedi Knights.\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n1\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n45\n ====\n ~~o o He betrayed and\n _\\ -/_ murdered your father.\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n1\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n49\n ====\n ~~o o Vader was seduced\n _\\ -/_ by the Dark side of\n / \\ / \\ the Force.\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n1\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n36\n ====\n ~~o o The Force?\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n1\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n49\n ====\n ~~o o The Force is what\n _\\ -/_ gives the Jedi\n / \\ / \\ his power.\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n1\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n51\n ====\n ~~o o It\'s an energy field\n _\\ -/_ created by all\n / \\ / \\ living things.\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n1\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n49\n ====\n ~~o o It surrounds us and\n _\\ -/_ penetrates us.\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n1\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n49\n ====\n ~~o o It binds the galaxy\n _\\ -/_ together.\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n6\n ====\n ~~o o\n _\\ -/_\n / \\ / \\\n //| | |\\\\\n || | | | ||\n || | | | ||\n (\' |====| =)===\n | || |\n (_)(_)\n |_||_|\n |_||_|\n__________________/__][__\\_________________________________________\n4\n\n\n\n\n\n\n\n\n\n\n\n\n\n5\n ====\n (o o")\n _\\- /_\n ___ / \\ / \\\n /() \\ / \\/ \\\n _|_____|_ | /| | |\\ |\n | | === | | || | | | ||\n |_| O |_| (\' | | | `)\n || O || | | |\n ||__*__|| | |\\ |\n ------- |~ \\___/ ~| / || \\\n || || /=\\ /=\\ /=\\ / ||_|\\\n______________||___||______[_]_[_]_[_]_______/____|[_]_\\___________\n9\n Now let\'s see if we ====\n can\'t figure out what (o o")\n you are. _\\- /_\n ___ / \\ / \\\n /() \\ / \\/ \\\n _|_____|_ | /| | |\\ |\n | | === | | || | | | ||\n |_| O |_| (\' | | | `)\n || O || | | |\n ||__*__|| | |\\ |\n ------- |~ \\___/ ~| / || \\\n || || /=\\ /=\\ /=\\ / ||_|\\\n______________||___||______[_]_[_]_[_]_______/____|[_]_\\___________\n21\n Now let\'s see if we ====\n can\'t figure out what (o o")\n you are. _\\- /_\n ___ / \\ / \\\n / ()\\ / \\/ \\\n _|_____|_ | /| | |\\ |\n | | === | | || | | | ||\n |_| O |_| (\' | | | `)\n || O || | | |\n ||__*__|| | |\\ |\n ------- |~ \\___/ ~| / || \\\n || || /=\\ /=\\ /=\\ / ||_|\\\n______________||___||______[_]_[_]_[_]_______/____|[_]_\\___________\n2\n ====\n (o o")\n _\\- /_\n ___ / \\ / \\\n / ()\\ / \\/ \\\n _|_____|_ | /| | |\\ |\n | | === | | || | | | ||\n |_| O |_| (\' | | | `)\n || O || | | |\n ||__*__|| | |\\ |\n ------- |~ \\___/ ~| / || \\\n || || /=\\ /=\\ /=\\ / ||_|\\\n______________||___||______[_]_[_]_[_]_______/____|[_]_\\___________\n2\n ====\n (o o")\n _\\- /_\n ___ / \\ / \\\n /() \\ / \\/ \\\n _|_____|_ | /| | |\\ |\n | | === | | || | | | ||\n |_| O |_| (\' | | | `)\n || O || | | |\n ||__*__|| | |\\ |\n ------- |~ \\___/ ~| / || \\\n || || /=\\ /=\\ /=\\ / ||_|\\\n______________||___||______[_]_[_]_[_]_______/____|[_]_\\___________\n9\n ====\n I saw part (o o")\n of the message... _\\- /_\n ___ / \\ / \\\n /() \\ / \\/ \\\n _|_____|_ | /| | |\\ |\n | | === | | || | | | ||\n |_| O |_| (\' | | | `)\n || O || | | |\n ||__*__|| | |\\ |\n ------- |~ \\___/ ~| / || \\\n || || /=\\ /=\\ /=\\ / ||_|\\\n______________||___||______[_]_[_]_[_]_______/____|[_]_\\___________\n11\n ====\n I saw part (o o")\n of the message... _\\- /_\n ___ / \\ / \\\n /() \\ / \\/ \\\n _|_____|_ | /| | |\\ |\n ,@ | | === | | || | | | ||\n /=- |_| O |_| (\' | | | `)\n || || O || | | |\n || ||__*__|| | |\\ |\n --~~--- |~ \\___/ ~| / || \\\n || || /=\\ /=\\ /=\\ / ||_|\\\n______________||___||______[_]_[_]_[_]_______/____|[_]_\\___________\n30\n I seem to have ====\n found it! (o o")\n _\\- /_\n ___ / \\ / \\\n /() \\ / \\/ \\\n _|_____|_ | /| | |\\ |\n ,@ | | === | | || | | | ||\n /=- |_| O |_| (\' | | | `)\n || || O || | | |\n || ||__*__|| | |\\ |\n --~~--- |~ \\___/ ~| / || \\\n || || /=\\ /=\\ /=\\ / ||_|\\\n______________||___||______[_]_[_]_[_]_______/____|[_]_\\___________\n4\n ====\n (o o")\n _\\- /_\n ___ / \\ / \\\n /() \\ / \\/ \\\n _|_____|_ | /| | |\\ |\n ,@ | | === | | || | | | ||\n /=- |_| O |_| (\' | | | `)\n || || O || | | |\n || ||__*__|| | |\\ |\n --~~--- |~ \\___/ ~| / || \\\n || || /=\\ /=\\ /=\\ / ||_|\\\n______________||___||______[_]_[_]_[_]_______/____|[_]_\\___________\n4\n\n\n\n\n\n\n\n\n\n\n\n\n\n69\n\n General Kenobi. Years ago you\n served my father in the Clone\n wars. Now he begs you to help\n him in his struggle against\n the Empire.\n ,@\n /=-\n ||\n ||\n --~~---\n || ||\n______________||___||______________________________________________\n1\n\n\n\n\n\n\n ,@\n /=-\n ||\n ||\n --~~---\n || ||\n______________||___||______________________________________________\n59\n\n I have placed information vital\n to the survival of the Rebellion\n into the memory systems of this\n R2 unit.\n\n ,@\n /=-\n ||\n ||\n --~~---\n || ||\n______________||___||______________________________________________\n1\n\n\n\n\n\n\n ,@\n /=-\n ||\n ||\n --~~---\n || ||\n______________||___||______________________________________________\n55\n\n You must see this droid safely\n delivered to him on Alderaan.\n\n\n\n ,@\n /=-\n ||\n ||\n --~~---\n || ||\n______________||___||______________________________________________\n1\n\n\n\n\n\n\n ,@\n /=-\n ||\n ||\n --~~---\n || ||\n______________||___||______________________________________________\n36\n\n Help me Obi-Wan Kenobi!\n You\'re my only hope!\n\n\n\n ,@\n /=-\n ||\n ||\n --~~---\n || ||\n______________||___||______________________________________________\n5\n\n\n\n\n\n\n ,@\n /=-\n ||\n ||\n --~~---\n || ||\n______________||___||______________________________________________\n1\n\n\n\n\n\n\n ,@\n /=-\n ||\n ~~\n --~~---\n || ||\n______________||___||______________________________________________\n1\n\n\n\n\n\n\n ,@\n /=-\n ~~\n ~~\n --~~---\n || ||\n______________||___||______________________________________________\n1\n\n\n\n\n\n\n ,@\n ~~~\n ~~\n ~~~\n --~~---\n || ||\n______________||___||______________________________________________\n1\n\n\n\n\n\n\n ~~\n ~~~\n ~~\n ~~~\n --~~---\n || ||\n______________||___||______________________________________________\n1\n\n\n\n\n\n\n ~~\n ~~~\n ~~\n ~~~\n --~~---\n || ||\n______________||___||______________________________________________\n1\n\n\n\n\n\n\n ~~\n ~~~\n ~~\n ~~~\n --~~---\n || ||\n______________||___||______________________________________________\n1\n\n\n\n\n\n\n ~~\n ~~~\n ~~\n ~~~\n --~~---\n || ||\n______________||___||______________________________________________\n1\n\n\n\n\n\n\n ~~\n ~~~\n ~~\n ~~~\n --~~---\n || ||\n______________||___||______________________________________________\n1\n\n\n\n\n\n\n ~~\n ~~~\n ~~\n ~~~\n --~~---\n || ||\n______________||___||______________________________________________\n1\n\n\n\n\n\n\n ~~\n ~~~\n ~~\n ~~~\n --~~---\n || ||\n______________||___||______________________________________________\n1\n\n\n\n\n\n\n ~~\n ~~~\n ~~\n ~~~\n --~~---\n || ||\n______________||___||______________________________________________\n3\n\n\n\n\n\n\n\n\n\n\n -------\n || ||\n______________||___||______________________________________________\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n3\n ==== ====\n ~~o o (o o")\n _\\ -/_ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | || / /| | |\\ |\n || | | | || || | | | ||\n (\' |====| =)=== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n28\n ==== ====\n ~~o o (o o") You must learn\n _\\ -/_ _\\- /_ the ways of the\n / \\ / \\ / \\ / \\ Force...\n //| | |\\\\ / \\/ \\\n || | | | || / /| | |\\ |\n || | | | || || | | | ||\n (\' |====| =)=== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n1\n ==== ====\n ~~o o (o o")\n _\\ -/_ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | || / /| | |\\ |\n || | | | || || | | | ||\n (\' |====| =)=== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n40\n ==== ====\n ~~o o (o o") ...if you are\n _\\ -/_ _\\- /_ to come with me\n / \\ / \\ / \\ / \\ to Alderaan.\n //| | |\\\\ / \\/ \\\n || | | | || / /| | |\\ |\n || | | | || || | | | ||\n (\' |====| =)=== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n4\n ==== ====\n ~~o o (o o")\n _\\ -/_ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | || / /| | |\\ |\n || | | | || || | | | ||\n (\' |====| =)=== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n9\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n . .\n . . .\n . . .\n. . .\n . . . .\n . .\n . . .\n . . .\n . .\n . . . .\n . .\n . . . .\n . . .\n2\n . .\n . . .\n . .\n . . .\n . . . .\n . .\n . . .\n . . .\n . .\n . . . .\n . .\n . . . .\n . . .\n2\n . .\n . . .\n . .\n . . .\n . . . .\n . .\n . . .\n . . .\n . .\n . . . .\n . .\n . . . .\n . . .\n2\n . .\n . . .\n . .\n . . .\n . . . .\n . .\n . . .\n . .\n . .\n . . . .\n. . .\n . . . .\n . . .\n2\n . .\n . . .\n . .\n. . . .\n . . . .\n . .\n . . .\n . .\n . .\n . . . .\n . . .\n . . . .\n . . .\n2\n . .\n . . .\n . .\n . . . .\n . . . .\n: . .\n| . . .\n| . .\n: . .\n . . . .\n . . .\n. . . . .\n . . .\n2\n .\n . . .\n . .\n . . . .\n\\ . . .\n.: . .\n_| . . .\n.| . .\n : . .\n/ . . . .\n . . .\n . . . .\n . . .\n2\n .\n . . .\n . .\n\\ . . . .\n:\\ . . .\n..: . .\n__| . . .\n..| . .\n: : . .\n./ . . . .\n/ . . .\n . . . .\n . . .\n2\n .\n . . .\n\\ . .\n.\\ . . . .\n :\\ . . .\n...: . .\n___| . . .\n...| . .\n : : . .\n../ . . . .\n / . . .\n/ . . . .\n . . .\n2\n .\n. . . .\n.\\ . .\n .\\ . . . .\n| :\\ . . .\n....: . .\n____| . . .\n....| . .\n : : . .\n.../ . . .\n / . . .\n./ . . . .\n . . .\n2\n .\n-. . . .\n .\\ . .\n\\ .\\ . . . .\n | :\\ . . .\n/....: . .\n_____| . . .\n.....| . .\n : : . .\n..../ . . .\n. / . . .\n_./ . . . .\n . . .\n2\n .\n\'-. . . .\n_ .\\ . .\n \\ .\\ . . . .\n) | :\\ . . .\n_/....: .\n______| . . .\n......| . .\n: : : . .\n...../ . . .\n . / . . .\n._./ . . . .\n- . . .\n2\n_ .\n.\'-. . . .\n__ .\\ . .\n \\ .\\ . . . .\n() | :\\ . . .\n__/....: .\n_______| . . .\n.......| . .\n : : : . .\n....../ . . .\n . / . . .\n.._./ . . . .\n.- . . .\n2\n__ .\n..\'-. . . .\n.__ .\\ . .\n/ \\ .\\ . . . .\n () | :\\ . . .\n\\__/....: .\n________| . . .\n........| . .\n : : : . .\n......./ . . .\n. . / . . .\n..._./ . . .\n..- . . .\n2\n-__ .\n...\'-. . . .\n .__ .\\ . .\n./ \\ .\\ . . . .\n| () | :\\ . . .\n.\\__/....: .\n_________| . . .\n.........| . .\n : : : . .\n......../ . . .\n . . / . . .\n...._./ . . .\n_..- . . .\n2\n--__ .\n:...\'-. . . .\n: .__ .\\ .\n../ \\ .\\ . . . .\n:| () | :\\ . . .\n..\\__/....: .\n__________| . . .\n..........| . .\n: : : : . .\n........./ . . .\n: . . / . . .\n....._./ . . .\n__..- . . .\n2\n---__ .\n.:...\'-. . . .\n : .__ .\\ .\n.../ \\ .\\ . . . .\n :| () | :\\ . . .\n...\\__/....: .\n___________| . . .\n...........| . .\n : : : : . .\n........../ . . .\n : . . / . . .\n......_./ . . .\n___..- . . .\n2\n_---__ .\n..:...\'-. . . .\n. : .__ .\\ .\n..../ \\ .\\ . . . .\n :| () | :\\ . . .\n....\\__/....: .\n____________| . . .\n............| .\n : : : : . .\n.........../ . . .\n. : . . / . . .\n......._./ . . .\n.___..- . . .\n2\n__---__ .\n...:...\'-. . . .\n . : .__ .\\ .\n...../ \\ .\\ . . . .\n :| () | :\\ . . .\n.....\\__/....: .\n_____________| . . .\n.............| .\n : : : : . .\n............/ . . .\n . : . . / . . .\n........_./ . . .\n..___..- . . .\n2\n __---__ .\n\'...:...\'-. . . .\n . : .__ .\\ .\n....../ \\ .\\ . . . .\n: :| () | :\\ . .\n......\\__/....: .\n______________| . . .\n..............| .\n: : : : : . .\n............./ . . .\n . : . . / . . .\n........._./ . . .\n-..___..- . .\n2\n __---__ .\n-\'...:...\'-. . .\n. . : .__ .\\ .\n......./ \\ .\\ . . . .\n : :| () | :\\ . .\n.......\\__/....: .\n_______________| . . .\n...............| .\n : : : : : . .\n............../ . . .\n. . : . . / . . .\n_........._./ . . .\n -..___..- . .\n2\n __---__ .\n.-\'...:...\'-. . .\n . . : .__ .\\ .\n......../ \\ .\\ . . . .\n : :| () | :\\ . .\n........\\__/....: .\n________________| . . .\n................| .\n : : : : : . .\n.............../ . . .\n . . : . . / . . .\n._........._./ . . .\n -..___..- . .\n2\n __---__ .\n .-\'...:...\'-. . .\n/ . . : .__ .\\ .\n........./ \\ .\\ . . . .\n: : :| () | :\\ . .\n.........\\__/....: .\n_________________| . . .\n.................| .\n: : : : : : . .\n................/ . . .\n . . : . . / . . .\n\\._........._./ . . .\n -..___..- . .\n2\n __---__ .\n .-\'...:...\'-. . .\n / . . : .__ .\\ .\n/........./ \\ .\\ . . . .\n : : :| () | :\\ . .\n..........\\__/....: .\n__________________| . . .\n..................| .\n : : : : : : . .\n................./ . . .\n\\ . . : . . / . . .\n \\._........._./ . . .\n -..___..- . .\n2\n __---__ .\n .-\'...:...\'-. . .\n / . . : .__ .\\ .\n /........./ \\ .\\ . . . .\n/ : : :| () | :\\ . .\n...........\\__/....: .\n___________________| . . .\n...................| .\n : : : : : : . .\n\\................./ . .\n \\ . . : . . / . . .\n \\._........._./ . . .\n -..___..- . .\n2\n __---__ .\n. .-\'...:...\'-. . .\n / . . : .__ .\\ .\n /........./ \\ .\\ . . . .\n / : : :| () | :\\ . .\n:...........\\__/....: .\n|___________________| . . .\n|...................| .\n: : : : : : : . .\n \\................./ . .\n \\ . . : . . / . . .\n \\._........._./ . . .\n -..___..- . .\n2\n __---__ .\n . .-\'...:...\'-. . .\n / . . : .__ .\\ .\n /........./ \\ .\\ . . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n |___________________| . . .\n |...................| .\n : : : : : : : . .\n \\................./ . .\n \\ . . : . . / . . .\n. \\._........._./ . . .\n -..___..- . .\n2\n __---__ .\n . .-\'...:...\'-. . .\n / . . : .__ .\\ .\n /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n |___________________| . .\n |...................| .\n : : : : : : : . .\n. \\................./ . .\n \\ . . : . . / . . .\n . \\._........._./ . . .\n -..___..- . .\n2\n __---__ .\n . .-\'...:...\'-. . .\n / . . : .__ .\\ .\n /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n |___________________| . .\n |...................| .\n : : : : : : : . .\n . \\................./ . .\n \\ . . : . . / . . .\n . \\._........._./ . . .\n -..___..- . .\n2\n. __---__\n . .-\'...:...\'-. . .\n / . . : .__ .\\ .\n. /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n |___________________| . .\n |...................| .\n : : : : : : : . .\n . \\................./ . .\n \\ . . : . . / . .\n . \\._........._./ . . .\n -..___..- . .\n2\n . __---__\n . .-\'...:...\'-. . .\n / . . : .__ .\\ .\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n |___________________| . .\n |...................| .\n : : : : : : : . .\n . \\................./ . .\n \\ . . : . . / . .\n . \\._........._./ . . .\n -..___..- . .\n2\n . __---__\n. . .-\'...:...\'-. . .\n / . . : .__ .\\ .\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n |___________________| . .\n |...................| .\n. : : : : : : : . .\n . \\................./ . .\n \\ . . : . . / . .\n . \\._........._./ . . .\n -..___..- . .\n2\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\ .\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n. |___________________| . .\n |...................| .\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n . \\._........._./ . . .\n -..___..- . .\n12\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| .\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== /\\___/\\\n ( o o o o | //|[ ] \\\\\n _\\ -/_ _\\- /_ // |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ \\\\ | |//\n | | :: \\ | | ::: | \\#|====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n39\n This station is now /~~\\\n the ultimate power |<><>|\n in the universe. /_/\\_\\\n /""\\ ==== /\\___/\\\n ( o o o o | //|[ ] \\\\\n _\\ -/_ _\\- /_ // |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ \\\\ | |//\n | | :: \\ | | ::: | \\#|====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n1\n /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== /\\___/\\\n ( o o o o | //|[ ] \\\\\n _\\ -/_ _\\- /_ // |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ \\\\ | |//\n | | :: \\ | | ::: | \\#|====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n31\n I suggest /~~\\\n we use it! |<><>|\n /_/\\_\\\n /""\\ ==== /\\___/\\\n ( o o o o | //|[ ] \\\\\n _\\ -/_ _\\- /_ // |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ \\\\ | |//\n | | :: \\ | | ::: | \\#|====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n3\n /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== /\\___/\\\n ( o o o o | //|[ ] \\\\\n _\\ -/_ _\\- /_ // |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ \\\\ | |//\n | | :: \\ | | ::: | \\#|====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n29\n The ability to destroy /~~\\\n a planet is insignificant... |<><>|\n /_/\\_\\\n /""\\ ==== /\\___/\\\n ( o o o o | //|[ ] \\\\\n _\\ -/_ _\\- /_ // |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ \\\\ | |//\n | | :: \\ | | ::: | \\#|====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n1\n /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== /\\___/\\\n ( o o o o | //|[ ] \\\\\n _\\ -/_ _\\- /_ // |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ \\\\ | |//\n | | :: \\ | | ::: | \\#|====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n4\n ...next to the power /~~\\\n of the Force! |<><>|\n /_/\\_\\\n /""\\ ==== /\\___/\\\n ( o o o o | //|[ ] \\\\\n _\\ -/_ _\\- /_ // |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ \\\\ | |//\n | | :: \\ | | ::: | \\#|====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n13\n ...next to the power /~~\\\n of the Force! |<><>|\n /_/\\_\\\n /""\\ ==== /\\___/\\\n ( o o | o o //|[ ] \\\\\n _\\ -/_ _\\ -/_ // |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ \\\\ | |//\n | | :: \\ | | ::: | \\#|====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n10\n ...next to the power /~~\\\n of the Force! |<><>|\n /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( o o | o o \\\\//|[ ] \\\\\n _\\ -/_ _\\ -/_ \\/ |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ | |//\n | | :: \\ | | ::: | |====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n11\n ...next to the power /~~\\\n of the Force! |<><>|\n /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( o o | o o \\\\//|[ ] \\\\\n _\\ -/_ _\\ -/_ \\/ |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ | |//\n | | :: \\ | | ::: | |====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n3\n /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( o o | o o \\\\//|[ ] \\\\\n _\\ -/_ _\\ -/_ \\/ |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ | |//\n | | :: \\ | | ::: | |====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n9\n Don\'t try to frighten /~~\\\n us with your sorcerer\'s |<><>|\n ways, Lord Vader... /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( o o | o o \\\\//|[ ] \\\\\n _\\ -/_ _\\ -/_ \\/ |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ | |//\n | | :: \\ | | ::: | |====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n21\n Don\'t try to frighten /~~\\\n us with your sorcerer\'s |<><>|\n ways, Lord Vader... /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( o o o o | \\\\//|[ ] \\\\\n _\\ -/_ _\\- /_ \\/ |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ | |//\n | | :: \\ | | ::: | |====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n6\n /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( o o o o | \\\\//|[ ] \\\\\n _\\ -/_ _\\- /_ \\/ |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ | |//\n | | :: \\ | | ::: | |====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n10\n /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( o o o o | \\\\//|[ ] \\\\\n _\\ o/_ _\\- /_ \\/ |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ | |//\n | | :: \\ | | ::: | |====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n6\n /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( O O o o | \\\\//|[ ] \\\\\n _\\ o/_ _\\- /_ \\/ |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ | |//\n | | :: \\ | | ::: | |====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n1\n /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( - - o o | \\\\//|[ ] \\\\\n _\\ o/_ _\\- /_ \\/ |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ | |//\n | | :: \\ | | ::: | |====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n4\n /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( - - | o o \\\\//|[ ] \\\\\n _\\ o/_ _\\ -/_ \\/ |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ | |//\n | | :: \\ | | ::: | |====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n3\n /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( - - | o o \\\\//|[ ] \\\\\n _\\ o/_ _\\ -/_ \\/ |[_] |\\\\\n /"\'() ") /"\'==\'"\\ | |//\n | | \\\\// | | ::: | |====#/\n || | \\/| || | || /|\\ /I\\\n-------------------------------------------------------------------\n\n\n\n2\n /~~\\\n Ugh!!! Ackkkk!!! |<><>|\n /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( - - | o o \\\\//|[ ] \\\\\n _\\ o/_ _\\ -/_ \\/ |[_] |\\\\\n /"\'() ") /"\'==\'"\\ | |//\n | | \\\\// | | ::: | |====#/\n || | \\/| || | || /|\\ /I\\\n-------------------------------------------------------------------\n\n\n\n8\n /~~\\\n Ugh!!! Ackkkk!!! |<><>|\n /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( - - o o | \\\\//|[ ] \\\\\n _\\ o/_ _\\- /_ \\/ |[_] |\\\\\n /"\'() ") /"\'==\'"\\ | |//\n | | \\\\// | | ::: | |====#/\n || | \\/| || | || /|\\ /I\\\n-------------------------------------------------------------------\n\n\n\n5\n /~~\\\n Ugh!!! Ackkkk!!! |<><>|\n /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( - - o o | \\\\//|[ ] \\\\\n _\\ o/_ _\\- /_ \\/ |[_] |\\\\\n /"\'() ") /"\'==\'"\\ | |//\n | | \\\\// | | ::: | |====#/\n || | \\/| || | || /|\\ /I\\\n-------------------------------------------------------------------\n\n\n\n11\n /~~\\\n Ugh!!! Ackkkk!!! |<><>|\n /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( x x o o | \\\\//|[ ] \\\\\n _\\ -/_ _\\- /_ \\/ |[_] |\\\\\n /"\'() ") /"\'==\'"\\ | |//\n | | \\\\// | | ::: | |====#/\n || | \\/| || | || /|\\ /I\\\n-------------------------------------------------------------------\n\n\n\n1\n /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( x x o o | \\\\//|[ ] \\\\\n _\\ -/_ _\\- /_ \\/ |[_] |\\\\\n /"\'() ") /"\'==\'"\\ | |//\n | | \\\\// | | ::: | |====#/\n || | \\/| || | || /|\\ /I\\\n-------------------------------------------------------------------\n\n\n\n23\n I find your lack of /~~\\\n faith disturbing. |<><>|\n /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( x x o o | \\\\//|[ ] \\\\\n _\\ -/_ _\\- /_ \\/ |[_] |\\\\\n /"\'() ") /"\'==\'"\\ | |//\n | | \\\\// | | ::: | |====#/\n || | \\/| || | || /|\\ /I\\\n-------------------------------------------------------------------\n\n\n\n2\n /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( x x o o | \\\\//|[ ] \\\\\n _\\ -/_ _\\- /_ \\/ |[_] |\\\\\n /"\'() ") /"\'==\'"\\ | |//\n | | \\\\// | | ::: | |====#/\n || | \\/| || | || /|\\ /I\\\n-------------------------------------------------------------------\n\n\n\n3\n /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( x x | o o \\\\//|[ ] \\\\\n _\\ -/_ _\\ -/_ \\/ |[_] |\\\\\n /"\'() ") /"\'==\'"\\ | |//\n | | \\\\// | | ::: | |====#/\n || | \\/| || | || /|\\ /I\\\n-------------------------------------------------------------------\n\n\n\n16\n /~~\\\n |<><>|\n /_/\\_\\\n /""\\ Vader, ==== # /\\___/\\\n ( x x release him! | o o \\\\//|[ ] \\\\\n _\\ -/_ _\\ -/_ \\/ |[_] |\\\\\n /"\'() ") /"\'==\'"\\ | |//\n | | \\\\// | | ::: | |====#/\n || | \\/| || | || /|\\ /I\\\n-------------------------------------------------------------------\n\n\n\n7\n /~~\\\n |<><>|\n /_/\\_\\\n /""\\ Vader, ==== # /\\___/\\\n ( o o release him! | o o \\\\//|[ ] \\\\\n _\\ -/_ _\\ -/_ \\/ |[_] |\\\\\n /"\'() ") /"\'==\'"\\ | |//\n | | \\\\// | | ::: | |====#/\n || | \\/| || | || /|\\ /I\\\n-------------------------------------------------------------------\n\n\n\n10\n /~~\\\n |<><>|\n /_/\\_\\\n /""\\ Vader, ==== # /\\___/\\\n ( o o release him! | o o \\\\//|[ ] \\\\\n _\\ -/_ _\\ -/_ \\/ |[_] |\\\\\n /"\'() ") /"\'==\'"\\ | |//\n | | \\\\// | | ::: | |====#/\n || | \\/| || | || /|\\ /I\\\n-------------------------------------------------------------------\n\n\n\n1\n /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( o o | o o \\\\//|[ ] \\\\\n _\\ -/_ _\\ -/_ \\/ |[_] |\\\\\n /"\'() ") /"\'==\'"\\ | |//\n | | \\\\// | | ::: | |====#/\n || | \\/| || | || /|\\ /I\\\n-------------------------------------------------------------------\n\n\n\n4\n /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( o o o o | \\\\//|[ ] \\\\\n _\\ -/_ _\\- /_ \\/ |[_] |\\\\\n /"\'() ") /"\'==\'"\\ | |//\n | | \\\\// | | ::: | |====#/\n || | \\/| || | || /|\\ /I\\\n-------------------------------------------------------------------\n\n\n\n10\n As you wish. /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== # /\\___/\\\n ( o o o o | \\\\//|[ ] \\\\\n _\\ -/_ _\\- /_ \\/ |[_] |\\\\\n /"\'() ") /"\'==\'"\\ | |//\n | | \\\\// | | ::: | |====#/\n || | \\/| || | || /|\\ /I\\\n-------------------------------------------------------------------\n\n\n\n1\n As you wish. /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== /\\___/\\\n ( o o o o | //|[ ] \\\\\n _\\ -/_ _\\- /_ // |[_] |\\\\\n /"\'() ") /"\'==\'"\\ \\\\ | |//\n | | \\\\// | | ::: | \\#|====#/\n || | \\/| || | || /|\\ /I\\\n-------------------------------------------------------------------\n\n\n\n3\n As you wish. /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== /\\___/\\\n ( o o o o | //|[ ] \\\\\n _\\ o/_ _\\- /_ // |[_] |\\\\\n /"\'() ") /"\'==\'"\\ \\\\ | |//\n | | \\\\// | | ::: | \\#|====#/\n || | \\/| || | || /|\\ /I\\\n-------------------------------------------------------------------\n\n\n\n4\n As you wish. /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== /\\___/\\\n ( o o o o | //|[ ] \\\\\n _\\ o/_ _\\- /_ // |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ \\\\ | |//\n | | :: \\ | | ::: | \\#|====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n11\n As you wish. /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== /\\___/\\\n ( o o o o | //|[ ] \\\\\n _\\ -/_ _\\- /_ // |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ \\\\ | |//\n | | :: \\ | | ::: | \\#|====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n6\n /~~\\\n |<><>|\n /_/\\_\\\n /""\\ ==== /\\___/\\\n ( o o o o | //|[ ] \\\\\n _\\ -/_ _\\- /_ // |[_] |\\\\\n /"\'--\'"\\ /"\'==\'"\\ \\\\ | |//\n | | :: \\ | | ::: | \\#|====#/\n || | |\\\\ || | || /|\\ /I\\\n---------------\\()-------------------------------------------------\n\n\n\n13\n\n\n\n\n\n\n\n\n\n\n\n\n\n1\n ==== ==== / / / * \\ ###\n ("o o) ~~o o | | | * | .##\n _\\ -/_ _\\ -/_ | | | * | ####\n / \\ / \\ / \\/ \\ \\ \\ \\__*__/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * \\ ###\n ("o o) ~~o o | | | * | .##\n _\\ -/_ _\\ -/_ | | | * | ####\n / \\ / \\ / \\/ \\ \\ \\ \\__*__/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * \\ ###\n ("o o) ~~o o | | | * | .##\n _\\ -/_ _\\ -/_ | | | * | ####\n / \\ / \\ / \\/ \\ \\ \\ \\__*__/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * \\ ###\n ("o o) ~~o o | | | * | .##\n _\\ -/_ _\\ -/_ | | | * | ####\n / \\ / \\ / \\/ \\ \\ \\ \\___*_/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * \\ ###\n ("o o) o o~~ | | | * | .##\n _\\ -/_ _\\- /_ | | | *| ####\n / \\ / \\ / \\/ \\ \\ \\ \\____*/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / *\\ ###\n ("o o) o o~~ | | | *| .##\n _\\ -/_ _\\- /_ | | | *| ####\n / \\ / \\ / \\/ \\ \\ \\ \\____*/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * ###\n ("o o) o o~~ | | | *| .##\n _\\ -/_ _\\- /_ | | | * ####\n / \\ / \\ / \\/ \\ \\ \\ \\_____* \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * ###\n ("o o) o o~~ | | | * .##\n _\\ -/_ _\\- /_ | | | * ####\n / \\ / \\ / \\/ \\ \\ \\ \\_____* \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ **\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / \\* ###\n ("o o) o o~~ | | | * .##\n _\\ -/_ _\\- /_ | | | * ####\n / \\ / \\ / \\/ \\ \\ \\ \\_____* \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ **\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / \\* ###\n ("o o) o o~~ | | | *| .##\n _\\ -/_ _\\- /_ | | | *| ####\n / \\ / \\ / \\/ \\ \\ \\ \\_____* \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ **\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * ###\n ("o o) o o~~ | | | * | .##\n _\\ -/_ _\\- /_ | | | *| ####\n / \\ / \\ / \\/ \\ \\ \\ \\_____* \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ **\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / *\\ ###\n ("o o) o o~~ | | | * | .##\n _\\ -/_ _\\- /_ | | | * | ####\n / \\ / \\ / \\/ \\ \\ \\ \\____*/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ **\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / *\\ ###\n ("o o) o o~~ | | | * | .##\n _\\ -/_ _\\- /_ | | | * | ####\n / \\ / \\ / \\/ \\ \\ \\ \\____*/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * \\ ###\n ("o o) o o~~ | | | * | .##\n _\\ -/_ _\\- /_ | | | * | ####\n / \\ / \\ / \\/ \\ \\ \\ \\___*_/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * \\ ###\n ("o o) o o~~ | | | * | .##\n _\\ -/_ _\\- /_ | | | * | ####\n / \\ / \\ / \\/ \\ \\ \\ \\___*_/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * \\ ###\n ("o o) o o~~ | | | * | .##\n _\\ -/_ _\\- /_ | | | * | ####\n / \\ / \\ / \\/ \\ \\ \\ \\__*__/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * \\ ###\n ("o o) o o~~ | | | * | .##\n _\\ -/_ _\\- /_ | | | * | ####\n / \\ / \\ / \\/ \\ \\ \\ \\__*__/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * \\ ###\n ("o o) o o~~ | | | * | .##\n _\\ -/_ _\\- /_ | | | * | ####\n / \\ / \\ / \\/ \\ \\ \\ \\__*__/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * \\ ###\n ("o o) o o~~ | | | * | .##\n _\\ -/_ _\\- /_ | | | * | ####\n / \\ / \\ / \\/ \\ \\ \\ \\__*__/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * \\ ###\n ("o o) ~~o o | | | * | .##\n _\\ -/_ _\\ -/_ | | | * | ####\n / \\ / \\ / \\/ \\ \\ \\ \\___*_/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * \\ ###\n ("o o) ~~o o | | | * | .##\n _\\ -/_ _\\ -/_ | | | *| ####\n / \\ / \\ / \\/ \\ \\ \\ \\____*/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / *\\ ###\n ("o o) ~~o o | | | *| .##\n _\\ -/_ _\\ -/_ | | | *| ####\n / \\ / \\ / \\/ \\ \\ \\ \\____*/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / *\\ ###\n ("o o) ~~o o | | | *| .##\n _\\ -/_ _\\ -/_ | | | * ####\n / \\ / \\ / \\/ \\ \\ \\ \\_____* \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * ###\n ("o o) ~~o o | | | *| .##\n _\\ -/_ _\\ -/_ | | | * ####\n / \\ / \\ / \\/ \\ \\ \\ \\_____* \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ **\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / \\* ###\n ("o o) ~~o o | | | *| .##\n _\\ -/_ _\\ -/_ | | | * ####\n / \\ / \\ / \\/ \\ \\ \\ \\_____* \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ **\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / \\* ###\n ("o o) ~~o o | | | *| .##\n _\\ -/_ _\\ -/_ | | | *| ####\n / \\ / \\ / \\/ \\ \\ \\ \\_____* \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ **\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * ###\n ("o o) ~~o o | | | * | .##\n _\\ -/_ _\\ -/_ | | | *| ####\n / \\ / \\ / \\/ \\ \\ \\ \\_____* \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ **\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / *\\ ###\n ("o o) ~~o o | | | * | .##\n _\\ -/_ _\\ -/_ | | | * | ####\n / \\ / \\ / \\/ \\ \\ \\ \\____*/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ **\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * \\ ###\n ("o o) ~~o o | | | * | .##\n _\\ -/_ _\\ -/_ | | | * | ####\n / \\ / \\ / \\/ \\ \\ \\ \\____*/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * \\ ###\n ("o o) ~~o o | | | * | .##\n _\\ -/_ _\\ -/_ | | | * | ####\n / \\ / \\ / \\/ \\ \\ \\ \\___*_/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * \\ ###\n ("o o) ~~o o | | | * | .##\n _\\ -/_ _\\ -/_ | | | * | ####\n / \\ / \\ / \\/ \\ \\ \\ \\___*_/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * \\ ###\n ("o o) ~~o o | | | * | .##\n _\\ -/_ _\\ -/_ | | | * | ####\n / \\ / \\ / \\/ \\ \\ \\ \\__*__/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n1\n ==== ==== / / / * \\ ###\n ("o o) ~~o o | | | * | .##\n _\\ -/_ _\\ -/_ | | | * | ####\n / \\ / \\ / \\/ \\ \\ \\ \\__*__/ \'\'#\n / \\/ \\ //| | |\\\\ | \\ \\ *\n| /| | |\\ \\ || | | | || | |\\ \\ *\n|| | | | \\ \\ || | | | || | | \\ \\ .## _____\n(\' | | | `() (\' |====| \') ~ \\ \\ ####. / \\\n | | | | || | \\ \\ .### | |\n | /| | (_)(_) \\ \\ | ..|\n / || \\ |_||_| \\ \\ \\____##\n /|_|| \\ |_||_| _____\\_\\_____________\n-/_[_]|____\\-----------/__][__\\---------------\\____________________\n7\n\n\n\n\n\n\n\n\n\n\n\n\n\n3\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._= + + |______#_/\n____________\'====_________|_|____ooo__ooo__________________________\n\n29\n\n It looks like the\n Sand People did this.\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._= + + |______#_/\n____________\'====_________|_|____ooo__ooo__________________________\n\n1\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._= + + |______#_/\n____________\'====_________|_|____ooo__ooo__________________________\n\n29\n\n They didn\'t. But we are\n meant to think they did.\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._= + + |______#_/\n____________\'====_________|_|____ooo__ooo__________________________\n\n1\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._= + + |______#_/\n____________\'====_________|_|____ooo__ooo__________________________\n\n28\n\n Only Imperial stormtroopers\n are so precise.\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._= + + |______#_/\n____________\'====_________|_|____ooo__ooo__________________________\n\n1\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._= + + |______#_/\n____________\'====_________|_|____ooo__ooo__________________________\n\n30\n\n If they traced the\n robots here that would\n lead them...\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._= + + |______#_/\n____________\'====_________|_|____ooo__ooo__________________________\n\n15\n\n\n ...home!\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._= + + |______#_/\n____________\'====_________|_|____ooo__ooo__________________________\n\n2\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._= + + |______#_/\n____________\'====_________|_|____ooo__ooo__________________________\n\n1\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._= ++ |______#_/\n____________\'====_________||_____ooo__ooo__________________________\n\n1\n\n Luke! It\'s too dangerous!\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._= + |______#_/\n____________\'====_________|______ooo__ooo__________________________\n\n1\n\n Luke! It\'s too dangerous!\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._= ++ |______#_/\n____________\'====________||______ooo__ooo__________________________\n\n1\n\n Luke! It\'s too dangerous!\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._= + + |______#_/\n____________\'====_______|_|______ooo__ooo__________________________\n\n1\n\n Luke! It\'s too dangerous!\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._= + + |______#_/\n____________\'====______|__|______ooo__ooo__________________________\n\n1\n\n Luke! It\'s too dangerous!\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._= + + |______#_/\n____________\'====_____|___|______ooo__ooo__________________________\n\n1\n\n Luke! It\'s too dangerous!\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._= + + |______#_/\n____________\'====____|____|______ooo__ooo__________________________\n\n1\n\n Luke! It\'s too dangerous!\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._= + + |______#_/\n____________\'====___|_____|______ooo__ooo__________________________\n\n1\n\n Luke! It\'s too dangerous!\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._= + + |______#_/\n____________\'====__|______|______ooo__ooo__________________________\n\n1\n\n Luke! It\'s too dangerous!\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._= + + |______#_/\n____________\'====_|_______|______ooo__ooo__________________________\n\n1\n\n Luke! It\'s too dangerous!\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _._=+ + |______#_/\n____________\'====|________|______ooo__ooo__________________________\n\n16\n\n Luke! It\'s too dangerous!\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _+_= + |______#_/\n____________\'====_________|______ooo__ooo__________________________\n\n1\n\n Luke! It\'s too dangerous!\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _+_= + |______#_/\n___________\'====__________|______ooo__ooo__________________________\n\n1\n\n Luke! It\'s too dangerous!\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _+_= + |______#_/\n__________\'====___________|______ooo__ooo__________________________\n\n1\n\n Luke! It\'s too dangerous!\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _+_= + |______#_/\n_________\'====____________|______ooo__ooo__________________________\n\n1\n\n Luke! It\'s too dangerous!\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _+_= + |______#_/\n________\'====_____________|______ooo__ooo__________________________\n\n1\n\n Luke! It\'s too dangerous!\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _+_= + |______#_/\n______\'====_______________|______ooo__ooo__________________________\n\n1\n\n Luke! It\'s too dangerous!\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _+_= + |______#_/\n____\'====_________________|______ooo__ooo__________________________\n\n1\n\n Luke! It\'s too dangerous!\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _+_= + |______#_/\n__\'====___________________|______ooo__ooo__________________________\n\n1\n\n Luke! It\'s too dangerous!\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n _+_= + |______#_/\n\'====_____________________|______ooo__ooo__________________________\n\n1\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n+_= + |______#_/\n===_______________________|______ooo__ooo__________________________\n\n1\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n= + |______#_/\n=_________________________|______ooo__ooo__________________________\n\n8\n\n\n\n\n\n\n ___________\n | _ =|\n | [_] /\n | # /\n + |______#_/\n__________________________|______ooo__ooo__________________________\n\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n __/ o\\*/o o \\ .||.\n_____________________________________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n __/ o\\*/o o \\ .||.\n_____________________________________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n __/ o\\*/o o \\ .||.\n_____________________________________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n __/ o\\*/o o \\ .||.\n\'____________________________________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n+_ __/ o\\*/o o \\ .||.\n==\'__________________________________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n=_+_ __/ o\\*/o o \\ .||.\n====\'________________________________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n__====\'______________________________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n____====\'____________________________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n______====\'__________________________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n_______====\'_________________________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n________====\'________________________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n_________====\'_______________________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n__________====\'______________________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n___________====\'_____________________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n____________====\'____________________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n_____________====\'___________________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n______________====\'__________________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n_______________====\'_________________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n________________====\'________________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n_________________====\'_______________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n__________________====\'______________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n___________________====\'_____________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n____________________====\'____________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n_____________________====\'___________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n______________________====\'__________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n_______________________====\'_________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n________________________====\'________________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n_________________________====\'_______________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n_________________________====\'_______________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n_________________________====\'_______________|__|__________|__|[]|_\n\n1\n *\n **\n ***\n *****\n *******\n *****\n *****\n ***\n **\n __ * ____ .|\\.\n =_+_ __/ o\\*/o o \\ .||.\n_________________________====\'_______________|__|__________|__|[]|_\n\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n2\n *\n *\n *\n *\n *\n * *\n * *\n * *\n * *\n # # * ___\n ## ## ## / |\n ############# # # / |\n_______####_#######__####_/ |\n2\n *\n *\n *\n *\n *\n * *\n * *\n * *\n * *\n # # * ___\n ## ## ## / |\n ############# # # / |\n_______####_#######__####_/ |\n2\n *\n *\n *\n *\n *\n * *\n * *\n * *\n * *\n # # * ___\n ## ## ## / |\n ############# # # / |\n_______####_#######__####_/ |\n2\n *\n *\n *\n *\n *\n * *\n * *\n * *\n * *\n # # * ___\n ## ## ## / |\n ############# # # / |\n_______####_#######__####_/ |\n2\n *\n *\n *\n *\n *\n * *\n * *\n * *\n * *\n # # * ___\n ## ## ## / |\n ############# # # / |\n_______####_#######__####_/ |\n2\n *\n *\n *\n *\n *\n * *\n * *\n * *\n * *\n # # * ___\n ## ## ## / |\n ############# # # / |\n_______####_#######__####_/ |\n2\n *\n *\n *\n *\n *\n * *\n * *\n * *\n * *\n # # * ___\n ## ## ## / |\n ############# # # / |\n_______####_#######__####_/ |\n2\n *\n *\n *\n *\n *\n * *\n * *\n * *\n * *\n # # * ___\n ## ## ## / |\n ############# # # / |\n_______####_#######__####_/ |\n2\n *\n *\n *\n *\n *\n * *\n * *\n * *\n * *\n # # * ___\n ## ## ## / |\n ############# # # / |\n_______####_#######__####_/ |\n2\n *\n *\n *\n *\n *\n * *\n * *\n * *\n * *\n # # * ___\n ## ## ## / |\n ############# # # / |\n_______####_#######__####_/ |\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n7\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| .\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| . |\n . : : : : : : : . |\n . \\................./ . . |\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . ./\n |...................| . |\n . : : : : : : : . |-\n . \\................./ . . |\n \\ . . : . . / . . \\\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: . _\n . |___________________| . /\n |...................| . | \\\n . : : : : : : : . |-{\n . \\................./ . . | /\n \\ . . : . . / . . \\_\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: . __\n . |___________________| . /\n |...................| . | \\_\n . : : : : : : : . |-{\n . \\................./ . . | /~\n \\ . . : . . / . .\\__\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: . ___\n . |___________________| . /\n |...................| . | \\_/\n . : : : : : : : . |-{ }\n . \\................./ . . | /~\\\n \\ . . : . . / . \\___\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: . ___\n . |___________________| . / \\\n |...................| . | \\_/\n . : : : : : : : . |-{ }-\n . \\................./ . . | /~\\\n \\ . . : . . / . \\___/\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: . ___\n . |___________________| . / \\\n |...................| . | \\_/ |\n . : : : : : : : . |-{ }-|\n . \\................./ . . | /~\\ |\n \\ . . : . . / . \\___/\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: . ___\n . |___________________| . / \\.\n |...................| . | \\_/ |\n . : : : : : : : . |-{ }-|\n . \\................./ . . | /~\\ |\n \\ . . : . . / . \\___/\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: . ___\n . |___________________| . / \\ .\n |...................| . | \\_/ |\n . : : : : : : : . |-{ }-|\n . \\................./ . . | /~\\ |\n \\ . . : . . / . \\___/\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: . ___\n . |___________________| . / \\ .\n |...................| . | \\_/ |\n . : : : : : : : . |-{ }-|\n . \\................./ . . | /~\\ |\n \\ . . : . . / . \\___/.\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: . ___\n . |___________________| . / \\ .\n |...................| . | \\_/ |\n . : : : : : : : .|-{ }-|\n . \\................./ . . | /~\\ |\n \\ . . : . . / . \\___/ .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: . ___\n . |___________________| . / \\ .\n |...................| . | \\_/ |\n . : : : : : : : |-{ }-|\n . \\................./ . . | /~\\ |\n \\ . . : . . / . \\___/ .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: . ___\n . |___________________| . / \\ .\n |...................| . | \\_/ |\n . : : : : : : : |-{ }-|\n . \\................./ . . | /~\\ |\n \\ . . : . . / . \\___/ .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: . ___\n . |___________________| . / \\ .\n |...................| . | \\_/ |\n . : : : : : : : |-{ }-|\n . \\................./ . . | /~\\ |\n \\ . . : . . / . \\___/ .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: . ___\n . |___________________| . / \\ .\n |...................| . | \\_/ |\n . : : : : : : : |-{ }-|\n . \\................./ . . | /~\\ |\n \\ . . : . . / . \\___/ .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: . __\n . |___________________| . / \\ .\n |...................| . |_\\/_|\n . : : : : : : : | /\\ |\n . \\................./ . . \\__/\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: . __\n . |___________________| . / \\ .\n |...................| . |_\\/_|\n . : : : : : : : | /\\ |\n . \\................./ . . \\__/\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . -- .\n |...................| . |\\/|\n . : : : : : : : |/\\| .\n . \\................./ . . --\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . -- .\n |...................| . |\\/|\n . : : : : : : : |/\\| .\n . \\................./ . . --\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| . []\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| . []\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| . "\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| . "\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| . \'\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| .\'\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| \'\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| \'.\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| \' .\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| \' .\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| \' .\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| \' .\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| \' .\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| \' .\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| \' .\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| \' .\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| \' .\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| \' .\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| \' .\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| \' .\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| \' .\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n1\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................|\' .\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n5\n . __---__\n . . .-\'...:...\'-. . .\n / . . : .__ .\\\n . /........./ \\ .\\ . . .\n / : : :| () | :\\ . .\n :...........\\__/....: .\n . |___________________| . .\n |...................| .\n . : : : : : : : .\n . \\................./ . .\n \\ . . : . . / . .\n. . \\._........._./ . . .\n -..___..- . .\n4\n\n\n\n\n\n\n\n\n\n\n\n\n\n5\n / \\ ===,\n | | @o o@)\n | | \\- /\n | | /~~ ~\\\\\n | | / ( ) \\\n | | /_/\\ /\\_|\n | | \\\\ \\ // ||\n | | @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n_________________________|_____________|________/__)(_)____________\n16\n / \\ ===,\n And now your | | @o o@)\n highness... | | \\- /\n | | /~~ ~\\\\\n | | / ( ) \\\n | | /_/\\ /\\_|\n | | \\\\ \\ // ||\n | | @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n_________________________|_____________|________/__)(_)____________\n2\n / \\ ===,\n And now your | | @o o@)\n highness... | | \\- /\n | | /~~ ~\\\\\n | \'| / ( ) \\\n | =| /_/\\ /\\_|\n | \'| \\\\ \\ // ||\n | | @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n_________________________|_____________|________/__)(_)____________\n2\n / \\ ===,\n And now your | | @o o@)\n highness... | | \\- /\n | /| /~~ ~\\\\\n | \'-| / ( ) \\\n | ==| /_/\\ /\\_|\n | \' | \\\\ \\ // ||\n | \\| @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n_________________________|_____________|________/__)(_)____________\n2\n / \\ ===,\n...we will discuss | | @o o@)\n the location of | | \\- /\n your hidden | / | /~~ ~\\\\\n Rebel base. | \'--| / ( ) \\\n | ===| /_/\\ /\\_|\n | \' o| \\\\ \\ // ||\n | \\ | @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n_________________________|_____________|________/__)(_)____________\n2\n / \\ ===,\n...we will discuss | | @o o@)\n the location of | _| \\- /\n your hidden | / | /~~ ~\\\\\n Rebel base. | \'--|| / ( ) \\\n | ====| /_/\\ /\\_|\n | \' o | \\\\ \\ // ||\n | \\ _| @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n_________________________|_____________|________/__)(_)____________\n2\n / \\ ===,\n...we will discuss | | @o o@)\n the location of | __| \\- /\n your hidden | / _| /~~ ~\\\\\n Rebel base. | \'--| | / ( ) \\\n | =====| /_/\\ /\\_|\n | \' o | \\\\ \\ // ||\n | \\ __| @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n_________________________|_____________|________/__)(_)____________\n2\n / \\ ===,\n...we will discuss | | @o o@)\n the location of | __ | \\- /\n your hidden | / __| /~~ ~\\\\\n Rebel base. | \'--| "| / ( ) \\\n | ======| /_/\\ /\\_|\n | \' o || \\\\ \\ // ||\n | \\ __ | @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n_________________________|_____________|________/__)(_)____________\n2\n / \\ ===,\n...we will discuss | | @o o@)\n the location of | __ | \\- /\n your hidden | / __\\| /~~ ~\\\\\n Rebel base. | \'--| ""| / ( ) \\\n | =======| /_/\\ /\\_|\n | \' o |_| \\\\ \\ // ||\n | \\ __ /| @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n_________________________|_____________|________/__)(_)____________\n2\n / \\ ===,\n...we will discuss | | @o o@)\n the location of | __ | \\o /\n your hidden | / __\\ | /~~ ~\\\\\n Rebel base. | \'--| ""\'| / ( ) \\\n | ========| /_/\\ /\\_|\n | \' o |_\'| \\\\ \\ // ||\n | \\ __ / | @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n_________________________|_____________|________/__)(_)____________\n2\n / \\ ===,\n...we will discuss | | @o o@)\n the location of | __ | \\o /\n your hidden | / __\\ | /~~ ~\\\\\n Rebel base. | \'--| ""\' | / ( ) \\\n | ======== | /_/\\ /\\_|\n | \' o |_\'+| \\\\ \\ // ||\n | \\ __ / | @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n_________________________|_____________|________/__)(_)____________\n2\n / \\ ===,\n...we will discuss | | @o o@)\n the location of | __ | \\o /\n your hidden | / __\\ | /~~ ~\\\\\n Rebel base. | \'--| ""\' | / ( ) \\\n | ======== | /_/\\ /\\_|\n | \' o |_\'+=| \\\\ \\ // ||\n | \\ __ / | @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n_________________________|_____________|________/__)(_)____________\n2\n / \\ ===,\n...we will discuss | | @o o@)\n the location of | __ | \\o /\n your hidden | / __\\ | /~~ ~\\\\\n Rebel base. | \'--| ""\' | / ( ) \\\n | ======== | /_/\\ /\\_|\n | \' o |_\'+=-| \\\\ \\ // ||\n | \\ __ / | @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n_________________________|_____________|________/__)(_)____________\n2\n / \\ ===,\n...we will discuss | | @o o@)\n the location of | __ | \\o /\n your hidden | / __\\ | /~~ ~\\\\\n Rebel base. | \'--| ""\' | / ( ) \\\n | ======== | /_/\\ /\\_|\n | \' o |_\'+=- | \\\\ \\ // ||\n | \\ __ / | @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n_________________________|_____________|________/__)(_)____________\n1\n / \\ ===,\n...we will discuss | | @o o@)\n the location of | __ | \\o /\n your hidden | / __\\ | /~~ ~\\\\\n Rebel base. | \'--| ""\' | / ( ) \\\n | ======== | /_/\\ /\\_|\n | \' o |_\'+=* | \\\\ \\ // ||\n | \\ __ / | @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n_________________________|_____________|________/__)(_)____________\n1\n / \\ ===,\n...we will discuss | | @o o@)\n the location of | __ | \\o /\n your hidden | / __\\ | /~~ ~\\\\\n Rebel base. | \'--| ""\' | / ( ) \\\n | ======== * | /_/\\ /\\_|\n | \' o |_\'+***| \\\\ \\ // ||\n | \\ __ / * | @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n_________________________|_____________|________/__)(_)____________\n1\n / \\ ===,\n...we will discuss | | @o o@)\n the location of | __ | \\o /\n your hidden | / __\\ | /~~ ~\\\\\n Rebel base. | \'--| ""\' | / ( ) \\\n | ======== | /_/\\ /\\_|\n | \' o |_\'+=* | \\\\ \\ // ||\n | \\ __ / | @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n_________________________|_____________|________/__)(_)____________\n17\n / \\ ===,\n...we will discuss | | @o o@)\n the location of | __ | \\o /\n your hidden | / __\\ | /~~ ~\\\\\n Rebel base. | \'--| ""\' | / ( ) \\\n | ======== | /_/\\ /\\_|\n | \' o |_\'+=- | \\\\ \\ // ||\n | \\ __ / | @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n_________________________|_____________|________/__)(_)____________\n3\n / \\ ===,\n | | @o o@)\n | __ | \\o /\n | / __\\ | /~~ ~\\\\\n | \'--| ""\' | / ( ) \\\n | ======== | /_/\\ /\\_|\n | \' o |_\'+=- | \\\\ \\ // ||\n | \\ __ / | @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n_________________________|_____________|________/__)(_)____________\n6\n / \\ ===,\n | | @o o@)\n | __ | \\- /\n | / __\\ | /~~ ~\\\\\n | \'--| ""\' | / ( ) \\\n | ======== | /_/\\ /\\_|\n | \' o |_\'+=- | \\\\ \\ // ||\n | \\ __ / | @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n_________________________|_____________|________/__)(_)____________\n15\n\n\n\n\n\n\n\n\n\n\n\n\n\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n + |______#_/ . +\n__________________________|______ooo__ooo_____<^"..|_|_____________\n ~~\'`\n2\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n + |______#_/ . +\n__________________________|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n + |______#_/ . +\n\'_________________________|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n+_ + |______#_/ . +\n==\'_______________________|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n=_+_ + |______#_/ . +\n====\'_____________________|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_+_ + |______#_/ . +\n__====\'___________________|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_+_ + |______#_/ . +\n____====\'_________________|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_+_ + |______#_/ . +\n______====\'_______________|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_+_ + |______#_/ . +\n_______====\'______________|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_+_ + |______#_/ . +\n________====\'_____________|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_+_ + |______#_/ . +\n_________====\'____________|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_+_ + |______#_/ . +\n__________====\'___________|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_+_ + |______#_/ . +\n___________====\'__________|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_+_ + |______#_/ . +\n____________====\'_________|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_+_ + |______#_/ . +\n_____________====\'________|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_+_ + |______#_/ . +\n______________====\'_______|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_+_ + |______#_/ . +\n_______________====\'______|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_+_ + |______#_/ . +\n________________====\'_____|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n2\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_+_ + |______#_/ . +\n________________====\'_____|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'|____|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n2\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'|____|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'_|___|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n2\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'_|___|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n2\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n I want to come with\n you to Alderaan.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n I want to come with\n you to Alderaan.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n I want to come with\n you to Alderaan.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n I want to come with\n you to Alderaan.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n I want to come with\n you to Alderaan.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n I want to come with\n you to Alderaan.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n I want to come with\n you to Alderaan.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n I want to come with\n you to Alderaan.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n I want to come with\n you to Alderaan.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n I want to come with\n you to Alderaan.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n2\n\n There is nothing for\n me here now.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n There is nothing for\n me here now.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n There is nothing for\n me here now.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n There is nothing for\n me here now.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n There is nothing for\n me here now.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n There is nothing for\n me here now.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n There is nothing for\n me here now.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n There is nothing for\n me here now.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n There is nothing for\n me here now.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n There is nothing for\n me here now.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n2\n\n There is nothing for\n me here now.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n2\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n I want to learn the\n ways of the Force...\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n I want to learn the\n ways of the Force...\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n I want to learn the\n ways of the Force...\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n I want to learn the\n ways of the Force...\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n I want to learn the\n ways of the Force...\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n I want to learn the\n ways of the Force...\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n I want to learn the\n ways of the Force...\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n I want to learn the\n ways of the Force...\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n I want to learn the\n ways of the Force...\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n I want to learn the\n ways of the Force...\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n I want to learn the\n ways of the Force...\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n2\n\n ...and become a Jedi\n like my father.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n ...and become a Jedi\n like my father.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n ...and become a Jedi\n like my father.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n ...and become a Jedi\n like my father.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n ...and become a Jedi\n like my father.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n ...and become a Jedi\n like my father.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n ...and become a Jedi\n like my father.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n ...and become a Jedi\n like my father.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n ...and become a Jedi\n like my father.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n ...and become a Jedi\n like my father.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n1\n\n ...and become a Jedi\n like my father.\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n2\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n3\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n2\n\n\n\n\n\n\n ___________\n | _ =| .\n | [_] / .\n | # / .\n =_._ + + |______#_/ . +\n________________====\'__|__|______ooo__ooo_____<^"._|_|_____________\n ~~\'\n6\n\n\n\n\n\n\n\n\n\n\n\n\n\n5\n\n\n\n =_._ + +\n______________====\'___|_|_\n \\\n |\n /\n /\n |\n |\n |\n |\n25\n\n\n\n =_._ + + Mos Eisley Spaceport.\n______________====\'___|_|_\n \\\n |\n /\n /\n |\n |\n |\n |\n1\n\n\n\n =_._ + +\n______________====\'___|_|_\n \\\n |\n /\n /\n |\n |\n |\n |\n36\n\n\n You will never find a\n =_._ + + more wretched hive of\n______________====\'___|_|_ scum and villainy.\n \\\n |\n /\n /\n |\n |\n |\n |\n1\n\n\n\n =_._ + +\n______________====\'___|_|_\n \\\n |\n /\n /\n |\n |\n |\n |\n26\n\n\n\n =_._ + + We must be cautious.\n______________====\'___|_|_\n \\\n |\n /\n /\n |\n |\n |\n |\n4\n\n\n\n =_._ + +\n______________====\'___|_|_\n \\\n |\n /\n /\n |\n |\n |\n |\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n2\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ o o| o o\n\'___/|[]|\\_|___|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n_ |~~| | | o o o o | | O O O O |__ o o| o o\n=\'__/|[]|\\_|___|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n+_ |~~| | | o o o o | | O O O O |__ o o| o o\n==\'_/|[]|\\_|___|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n_+_ |~~| | | o o o o | | O O O O |__ o o| o o\n===\'/|[]|\\_|___|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n=_+_ |~~| | | o o o o | | O O O O |__ o o| o o\n====/|[]|\\_|___|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n =_+_|~~| | | o o o o | | O O O O |__ o o| o o\n_===/|[]|\\_|___|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n =_+|~~| | | o o o o | | O O O O |__ o o| o o\n__==/|[]|\\_|___|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n =_|~~| | | o o o o | | O O O O |__ o o| o o\n___=/|[]|\\_|___|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n =|~~| | | o o o o | | O O O O |__ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~|_ | | o o o o | | O O O O |__ o o| o o\n____/|[]|\\\'|___|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~|+_| | o o o o | | O O O O |__ o o| o o\n____/|[]|\\=\'___|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~|_+_ | o o o o | | O O O O |__ o o| o o\n____/|[]|\\==\'__|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~|=_+_ | o o o o | | O O O O |__ o o| o o\n____/|[]|\\===\'_|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| =_+_ | o o o o | | O O O O |__ o o| o o\n____/|[]|\\====\'|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| =_+_| o o o o | | O O O O |__ o o| o o\n____/|[]|\\_====|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| |=_+| o o o o | | O O O O |__ o o| o o\n____/|[]|\\_|===|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | =_| o o o o | | O O O O |__ o o| o o\n____/|[]|\\_|_==|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | =| o o o o | | O O O O |__ o o| o o\n____/|[]|\\_|__=|_________|_____|___________|__|____________|_||____\n7\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ o o| o o\n____/|[]|\\_|___|_________|\'____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o |_ | O O O O |__ o o| o o\n____/|[]|\\_|___|_________|=\'___|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o |+_ | O O O O |__ o o| o o\n____/|[]|\\_|___|_________|==\'__|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o |_+_ | O O O O |__ o o| o o\n____/|[]|\\_|___|_________|===\'_|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o |=_+_ | O O O O |__ o o| o o\n____/|[]|\\_|___|_________|====\'|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | =_+_| O O O O |__ o o| o o\n____/|[]|\\_|___|_________|_====|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | =_+| O O O O |__ o o| o o\n____/|[]|\\_|___|_________|__===|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | =_| O O O O |__ o o| o o\n____/|[]|\\_|___|_________|___==|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | =| O O O O |__ o o| o o\n____/|[]|\\_|___|_________|____=|___________|__|____________|_||____\n12\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|____________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|\'___________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |=_+_ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|=\'__________|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |_=_+_ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|==\'_________|_||____\n2\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__=_+_ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|===\'________|_||____\n2\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|====\'_______|_||____\n2\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|_====\'______|_||____\n2\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|__====\'_____|_||____\n7\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|___====\'____|_||____\n25\n\n\n Let me see your\n identification.\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|___====\'____|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|___====\'____|_||____\n26\n\n\n\n\n\n You don\'t need to\n see his identification.\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|___====\'____|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|___====\'____|_||____\n25\n\n\n We don\'t need to see his\n identification.\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|___====\'____|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|___====\'____|_||____\n25\n\n\n\n\n\n These aren\'t the\n droids you\'re looking for.\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|___====\'____|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|___====\'____|_||____\n25\n\n\n These aren\'t the droids\n we\'re looking for.\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|___====\'____|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|___====\'____|_||____\n26\n\n\n\n\n\n Move along.\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|___====\'____|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|___====\'____|_||____\n25\n\n\n Move along! Move along!\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ o o| o o\n____/|[]|\\_|___|_________|_____|___________|__|___====\'____|_||____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ o | o o\n____/|[]|\\_|___|_________|_____|___________|__|___====\'_____|_|____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ o| o o\n____/|[]|\\_|___|_________|_____|___________|__|___====\'______||____\n2\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ | o o\n____/|[]|\\_|___|_________|_____|___________|__|___====\'_______|____\n2\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ | o o\n____/|[]|\\_|___|_________|_____|___________|__|____====\'______|____\n2\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ | o o\n____/|[]|\\_|___|_________|_____|___________|__|_____====\'_____|____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ | o o\n____/|[]|\\_|___|_________|_____|___________|__|______====\'____|____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ | o o\n____/|[]|\\_|___|_________|_____|___________|__|_______====\'___|____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ | o o\n____/|[]|\\_|___|_________|_____|___________|__|________====\'__|____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ | o o\n____/|[]|\\_|___|_________|_____|___________|__|_________====\'_|____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_ | o o\n____/|[]|\\_|___|_________|_____|___________|__|__________====\'|____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+_| o o\n____/|[]|\\_|___|_________|_____|___________|__|___________====|____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_+| o o\n____/|[]|\\_|___|_________|_____|___________|__|____________===|____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =_| o o\n____/|[]|\\_|___|_________|_____|___________|__|_____________==|____\n1\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ =| o o\n____/|[]|\\_|___|_________|_____|___________|__|______________=|____\n5\n\n\n\n\n\n\n\n\n\n { ........ ....... ....\n | | \\.. ./ \\. |\n |~~| | | o o o o | | O O O O |__ | o o\n____/|[]|\\_|___|_________|_____|___________|__|_______________|____\n7\n\n\n\n\n\n\n\n\n\n\n\n\n\n1\n ==== ====\n ~~o o (o o")\n _\\ -/_ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | || | /| | |\\ |\n || | | | || || | | | ||\n (\' |====I \') ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n29\n ==== ====\nI can\'t understand ~~o o (o o")\n how we got by _\\ -/_ _\\- /_\n those troops. / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | || | /| | |\\ |\n || | | | || || | | | ||\n (\' |====I \') ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n2\n ==== ====\n ~~o o (o o")\n _\\ -/_ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | || | /| | |\\ |\n || | | | || || | | | ||\n (\' |====I \') ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n8\n ==== ====\n ~~o o (o o") The Force can\n _\\ -/_ _\\- /_ have a strong\n / \\ / \\ / \\ / \\ influence...\n //| | |\\\\ / \\/ \\\n || | | | || | /| | |\\ |\n || | | | || || | | | ||\n (\' |====I \') ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n17\n ==== ====\n ~~o o (o o") The Force can\n _\\ -/_ _\\- /_ have a strong\n / \\ / \\ / \\ / \\ influence...\n //| | |\\\\ / \\/ \\\n \\\\| | | || | /| | |\\ |\n \\\\ | | || || | | | ||\n )====I \') ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n19\n ==== ====\n ~~o o (o o") ...on the\n _\\ -/_ _\\- /_ weak minded.\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n \\\\| | | || | /| | |\\ |\n \\\\ | | || || | | | ||\n )====I \') ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n7\n ==== ====\n ~~o o (o o") ...on the\n _\\ -/_ _\\- /_ weak minded.\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | || | /| | |\\ |\n || | | | || || | | | ||\n (\' |====I \') ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n4\n ==== ====\n ~~o o (o o")\n _\\ -/_ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | || | /| | |\\ |\n || | | | || || | | | ||\n (\' |====I \') ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n29\n ==== ====\n Do you really ~~o o (o o")\n think we\'re _\\ -/_ _\\- /_\n going to find... / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | || | /| | |\\ |\n || | | | || || | | | ||\n (\' |====I \') ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n8\n ==== ====\n ...a pilot here ~~o o (o o")\n to take us to _\\ -/_ _\\- /_\n Alderaan. / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | || | /| | |\\ |\n || | | | || || | | | ||\n (\' |====I \') ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n1\n ==== ====\n ...a pilot here ~~o o (o o")\n to take us to _\\ -/_ _\\- /_\n Alderaan. / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n \\\\| | | || | /| | |\\ |\n \\\\ | | || || | | | ||\n \')===I \') ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n8\n ==== ====\n ...a pilot here ~~o o (o o")\n to take us to _\\ -/_ _\\- /_\n Alderaan. / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n \\\\| | | \\\\ | /| | |\\ |\n \\\\ | | \\\\ || | | | ||\n \')===I \') ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n20\n ==== ====\n ...a pilot here ~~o o ("o o)\n to take us to _\\ -/_ _\\ -/_\n Alderaan. / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n \\\\| | | \\\\ | /| | |\\ |\n \\\\ | | \\\\ || | | | ||\n \')===I \') ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n3\n ==== ====\n ~~o o ("o o)\n _\\ -/_ _\\ -/_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n \\\\| | | \\\\ | /| | |\\ |\n \\\\ | | \\\\ || | | | ||\n \')===I \') ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n1\n ==== ====\n ~~o o ("o o)\n _\\ -/_ _\\ -/_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n \\\\| | |// | /| | |\\ |\n \\\\ | // || | | | ||\n \')===) ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n32\n ==== ====\n ~~o o ("o o) Most of the best\n _\\ -/_ _\\ -/_ freighter pilots\n / \\ / \\ / \\ / \\ can be found here.\n //| | |\\\\ / \\/ \\\n \\\\| | |// | /| | |\\ |\n \\\\ | // || | | | ||\n \')===) ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n6\n ==== ====\n ~~o o (o o") Most of the best\n _\\ -/_ _\\- /_ freighter pilots\n / \\ / \\ / \\ / \\ can be found here.\n //| | |\\\\ / \\/ \\\n \\\\| | |// | /| | |\\ |\n \\\\ | // || | | | ||\n \')===) ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n1\n ==== ====\n ~~o o (o o")\n _\\ -/_ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n \\\\| | |// | /| | |\\ |\n \\\\ | // || | | | ||\n \')===) ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n31\n ==== ====\n ~~o o (o o") Only watch your\n _\\ -/_ _\\- /_ step.\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n \\\\| | |// | /| | |\\ |\n \\\\ | // || | | | ||\n \')===) ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n34\n ==== ====\n ~~o o (o o") This place can\n _\\ -/_ _\\- /_ be a little rough.\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n \\\\| | |// | /| | |\\ |\n \\\\ | // || | | | ||\n \')===) ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n4\n ==== ====\n ~~o o (o o")\n _\\ -/_ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n \\\\| | |// | /| | |\\ |\n \\\\ | // || | | | ||\n \')===) ( | | | `)\n | || I | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n____________________/__][__\\________/____|[_]_\\____________________\n4\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n / _\\ /\\_/\\\n | (__) { . . }\n \\ / | |\n /-===-\\ _\\!^!/_\n == // | |\\\\ / === \\\n || \\\\ | | \\\\ //| | | ||\n.---------------. \\\\ | | \\\\ .--//---|_|------.\n\'-. .-\' =\\)=== () \'- {} .-\'\n | | | || | | |\n | | ( )| ) | |\n | | | || | | |\n | | | || | | |\n__|___________|______[_][__]______|_____________|__________________\n1\n / _\\ /\\_/\\\n | (__) { . . }\n \\ / | |\n /-===-\\ _\\!^!/_\n == // | |\\\\ / === \\\n {\\---/} || \\\\ | | \\\\ //| | | ||\n.---------------. \\\\ | | \\\\ .--//---|_|------.\n\'-. .-\' =\\)=== () \'- {} .-\'\n | | | || | | |\n | | ( )| ) | |\n | | | || | | |\n | | | || | | |\n__|___________|______[_][__]______|_____________|__________________\n1\n / _\\ /\\_/\\\n | (__) { . . }\n \\ / | |\n /-===-\\ _\\!^!/_\n {\\---/} == // | |\\\\ / === \\\n {<><> } || \\\\ | | \\\\ //| | | ||\n.---------------. \\\\ | | \\\\ .--//---|_|------.\n\'-. .-\' =\\)=== () \'- {} .-\'\n | | | || | | |\n | | ( )| ) | |\n | | | || | | |\n | | | || | | |\n__|___________|______[_][__]______|_____________|__________________\n1\n / _\\ /\\_/\\\n | (__) { . . }\n \\ / | |\n {\\---/} /-===-\\ _\\!^!/_\n {<><> } == // | |\\\\ / === \\\n \\ - / || \\\\ | | \\\\ //| | | ||\n.---------------. \\\\ | | \\\\ .--//---|_|------.\n\'-. .-\' =\\)=== () \'- {} .-\'\n | | | || | | |\n | | ( )| ) | |\n | | | || | | |\n | | | || | | |\n__|___________|______[_][__]______|_____________|__________________\n7\n / _\\ /\\_/\\\n | (__) { . . }\n {\\---/} \\ / | |\n {<><> } /-===-\\ _\\!^!/_\n \\ - / == // | |\\\\ / === \\\n | | || \\\\ | | \\\\ //| | | ||\n.---------------. \\\\ | | \\\\ .--//---|_|------.\n\'-. .-\' =\\)=== () \'- {} .-\'\n | | | || | | |\n | | ( )| ) | |\n | | | || | | |\n | | | || | | |\n__|___________|______[_][__]______|_____________|__________________\n1\n / _\\ /\\_/\\\n | (__) { }\n {\\---/} \\ / | |\n {<><> } /-===-\\ _\\!^!/_\n \\ - / == // | |\\\\ / === \\\n | | || \\\\ | | \\\\ //| | | ||\n.---------------. \\\\ | | \\\\ .--//---|_|------.\n\'-. .-\' =\\)=== () \'- {} .-\'\n | | | || | | |\n | | ( )| ) | |\n | | | || | | |\n | | | || | | |\n__|___________|______[_][__]______|_____________|__________________\n2\n / _\\ /\\_/\\\n | (__) { . . }\n {\\---/} \\ / | |\n {<><> } /-===-\\ _\\!^!/_\n \\ - / == // | |\\\\ / === \\\n | | || \\\\ | | \\\\ //| | | ||\n.---------------. \\\\ | | \\\\ .--//---|_|------.\n\'-. .-\' =\\)=== () \'- {} .-\'\n | | | || | | |\n | | ( )| ) | |\n | | | || | | |\n | | | || | | |\n__|___________|______[_][__]______|_____________|__________________\n6\n / _\\ /\\_/\\\n | (__) { . . }\n {\\---/} \\ / | |\n { <><>} /-===-\\ _\\!^!/_\n \\ - / == // | |\\\\ / === \\\n | | || \\\\ | | \\\\ //| | | ||\n.---------------. \\\\ | | \\\\ .--//---|_|------.\n\'-. .-\' =\\)=== () \'- {} .-\'\n | | | || | | |\n | | ( )| ) | |\n | | | || | | |\n | | | || | | |\n__|___________|______[_][__]______|_____________|__________________\n2\n / _\\ /\\_/\\\n | (__) { . . }\n {\\---/} \\ / | |\n { <><>} /-===-\\ _\\!^!/_\n \\ - / == // | |\\\\ / === \\\n | | || \\\\ | | \\\\ //| | | ||\n---------------. \\\\ | | \\\\ .--//---|_|------.\n-. .-\' =\\)=== () \'- {} .-\'\n | | | || | | |\n | | ( )| ) | |\n | | | || | | |\n | | | || | | |\n_|___________|______[_][__]______|_____________|___________________\n2\n / _\\ /\\_/\\\n | (__) { . . }\n {\\---/} \\ / | |\n { <><>} /-===-\\ _\\!^!/_\n \\ - / == // | |\\\\ / === \\\n | | || \\\\ | | \\\\ //| | | ||\n--------------. \\\\ | | \\\\ .--//---|_|------.\n. .-\' =\\)=== () \'- {} .-\'\n| | | || | | |\n| | ( )| ) | |\n| | | || | | |\n| | | || | | |\n|___________|______[_][__]______|_____________|___________________/\n2\n / _\\ /\\_/\\\n | (__) { . . }\n {\\---/} \\ / | |\n { <><>} /-===-\\ _\\!^!/_\n \\ - / == // | |\\\\ / === \\\n | | || \\\\ | | \\\\ //| | | ||\n-------------. \\\\ | | \\\\ .--//---|_|------. (\n .-\' =\\)=== () \'- {} .-\'\n | | || | | |\n | ( )| ) | | (\n | | || | | | |\n | | || | | | |\n___________|______[_][__]______|_____________|___________________/_\n2\n / _\\ /\\_/\\\n | (__) { . . }\n{\\---/} \\ / | |\n{ <><>} /-===-\\ _\\!^!/_\n \\ - / == // | |\\\\ / === \\\n | | || \\\\ | | \\\\ //| | | || /\n------------. \\\\ | | \\\\ .--//---|_|------. (\n .-\' =\\)=== () \'- {} .-\' \\\n | | || | | | -\n | ( )| ) | | (\n | | || | | | |_\n | | || | | | |\n__________|______[_][__]______|_____________|___________________/__\n2\n / _\\ /\\_/\\\n | (__) { . . }\n\\---/} \\ / | |\n<><> } /-===-\\ _\\!^!/_\n\\ - / == // | |\\\\ / === \\ _\n | | || \\\\ | | \\\\ //| | | || //\n-----------. \\\\ | | \\\\ .--//---|_|------. (\n .-\' =\\)=== () \'- {} .-\' \\\n | | || | | | -=\n | ( )| ) | | (\n | | || | | | |__\n | | || | | | |\n_________|______[_][__]______|_____________|___________________/___\n2\n / _\\ /\\_/\\\n | (__) { . . }\n---/} \\ / | |\n><> } /-===-\\ _\\!^!/_\n - / == // | |\\\\ / === \\ __\n| | || \\\\ | |// //| | | || //\\\n----------. \\\\ | // .--//---|_|------. (\n .-\' =\\)==) \'- {} .-\' \\\n | | || | | | -==\n | ( )| ) | | ( _\n | | || | | | |___\n | | || | | | |\n________|______[_][__]______|_____________|___________________/____\n2\n / _\\ /\\_/\\\n | (__) { }\n--/} \\ / | |\n<> } /-===-\\ _\\!^!/_\n- / == // | |\\\\ / === \\ __\n | || \\\\ | |// //| | | || //\\\\\n---------. \\\\ | // .--//---|_|------. ( O\n .-\' =\\)==) \'- {} .-\' \\ /\n | | || | | | -==-\n | ( )| ) | | ( __\n | | || | | | |____\n | | || | | | |\n_______|______[_][__]______|_____________|___________________/_____\n2\n / __\\ /\\_/\\\n | (___) { . . }\n-/} \\ / | |\n> } /-===-\\ _\\!^!/_\n / == // | |\\\\ / === \\ __\n| || \\\\ | |// //| | | || //\\\\\n--------. \\\\ | // .--//---|_|------. ( O!\n .-\' =\\)==) \'- {} .-\' \\ /\'\n | | || | | | -==-/\n | ( )| ) | | ( __/\n | | || | | | |____|\n | | || | | | | |\n______|______[_][__]______|_____________|___________________/______\n2\n /___\\ /\\_/\\\n |(___)| { . . }\n/} \\ / | |\n } /-===-\\ _\\!^!/_\n/ == // | |\\\\ / === \\ __\n || \\\\ | |// //| | | || //\\\\\n-------. \\\\ | // .--//---|_|------. ( O!\n .-\' =\\)==) \'- {} .-\' \\ /\'/\n | | || | | | -==-//\n | ( )| ) | | ( __/\n | | || | | | |____|\n | | || | | | | |\n_____|______[_][__]______|_____________|___________________/______\\\n2\n /___\\ /\\_/\\\n |(___)| { . . }\n} \\ / | |\n} /-===-\\ _\\!^!/_\n == // | |\\\\ ( === \\ __\n || \\\\ | |// \\\\/{ } || //\\\\\n------. \\\\ | // .-----\\/|_|------. ( O!\n .-\' =\\)==) \'- .-\' \\ /\'/(\n | | || | | | -==-//\n | ( )| ) | | ( __/\n | | || | | | |____|\n | | || | | | | |\n____|______[_][__]______|_____________|___________________/______\\_\n2\n /___\\ /\\_/\\\n |(___)| { . . }\n \\ / | |\n /-===-\\ _\\===/_\n == // | |\\\\ ( { } \\ __\n || \\\\ | |// \\\\//_| || //\\\\\n-----. \\\\ | // .-----\\/---------. ( O!\n .-\' =\\)==) \'- .-\' \\ /\'/()\n | | || | | | -==-//\n | ( )| ) | | ( __/\n | | || | | | |____|\n | | || | | | | |\n___|______[_][__]______|_____________|___________________/______\\__\n2\n /___\\ /\\_/\\\n |(___)| { . . }\n \\ / | |\n /-===-\\ _\\===/_\n== // | |\\\\ ( { } \\ __\n|| \\\\ | |// \\\\//_| || //\\\\\n----. \\\\ | // .-----\\/---------. ( O! .\n .-\' =\\)==) \'- .-\' \\ /\'/()\'\n | | || | | | -==-//\n | ( )| ) | | ( __/\n | | || | | | |____|\n | | || | | | | |\n__|______[_][__]______|_____________|___________________/______\\___\n2\n / __\\ /\\_/\\\n | (___| { }\n \\ / | |\n /-===-\\ _\\===/_\n= // | |\\\\ ( { } \\ __\n| \\\\ | |// \\\\//_| || //\\\\\n---. \\\\ | // .-----\\/---------. ( O! .-\n .-\' =\\)==) \'- .-\' \\ /\'/()\'-\n | | || | | | -==-// |\n | ( )| ) | | ( __/ |\n | | || | | | |____| |\n | | || | | | | | |\n_|______[_][__]______|_____________|___________________/______\\___|\n2\n / _\\ /\\_/\\\n | (__| { . . }\n \\ / | |\n /-===-\\ _\\===/_\n // | |\\\\ ( { } \\ __\n \\\\ | |// \\\\//_| || //\\\\\n--. \\\\ | // .-----\\/---------. ( O! .--\n.-\' =\\)==) \'- .-\' \\ /\'/()\'--\n| | || | | | -==-// |\n| ( )| ) | | ( __/ |\n| | || | | | |____| |\n| | || | | | | | |\n|______[_][__]______|_____________|___________________/______\\___|_\n2\n / _\\ /\\_/\\\n | (__| { . . }\n \\ / | |\n /-===-\\ _\\!^!/_\n // | |\\\\ ( === \\ __\n \\\\ | |// \\\\/{ } || //\\\\\n-. \\\\ | // .-----\\/|_|------. ( O! .---\n-\' =\\)==) \'- .-\' \\ /\'/()\'---\n | || | | | -==-// |\n ( )| ) | | ( __/ |\n | || | | | |____| |\n | || | | | | | |\n______[_][__]______|_____________|___________________/______\\___|__\n2\n / _\\ /\\_/\\\n | (__| { . . }\n \\ / | |\n /-===-\\ _\\!^!/_\n // | |\\\\ ( === \\ __\n \\\\ | |// \\\\/{ } || //\\\\\n. \\\\ | // .-----\\/|_|------. ( O! .----\n\' =\\)==) \'- .-\' \\ /\'/()\'----\n | || | | | -==-// |\n ( )| ) | | ( __/ |\n | || | | | |____| |\n | || | | | | | |\n_____[_][__]______|_____________|___________________/______\\___|___\n2\n / _\\ /\\_/\\\n | (__| { . . }\n \\ / | |\n /-===-\\ _\\!^!/_\n // | |\\\\ ( === \\ __\n \\\\ | |// \\\\ | | || //\\\\\n \\\\ | // .-----\\\\|_|------. ( O! .-----\n =\\)==) \'- \\{} .-\' \\ /\'/()\'-----\n | || | | | -==-// |\n ( )| ) | | ( __/ |\n | || | | | |____| |\n | || | | | | | |\n____[_][__]______|_____________|___________________/______\\___|____\n1\n / _\\ /\\_/\\\n | (__| { . . }\n \\ / | |\n /-===-\\ _\\!^!/_\n // | |\\\\ ( === \\ __ =\n \\\\ | |// \\\\ | | || //\\\\ (\n \\\\ | // .-----\\\\|_|------. ( O! .------\n =\\)==) \'- \\{} .-\' \\ /\'/()\'------\n | || | | | -==-// |\n ( )| ) | | ( __/ |\n | || | | | |____| |\n | || | | | | | |\n___[_][__]______|_____________|___________________/______\\___|_____\n1\n / _\\ /\\_/\\\n | (__| { . . }\n \\ / | |\n /-===-\\ _\\!^!/_\n // | |\\\\ ( === \\ __ ==\n \\\\ | |// \\\\ | | || //\\\\ (|\n \\\\ | // .-----\\\\|_|------. ( O! .------\n =\\)==) \'- \\{} .-\' \\ /\'/()\'------\n | || | | | -==-// |\n ( )| ) | | ( __/ |\n | || | | | |____| |\n | || | | | | | |\n___[_][__]______|_____________|___________________/______\\___|_____\n1\n / _\\ /\\_/\\\n | (__| { . . }\n \\ / | |\n /-===-\\ _\\!^!/_\n // | |\\\\ ( === \\ __ ==/\n \\\\ | |// \\\\ | | || //\\\\ (|/\n \\\\ | // .-----\\\\|_|------. ( O! .------\n =\\)==) \'- \\{} .-\' \\ /\'/()\'------\n | || | | | -==-// |\n ( )| ) | | ( __/ |\n | || | | | |____| |\n | || | | | | | |\n___[_][__]______|_____________|___________________/______\\___|_____\n1\n / _\\ /\\_/\\\n | (__| { }\n \\ / | |\n /-===-\\ _\\!^!/_ /\n // | |\\\\ ( === \\ __ ==//\n \\\\ | |// \\\\ | | || //\\\\ (|/\n \\\\ | // .-----\\\\|_|------. ( O! .------\n =\\)==) \'- \\{} .-\' \\ /\'/()\'------\n | || | | | -==-// |\n ( )| ) | | ( __/ |\n | || | | | |____| |\n | || | | | | | |\n___[_][__]______|_____________|___________________/______\\___|_____\n1\n / _\\ /\\_/\\\n | (__| { . . }\n \\ / | | /\n /-===-\\ _\\!^!/_ //\n // | |\\\\ ( === \\ __ ==//\n \\\\ | |// \\\\ | | || //\\\\ (|/\n \\\\ | // .-----\\\\|_|------. ( O! .------\n =\\)==) \'- \\{} .-\' \\ /\'/()\'------\n | || | | | -==-// |\n ( )| ) | | ( __/ |\n | || | | | |____| |\n | || | | | | | |\n___[_][__]______|_____________|___________________/______\\___|_____\n1\n / _\\ /\\_/\\\n | (__| { . . }\n \\ / | |\n /-===-\\ _\\!^!/_ /\n // | |\\\\ ( === \\ __ == //\n \\\\ | |// \\\\ | | || //\\\\ ||)/\n \\\\ | // .-----\\\\|_|------. ( O! .------\n =\\)==) \'- \\{} .-\' \\ /\'/()\'------\n | || | | | -==-// |\n ( )| ) | | ( __/ |\n | || | | | |____| |\n | || | | | | | |\n___[_][__]______|_____________|___________________/______\\___|_____\n1\n / _\\ /\\_/\\\n | (__| { . . }\n \\ / | |\n /-===-\\ _\\!^!/_\n // | |\\\\ ( === \\ __ == /\n \\\\ | |// \\\\ | | || //\\\\ ||()/\n \\\\ | // .-----\\\\|_|------. ( O! .------\n =\\)==) \'- \\{} .-\' \\ /\'/()\'------\n | || | | | -==-// |\n ( )| ) | | ( __/ |\n | || | | | |____| |\n | || | | | | | |\n___[_][__]______|_____________|___________________/______\\___|_____\n1\n / _\\ /\\_/\\\n | (__| { . . }\n \\ / | |\n /-===-\\ _\\!^!/_\n // | |\\\\ ( === \\ __ ==\n \\\\ | |// \\\\ | | || //\\\\ || ()\n \\\\ | // .-----\\\\|_|------. ( O! .------\n =\\)==) \'- \\{} .-\' \\ /\'/()\'------\n | || | | | -==-// |\n ( )| ) | | ( __/ |\n | || | | | |____| |\n | || | | | | | |\n___[_][__]______|_____________|___________________/______\\___|_____\n1\n / _\\ /\\_/\\\n | (__| { . . }\n \\ / | |\n /-===-\\ _\\!^!/_\n // | |\\\\ ( === \\ __ ==\n \\\\ | |// \\\\ | | || //\\\\ || (\n \\\\ | // .-----\\\\|_|------. ( O! .------\n =\\)==) \'- \\{} .-\' \\ /\'/()\'------\n | || | | | -==-// |\n ( )| ) | | ( __/ |\n | || | | | |____| |\n | || | | | | | |\n___[_][__]______|_____________|___________________/______\\___|_____\n4\n / _\\ /\\_/\\\n | (__| { . . }\n \\ / | |\n /-===-\\ _\\!^!/_\n // | |\\\\ ( === \\ __ ==\n \\\\ | |// \\\\ | | || //\\\\ ||\n \\\\ | // .-----\\\\|_|------. ( O! .------\n =\\)==) \'- \\{} .-\' \\ /\'/()\'------\n | || | | | -==-// |\n ( )| ) | | ( __/ |\n | || | | | |____| |\n | || | | | | | |\n___[_][__]______|_____________|___________________/______\\___|_____\n1\n\n\n\n\n\n\n\n\n\n\n\n\n\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | |()___()| \\(I)/|\n ===>__/ (:::::::) ==I===\n | || | .=======. | I| |\n | || | |_|| ||_| | || |\n |_||_| [ ]| |[ ] |_||_|\n___________[_][__\\__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | ()____()| \\(I)/|\n ===>__/ (:::::::) ==I===\n | || | .=======. | I| |\n | || | |_|| ||_| | || |\n |_||_| [ ]| |[ ] |_||_|\n___________[_][__\\__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | ()____()| |\\(I)/\n ===>__/ (:::::::) ===I==\n | || | .=======. | |I |\n | || | |_|| ||_| | || |\n |_||_|_ [ ]| |[ ] |_||_|\n___________[_][__/__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | |()___()| |\\(I)/\n ===>__/ (:::::::) ===I==\n | || | .=======. | |I |\n | || | |_|| ||_| | || |\n |_||_|_ [ ]| |[ ] |_||_|\n___________[_][__/__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | |()___()| \\(I)/|\n ===>__/ (:::::::) ==I===\n | || | .=======. | I| |\n | || | |_|| ||_| | || |\n |_||_| [ ]| |[ ] |_||_|\n___________[_][__\\__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | |()____() \\(I)/|\n ===>__/ (:::::::) ==I===\n | || | .=======. | I| |\n | || | |_|| ||_| | || |\n |_||_| [ ]| |[ ] |_||_|\n___________[_][__\\__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | |()____() |\\(I)/\n ===>__/ (:::::::) ===I==\n | || | .=======. | |I |\n | || | |_|| ||_| | || |\n |_||_|_ [ ]| |[ ] |_||_|\n___________[_][__/__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | |()___()| |\\(I)/\n ===>__/ (:::::::) ===I==\n | || | .=======. | |I |\n | || | |_|| ||_| | || |\n |_||_|_ [ ]| |[ ] |_||_|\n___________[_][__/__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | |()___()| \\(I)/|\n ===>__/ (:::::::) ==I===\n | || | .=======. | I| |\n | || | |_|| ||_| | || |\n |_||_| [ ]| |[ ] |_||_|\n___________[_][__\\__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | ()____()| \\(I)/|\n ===>__/ (:::::::) ==I===\n | || | .=======. | I| |\n | || | |_|| ||_| | || |\n |_||_| [ ]| |[ ] |_||_|\n___________[_][__\\__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | ()____()| |\\(I)/\n ===>__/ (:::::::) ===I==\n | || | .=======. | |I |\n | || | |_|| ||_| | || |\n |_||_|_ [ ]| |[ ] |_||_|\n___________[_][__/__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | |()___()| |\\(I)/\n ===>__/ (:::::::) ===I==\n | || | .=======. | |I |\n | || | |_|| ||_| | || |\n |_||_|_ [ ]| |[ ] |_||_|\n___________[_][__/__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | |()___()| \\(I)/|\n ===>__/ (:::::::) ==I===\n | || | .=======. | I| |\n | || | |_|| ||_| | || |\n |_||_| [ ]| |[ ] |_||_|\n___________[_][__\\__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | |()____() \\(I)/|\n ===>__/ (:::::::) ==I===\n | || | .=======. | I| |\n | || | |_|| ||_| | || |\n |_||_| [ ]| |[ ] |_||_|\n___________[_][__\\__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | |()____() |\\(I)/\n ===>__/ (:::::::) ===I==\n | || | .=======. | |I |\n | || | |_|| ||_| | || |\n |_||_|_ [ ]| |[ ] |_||_|\n___________[_][__/__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | |()___()| |\\(I)/\n ===>__/ (:::::::) ===I==\n | || | .=======. | |I |\n | || | |_|| ||_| | || |\n |_||_|_ [ ]| |[ ] |_||_|\n___________[_][__/__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | |()___()| \\(I)/|\n ===>__/ (:::::::) ==I===\n | || | .=======. | I| |\n | || | |_|| ||_| | || |\n |_||_| [ ]| |[ ] |_||_|\n___________[_][__\\__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | ()____()| \\(I)/|\n ===>__/ (:::::::) ==I===\n | || | .=======. | I| |\n | || | |_|| ||_| | || |\n |_||_| [ ]| |[ ] |_||_|\n___________[_][__\\__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | ()____()| |\\(I)/\n ===>__/ (:::::::) ===I==\n | || | .=======. | |I |\n | || | |_|| ||_| | || |\n |_||_|_ [ ]| |[ ] |_||_|\n___________[_][__/__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | |()___()| |\\(I)/\n ===>__/ (:::::::) ===I==\n | || | .=======. | |I |\n | || | |_|| ||_| | || |\n |_||_|_ [ ]| |[ ] |_||_|\n___________[_][__/__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | |()___()| \\(I)/|\n ===>__/ (:::::::) ==I===\n | || | .=======. | I| |\n | || | |_|| ||_| | || |\n |_||_| [ ]| |[ ] |_||_|\n___________[_][__\\__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | |()____() \\(I)/|\n ===>__/ (:::::::) ==I===\n | || | .=======. | I| |\n | || | |_|| ||_| | || |\n |_||_| [ ]| |[ ] |_||_|\n___________[_][__\\__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | |()____() |\\(I)/\n ===>__/ (:::::::) ===I==\n | || | .=======. | |I |\n | || | |_|| ||_| | || |\n |_||_|_ [ ]| |[ ] |_||_|\n___________[_][__/__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | |()___()| |\\(I)/\n ===>__/ (:::::::) ===I==\n | || | .=======. | |I |\n | || | |_|| ||_| | || |\n |_||_|_ [ ]| |[ ] |_||_|\n___________[_][__/__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | |()___()| \\(I)/|\n ===>__/ (:::::::) ==I===\n | || | .=======. | I| |\n | || | |_|| ||_| | || |\n |_||_| [ ]| |[ ] |_||_|\n___________[_][__\\__________---------_________/__][__\\_____________\n1\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | ()____()| \\(I)/|\n ===>__/ (:::::::) ==I===\n | || | .=======. | I| |\n | || | |_|| ||_| | || |\n |_||_| [ ]| |[ ] |_||_|\n___________[_][__\\__________---------_________/__][__\\_____________\n2\n / \\ / \\\n ( ) ___ ( )\n (O O) / \\ (O O)\n (/=\\) ( ) (/=\\)\n // I \\ (O O) // I \\\\\n || I/~\\| (/^\\) || I ||\n \\\\ > # ) //---\\\\ \\\\ I //\n |\\(> O | |()___()| |\\(I)/\n ===>__/ (:::::::) ===I==\n | || | .=======. | |I |\n | || | |_|| ||_| | || |\n |_||_|_ [ ]| |[ ] |_||_|\n___________[_][__/__________---------_________/__][__\\_____________\n1\n\n\n\n\n\n\n\n\n\n\n\n\n\n3\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\o /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n1\n /~\\ ====\n ( oo| ~~o o\n _\\=/_ _\\ o/_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n2\n /~\\ ====\n |oo ) ~~o o\n _\\=/_ _\\ o/_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n1\n /~\\ ====\n |oo ) o o~~\n _\\=/_ _\\o /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n3\n /~\\ ====\n |oo ) o o~~\n _\\=/_ _\\o /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n5\n /~\\ ====\n |oo ) o o~~\n _\\=/_ _\\o /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ /() \\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n6\n /~\\ ====\n |oo ) ~~o o\n _\\=/_ _\\ o/_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ /() \\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n1\n /~\\ ====\n |oo ) ~~o o\n _\\=/_ _\\ -/_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ /() \\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n5\n /~\\ ====\n |oo ) ~~o o Hey! We don\'t\n _\\=/_ _\\ -/_ serve their\n / _ \\ ___ / \\ / \\ kind here!\n //|/.\\|\\\\ /() \\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n8\n /~\\ ====\n ( oo| ~~o o Hey! We don\'t\n _\\=/_ _\\ -/_ serve their\n / _ \\ ___ / \\ / \\ kind here!\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n6\n /~\\ ====\n ( oo| ~~o o Hey! We don\'t\n _\\=/_ _\\ -/_ serve their\n / _ \\ ___ / \\ / \\ kind here!\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n2\n /~\\ ====\n ( oo| ~~o o Hey! We don\'t\n _\\=/_ _\\ -/_ serve their\n / _ \\ ___ / \\ / \\ kind here!\n //|/.\\|\\\\ /() \\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n3\n /~\\ ====\n ( oo| ~~o o Hey! We don\'t\n _\\=/_ _\\ -/_ serve their\n / _ \\ ___ / \\ / \\ kind here!\n //|/.\\|\\\\ /() \\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n2\n /~\\ ====\n ( oo| ~~o o\n _\\=/_ _\\ -/_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ /() \\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n1\n /~\\ ====\n ( oo| ~~o o Your droids!\n _\\=/_ _\\ -/_ They\'ll have to\n / _ \\ ___ / \\ / \\ wait outside.\n //|/.\\|\\\\ /() \\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n14\n /~\\ ====\n ( oo| ~~o o Your droids!\n _\\=/_ _\\ -/_ They\'ll have to\n / _ \\ ___ / \\ / \\ wait outside.\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n11\n /~\\ ====\n ( oo| ~~o o Your droids!\n _\\=/_ _\\ -/_ They\'ll have to\n / _ \\ ___ / \\ / \\ wait outside.\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n4\n /~\\ ====\n ( oo| o o~~ Your droids!\n _\\=/_ _\\- /_ They\'ll have to\n / _ \\ ___ / \\ / \\ wait outside.\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n6\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n5\n /~\\ Why don\'t you ====\n ( oo| wait... o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n1\n /~\\ Why don\'t you ====\n ( oo| wait... o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n3\n /~\\ Why don\'t you ====\n ( oo| wait... o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n19\n /~\\ Why don\'t you ====\n ( oo| wait... o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n7\n /~\\ ...out by ====\n ( oo| the speeder. o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n20\n /~\\ ...out by ====\n ( oo| the speeder. o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ / ()\\ //| | |\\\\\n || \\_/ || _|_____|_ // | | |//\n || |\\ /| || | | === | | // | | //\n # \\_ _/ # |_| O |_|(\' |===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n2\n /~\\ ...out by ====\n ( oo| the speeder. o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ /() \\ //| | |\\\\\n || \\_/ || _|_____|_ // | | |//\n || |\\ /| || | | === | | // | | //\n # \\_ _/ # |_| O |_|(\' |===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n2\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ /() \\ //| | |\\\\\n || \\_/ || _|_____|_ // | | |//\n || |\\ /| || | | === | | // | | //\n # \\_ _/ # |_| O |_|(\' |===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n4\n /~\\ ====\n ( oo| o o~~\n _\\=/_ _\\- /_\n / _ \\ ___ / \\ / \\\n //|/.\\|\\\\ /() \\ //| | |\\\\\n || \\_/ || _|_____|_ \\\\| | |//\n || |\\ /| || | | === | | \\\\ | //\n # \\_ _/ # |_| O |_| )===(I\n | | | || O || | || I\n | | | ||__*__|| (_)(_)\n []|[] |~ \\___/ ~| |_||_|\n | | | /=\\ /=\\ /=\\ |_||_|\n____________/_]_[_\\_____[_]_[_]_[_]____/__][__\\____________________\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n16\n """" / \\ ====\n ( o,o) ( (O ~~~~\n _\\ =/_ ~# | | | `)\n | || | | | |\n | )| ) | |\\ |\n | || | / || \\\n |_||_| / ||_|\\\n_____________________[_][__\\_________/____|[_]_\\___________________\n1\n """"*******. ====\n No blasters! ( o,o)*******. (o o")\n No blasters! _\\ =/_*******. _\\- /_\n / \\--/ \\*******. / \\ / \\\n //| | |\\\\******. / \\/ \\\n-------------------\\\\| | |-\\\\****\\--/ /| | |\\ |------------------\n \\\\ | | \\o===\\\\// | | | ||\n )===== #\' (> | | | `)\n | || | | | |\n | )| ) | |\\ |\n | || | / || \\\n |_||_| / ||_|\\\n_____________________[_][__\\_________/____|[_]_\\___________________\n1\n """"*********. ====\n No blasters! ( O,O)********. (o o")\n No blasters! _\\ =/**********. _\\- /_\n / \\--***********. / \\ / \\\n //| | **********. / \\/ \\\n-------------------\\\\| | |**********/ /| | |\\ |------------------\n \\\\ | |``*****\\\\// | | | ||\n )===== ```` (> | | | `)\n | || | | | |\n | )| ) | |\\ |\n | || | / || \\\n |_||_| / ||_|\\\n_____________________[_][__\\_________/____|[_]_\\___________________\n1\n """"*******. ====\n No blasters! ( O,O)*******. (o o")\n No blasters! _\\ o/_*******. _\\- /_\n / \\--/()*******. / \\ / \\\n //| | | .******. / \\/ \\\n-------------------\\\\| | |-\\\\****\\--/ /| | |\\ |------------------\n \\\\ | | \\\\ \\\\// | | | ||\n )===== o=== (> | | | `)\n | || | #\' | | |\n | )| ) | |\\ |\n | || | / || \\\n |_||_| / ||_|\\\n_____________________[_][__\\_________/____|[_]_\\___________________\n1\n """" `*. ====\n No blasters! ( O,O) `*. (o o")\n No blasters! _\\ o/_ `*. _\\- /_\n / \\--/() `*. / \\ / \\\n //| | | `*. / \\/ \\\n-------------------\\\\| | |-----`*\\--/ /| | |\\ |------------------\n \\\\ | | \\\\ \\\\// | | | ||\n )===== \\\\ (> | | | `)\n | || | o=== | | |\n | )| ) #\' | |\\ |\n | || | / || \\\n |_||_| / ||_|\\\n_____________________[_][__\\_________/____|[_]_\\___________________\n1\n """" ====\n No blasters! ( O,O) (o o")\n No blasters! _\\ o/_ *. _\\- /_\n / \\--/() `*. / \\ / \\\n //| | | `*. / \\/ \\\n-------------------\\\\| | |-----`*\\--/ /| | |\\ |------------------\n \\\\ | | \\\\ \\\\// | | | ||\n )===== \\\\ (> | | | `)\n | || | o=== | | |\n | )| ) #\' | |\\ |\n | || | / || \\\n |_||_| / ||_|\\\n_____________________[_][__\\_________/____|[_]_\\___________________\n1\n """" ====\n No blasters! ( O,O) (o o")\n No blasters! _\\ o/_ _\\- /_\n / \\--/() / \\ / \\\n //| | | *. / \\/ \\\n-------------------\\\\| | |-----`*\\--/ /| | |\\ |------------------\n \\\\ | | \\\\// | | | ||\n )===== \\\\ (> | | | `)\n | || | o=== | | |\n | )| ) #\' | |\\ |\n | || | / || \\\n |_||_| / ||_|\\\n_____________________[_][__\\_________/____|[_]_\\___________________\n1\n """" ====\n No blasters! ( o,o) (o o")\n No blasters! _\\ o/_ _\\- /_\n / \\--/() / \\ / \\\n //| | | / \\/ \\\n-------------------\\\\| | |------o\\--/ /| | |\\ |------------------\n \\\\ | | \\\\// | | | ||\n )===== (> | | | `)\n | || | \\\\ | | |\n | )| ) o=== | |\\ |\n | || | #\' / || \\\n |_||_| / ||_|\\\n_____________________[_][__\\_________/____|[_]_\\___________________\n1\n """" ====\n ( o,o) (o o")\n _\\ o/_ _\\- /_\n / \\--/() / \\ / \\\n //| | | / \\/ \\\n-------------------\\\\| | |----------/ /| | |\\ |------------------\n \\\\ | | || | | | ||\n )===== ===(= | | | `)\n | || | | | |\n | )| ) \\\\ | |\\ |\n | || | o=== / || \\\n |_||_| #\' / ||_|\\\n_____________________[_][__\\_________/____|[_]_\\___________________\n1\n """" ====\n ( o,o) (o o")\n _\\ =/_ _\\- /_\n / \\--/() / \\ / \\\n //| | | / \\/ \\\n-------------------\\\\| | |----------/ /| | |\\ |------------------\n \\\\ | | || | | | ||\n )===== ===(= | | | `)\n | || | | | |\n | )| ) | |\\ |\n | || | \\\\ / || \\\n |_||_| o=== / ||_|\\\n_____________________[_][__\\__#\'_____/____|[_]_\\___________________\n1\n """" ====\n ( o,o) (o o")\n _\\ =/_ _\\- /_\n / \\--/() / \\ / \\\n //| | | / \\/ \\\n-------------------\\\\| | |----------/ /| | |\\ |------------------\n \\\\ | | || | | | ||\n )===== ===(= | | | `)\n | || | | | |\n | )| ) | |\\ |\n | || | / || \\\n |_||_| \\\\ / ||_|\\\n_____________________[_][__\\__#\'==___/____|[_]_\\___________________\n7\n """" ====\n ( o,o) (o o")\n _\\ =/_ _\\- /_\n / \\--/() / \\ / \\\n //| | | / \\/ \\\n-------------------\\\\| | |----------/ /| | |\\ |------------------\n \\\\ | | || | | | ||\n )===== ===(= | | | `)\n | || | | | |\n | )| ) | |\\ |\n | || | / || \\\n |_||_| / ||_|\\\n_____________________[_][__\\_=#\'==___/____|[_]_\\___________________\n9\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n ==== ==== ####\n ~~o o ("o o) {o o"}\n _\\ -/_ _\\ -/_ {= }\n / \\ / \\ / \\ / \\ {~~ //~}\n //| | \\\\ / \\/ \\ {{~{ //}~}}\n \\\\| | // | /| | |\\ | {} {// } {}\n \\\\ | // || | | | || {} // } {}\n )====) (\' | | | `) {} H{{}}} {}\n | || I | | | @ H"||"} @\n (_)(_) | /| | {"||"}\n |_||_| / || \\ {"||"}\n |_||_| /|_|| \\ {"||"}\n_________[_][__\\____/_[_]|____\\_____________________[_][_]_________\n10\n ==== ==== ####\n ~~o o ("o o) Chewbacca here {o o"}\n _\\ -/_ _\\ -/_ is first mate on {= }\n / \\ / \\ / \\ / \\ a ship... {~~ //~}\n //| | \\\\ / \\/ \\ {{~{ //}~}}\n \\\\| | // | /| | |\\ | {} {// } {}\n \\\\ | // || | | | || {} // } {}\n )====) (\' | | | `) {} H{{}}} {}\n | || I | | | @ H"||"} @\n (_)(_) | /| | {"||"}\n |_||_| / || \\ {"||"}\n |_||_| /|_|| \\ {"||"}\n_________[_][__\\____/_[_]|____\\_____________________[_][_]_________\n23\n ==== ==== ####\n ~~o o ("o o) Chewbacca here {o o"}\n _\\ -/_ _\\ -/_ is first mate on {= }\n / \\ / \\ / \\ / \\ a ship... {~~ //~}\n //| | \\\\ / \\/ \\ {{~{ //}~}}\n \\\\| | // | /| | |\\ \\ {} {// } {}\n \\\\ | // || | | | \\ \\ {} // } {}\n )====) (\' | | | `() {} H{{}}} {}\n | || I | | | @ H"||"} @\n (_)(_) | /| | {"||"}\n |_||_| / || \\ {"||"}\n |_||_| /|_|| \\ {"||"}\n_________[_][__\\____/_[_]|____\\_____________________[_][_]_________\n11\n ==== ==== ####\n ~~o o ("o o) ...that might {o o"}\n _\\ -/_ _\\ -/_ suit us. {= }\n / \\ / \\ / \\ / \\ {~~ //~}\n //| | \\\\ / \\/ \\ {{~{ //}~}}\n \\\\| | // | /| | |\\ \\ {} {// } {}\n \\\\ | // || | | | \\ \\ {} // } {}\n )====) (\' | | | `() {} H{{}}} {}\n | || I | | | @ H"||"} @\n (_)(_) | /| | {"||"}\n |_||_| / || \\ {"||"}\n |_||_| /|_|| \\ {"||"}\n_________[_][__\\____/_[_]|____\\_____________________[_][_]_________\n10\n ==== ==== ####\n ~~o o ("o o) ...that might {o o"}\n _\\ -/_ _\\ -/_ suit us. {= }\n / \\ / \\ / \\ / \\ {~~ //~}\n //| | \\\\ / \\/ \\ {{~{ //}~}}\n \\\\| | // | /| | |\\ | {} {// } {}\n \\\\ | // || | | | || {} // } {}\n )====) (\' | | | `) {} H{{}}} {}\n | || I | | | @ H"||"} @\n (_)(_) | /| | {"||"}\n |_||_| / || \\ {"||"}\n |_||_| /|_|| \\ {"||"}\n_________[_][__\\____/_[_]|____\\_____________________[_][_]_________\n6\n ==== ==== ####\n ~~o o ("o o) {o o"}\n _\\ -/_ _\\ -/_ {= }\n / \\ / \\ / \\ / \\ {~~ //~}\n //| | \\\\ / \\/ \\ {{~{ //}~}}\n \\\\| | // | /| | |\\ | {} {// } {}\n \\\\ | // || | | | || {} // } {}\n )====) (\' | | | `) {} H{{}}} {}\n | || I | | | @ H"||"} @\n (_)(_) | /| | {"||"}\n |_||_| / || \\ {"||"}\n |_||_| /|_|| \\ {"||"}\n_________[_][__\\____/_[_]|____\\_____________________[_][_]_________\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n\n\n\n\n #### -=== ==== ====\n {"o o} ""o o (o o") o o~~\n { =} _\\ -/_ _\\- /_ _\\- /_\n {~~ //~} /| || |\\ / \\ / \\ / \\ / \\\n {{~{ //}~}} //| || |\\\\ / \\/ \\ / | \\\n -------------||--------\\\\------------| /------\\ |-----------------\n (\' () || ||\n (\' \')\n\n35\n Han Solo. I\'m captain\n of the Millennium Falcon.\n\n\n #### -=== ==== ====\n {"o o} ""o o (o o") o o~~\n { =} _\\ -/_ _\\- /_ _\\- /_\n {~~ //~} /| || |\\ / \\ / \\ / \\ / \\\n {{~{ //}~}} //| || |\\\\ / \\/ \\ / | \\\n -------------||--------\\\\------------| /------\\ |-----------------\n (\' () || ||\n (\' \')\n\n2\n\n\n\n\n #### -=== ==== ====\n {"o o} ""o o (o o") o o~~\n { =} _\\ -/_ _\\- /_ _\\- /_\n {~~ //~} /| || |\\ / \\ / \\ / \\ / \\\n {{~{ //}~}} //| || |\\\\ / \\/ \\ / | \\\n -------------||--------\\\\------------| /------\\ |-----------------\n (\' () || ||\n (\' \')\n\n35\n Chewie here tells me\n you\'re looking for passage\n to the Alderaan system.\n\n #### -=== ==== ====\n {"o o} ""o o (o o") o o~~\n { =} _\\ -/_ _\\- /_ _\\- /_\n {~~ //~} /| || |\\ / \\ / \\ / \\ / \\\n {{~{ //}~}} //| || |\\\\ / \\/ \\ / | \\\n -------------||--------\\\\------------| /------\\ |-----------------\n (\' () || ||\n (\' \')\n\n1\n\n\n\n\n #### -=== ==== ====\n {"o o} ""o o (o o") o o~~\n { =} _\\ -/_ _\\- /_ _\\- /_\n {~~ //~} /| || |\\ / \\ / \\ / \\ / \\\n {{~{ //}~}} //| || |\\\\ / \\/ \\ / | \\\n -------------||--------\\\\------------| /------\\ |-----------------\n (\' () || ||\n (\' \')\n\n32\n Yes, indeed.\n If it\'s a fast ship.\n\n\n #### -=== ==== ====\n {"o o} ""o o (o o") o o~~\n { =} _\\ -/_ _\\- /_ _\\- /_\n {~~ //~} /| || |\\ / \\ / \\ / \\ / \\\n {{~{ //}~}} //| || |\\\\ / \\/ \\ / | \\\n -------------||--------\\\\------------| /------\\ |-----------------\n (\' () || ||\n (\' \')\n\n1\n Yes, indeed.\n If it\'s a fast ship.\n\n\n #### -=== ==== ====\n {"o o} ""o o (o o") o o~~\n { =} _\\ -/_ _\\- /_ _\\- /_\n {~~ //~} /| || |\\.__ / \\ / \\ / \\ / \\\n {{~{ //}~}} //| || |\\._/\') / \\/ \\ / | \\\n -------------||----------------------| /------\\ |-----------------\n (\' || ||\n (\' \')\n\n1\n\n\n\n\n #### -=== ==== ====\n {"o o} ""o o (o o") o o~~\n { =} _\\ -/_ _\\- /_ _\\- /_\n {~~ //~} /| || |\\.__ / \\ / \\ / \\ / \\\n {{~{ //}~}} //| || |\\._/\') / \\/ \\ / | \\\n -------------||----------------------| /------\\ |-----------------\n (\' || ||\n (\' \')\n\n12\n It\'s the ship that made\n the Kessel run in less than\n twelve parsecs!\n\n #### -=== ==== ====\n {"o o} ""o o (o o") o o~~\n { =} _\\ -/_ _\\- /_ _\\- /_\n {~~ //~} /| || |\\.__ / \\ / \\ / \\ / \\\n {{~{ //}~}} //| || |\\._/\') / \\/ \\ / | \\\n -------------||----------------------| /------\\ |-----------------\n (\' || ||\n (\' \')\n\n4\n It\'s the ship that made\n the Kessel run in less than\n twelve parsecs!\n\n #### -=== ==== ====\n {"o o} ""o o ("o o) o o~~\n { =} _\\ -/_ _\\ -/_ _\\- /_\n {~~ //~} /| || |\\.__ / \\ / \\ / \\ / \\\n {{~{ //}~}} //| || |\\._/\') / \\/ \\ / | \\\n -------------||----------------------| /------\\ |-----------------\n (\' || ||\n (\' \')\n\n13\n It\'s the ship that made\n the Kessel run in less than\n twelve parsecs!\n\n #### -=== ==== ====\n {"o o} ""o o ("o o) o o~~\n { =} _\\ -/_ _\\ -/_ _\\- /_\n {~~ //~} /| || |\\ / \\ / \\ / \\ / \\\n {{~{ //}~}} //| || |\\\\ / \\/ \\ / | \\\n -------------||--------\\\\------------| /------\\ |-----------------\n (\' () || ||\n (\' \')\n\n2\n It\'s the ship that made\n the Kessel run in less than\n twelve parsecs!\n\n #### -=== ==== ====\n {"o o} ""o o ("o o) o o~~\n { =} _\\ -/_ _\\ -/_ -\\- /-\n {~~ //~} /| || |\\ / \\ / \\ / \\ / \\\n {{~{ //}~}} //| || |\\\\ / \\/ \\ / | \\\n -------------||--------\\\\------------| /------\\ |-----------------\n (\' () || ||\n (\' \')\n\n3\n She\'s fast enough for\n you, old man.\n\n\n #### -=== ==== ====\n {"o o} ""o o ("o o) o o~~\n { =} _\\ -/_ _\\ -/_ -\\- /-\n {~~ //~} /| || |\\ / \\ / \\ / \\ / \\\n {{~{ //}~}} //| || |\\\\ / \\/ \\ / | \\\n -------------||--------\\\\------------| /------\\ |-----------------\n (\' () || ||\n (\' \')\n\n2\n She\'s fast enough for\n you, old man.\n\n\n #### -=== ==== ====\n {"o o} ""o o (o o") o o~~\n { =} _\\ -/_ _\\- /_ -\\- /-\n {~~ //~} /| || |\\ / \\ / \\ / \\ / \\\n {{~{ //}~}} //| || |\\\\ / \\/ \\ / | \\\n -------------||--------\\\\------------| /------\\ |-----------------\n (\' () || ||\n (\' \')\n\n27\n She\'s fast enough for\n you, old man.\n\n\n #### -=== ==== ====\n {"o o} ""o o (o o") o o~~\n { =} _\\ -/_ _\\- /_ _\\- /_\n {~~ //~} /| || |\\ / \\ / \\ / \\ / \\\n {{~{ //}~}} //| || |\\\\ / \\/ \\ / | \\\n -------------||--------\\\\------------| /------\\ |-----------------\n (\' () || ||\n (\' \')\n\n1\n\n\n\n\n #### -=== ==== ====\n {"o o} ""o o (o o") o o~~\n { =} _\\ -/_ _\\- /_ _\\- /_\n {~~ //~} /| || |\\ / \\ / \\ / \\ / \\\n {{~{ //}~}} //| || |\\\\ / \\/ \\ / | \\\n -------------||--------\\\\------------| /------\\ |-----------------\n (\' () || ||\n (\' \')\n\n30\n Docking bay\n ninety-four.\n\n\n #### -=== ==== ====\n {"o o} ""o o (o o") o o~~\n { =} _\\ -/_ _\\- /_ _\\- /_\n {~~ //~} /| || |\\ / \\ / \\ / \\ / \\\n {{~{ //}~}} //| || |\\\\ / \\/ \\ / | \\\n -------------||--------\\\\------------| /------\\ |-----------------\n (\' () || ||\n (\' \')\n\n1\n\n\n\n\n #### -=== ==== ====\n {"o o} ""o o (o o") o o~~\n { =} _\\ -/_ _\\- /_ _\\- /_\n {~~ //~} /| || |\\ / \\ / \\ / \\ / \\\n {{~{ //}~}} //| || |\\\\ / \\/ \\ / | \\\n -------------||--------\\\\------------| /------\\ |-----------------\n (\' () || ||\n (\' \')\n\n6\n\n\n\n\n\n\n\n\n\n\n\n\n\n2\n\n\n\n\n #### ===-\n {"o o} o o""\n { =} _\\- /_\n {~~ //~} /| || |\\\n {{~{ //}~}} //| || |\\\\\n--------------------------------||--------||-----------------------\n (\' \')\n\n\n29\n\n This could really\n save my neck.\n\n #### ===-\n {"o o} o o""\n { =} _\\- /_\n {~~ //~} /| || |\\\n {{~{ //}~}} //| || |\\\\\n--------------------------------||--------||-----------------------\n (\' \')\n\n\n1\n\n\n\n\n #### ===-\n {"o o} o o""\n { =} _\\- /_\n {~~ //~} /| || |\\\n {{~{ //}~}} //| || |\\\\\n--------------------------------||--------||-----------------------\n (\' \')\n\n\n10\n\n Get back to the ship\n and get her ready.\n\n #### ===-\n {"o o} o o""\n { =} _\\- /_\n {~~ //~} /| || |\\\n {{~{ //}~}} //| || |\\\\\n--------------------------------||--------||-----------------------\n (\' \')\n\n\n1\n\n Get back to the ship\n and get her ready.\n ####\n {"o o} ===-\n { =} o o""\n {~~ //~} _\\- /_\n {{~{ //}~}} /| || |\\\n {} {// } {} //| || |\\\\\n--------------------------------||--------||-----------------------\n (\' \')\n\n\n1\n\n Get back to the ship\n #### and get her ready.\n {"o o}\n { =} ===-\n {~~ //~} o o""\n {{~{ //}~}} _\\- /_\n {} {// } {} /| || |\\\n {} // } {} //| || |\\\\\n--------------------------------||--------||-----------------------\n (\' \')\n\n\n1\n\n #### Get back to the ship\n {"o o} and get her ready.\n { =}\n {~~ //~} ===-\n {{~{ //}~}} o o""\n {} {// } {} _\\- /_\n {} // } {} /| || |\\\n {} H{{}}} {} //| || |\\\\\n--------------------------------||--------||-----------------------\n (\' \')\n\n\n4\n ####\n {"o o} Get back to the ship\n { =} and get her ready.\n {~~ //~}\n {{~{ //}~}} ===-\n {{~{// } }} o o""\n {} // } {} _\\- /_\n {} H{{}}} {} /| || |\\\n {} H"||"} {} //| || |\\\\\n--------------------------------||--------||-----------------------\n (\' \')\n\n\n3\n ####\n {"o o}\n { =}\n {~~ //~}\n {{~{ //}~}} ===-\n {{~{// } }} o o""\n {} // } {} _\\- /_\n {} H{{}}} {} /| || |\\\n {} H"||"} {} //| || |\\\\\n--------------------------------||--------||-----------------------\n (\' \')\n\n\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n2\n -=== `"\',\n ""o o O O|)\n _\\ -/_ _\\o/ _\n /| || |\\ /|\\ / |\\\n //| || |\\\\ //| | |\\\\\n || | || | \\\\ // | | | ||\n || |/ \\| \\\\ -==# | | | ||\n |! |====| \') \'\\ |====| /#\n =] |/|| | | || | "\n I ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n31\n -=== `"\',\n ""o o O O|) Going somewhere,\n _\\ -/_ _\\o/ _ Solo?\n /| || |\\ /|\\ / |\\\n //| || |\\\\ //| | |\\\\\n || | || | \\\\ // | | | ||\n || |/ \\| \\\\ -==# | | | ||\n |! |====| \') \'\\ |====| /#\n =] |/|| | | || | "\n I ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n30\n -=== `"\',\n Yes Greedo! ""o o O O|)\n _\\ -/_ _\\o/ _\n /| || |\\ /|\\ / |\\\n //| || |\\\\ //| | |\\\\\n || | || | \\\\ // | | | ||\n || |/ \\| \\\\ -==# | | | ||\n |! |====| \') \'\\ |====| /#\n =] |/|| | | || | "\n I ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n1\n -=== `"\',\n ""o o O O|)\n _\\ -/_ _\\o/ _\n /| || |\\ /|\\ / |\\\n //| || |\\\\ //| | |\\\\\n || | || | \\\\ // | | | ||\n || |/ \\| \\\\ -==# | | | ||\n |! |====| \') \'\\ |====| /#\n =] |/|| | | || | "\n I ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n30\n -=== `"\',\n I was just ""o o O O|)\n going to see _\\ -/_ _\\o/ _\n your boss. /| || |\\ /|\\ / |\\\n //| || |\\\\ //| | |\\\\\n || | || | \\\\ // | | | ||\n || |/ \\| \\\\ -==# | | | ||\n |! |====| \') \'\\ |====| /#\n =] |/|| | | || | "\n I ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n1\n -=== `"\',\n ""o o O O|)\n _\\ -/_ _\\o/ _\n /| || |\\ /|\\ / |\\\n //| || |\\\\ //| | |\\\\\n || | || | \\\\ // | | | ||\n || |/ \\| \\\\ -==# | | | ||\n |! |====| \') \'\\ |====| /#\n =] |/|| | | || | "\n I ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n31\n -=== `"\',\n Tell Jabba ""o o O O|)\n I have his _\\ -/_ _\\o/ _\n money. /| || |\\ /|\\ / |\\\n //| || |\\\\ //| | |\\\\\n || | || | \\\\ // | | | ||\n || |/ \\| \\\\ -==# | | | ||\n |! |====| \') \'\\ |====| /#\n =] |/|| | | || | "\n I ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n1\n -=== `"\',\n ""o o O O|)\n _\\ -/_ _\\o/ _\n /| || |\\ /|\\ / |\\\n //| || |\\\\ //| | |\\\\\n || | || | \\\\ // | | | ||\n || |/ \\| \\\\ -==# | | | ||\n |! |====| \') \'\\ |====| /#\n =] |/|| | | || | "\n I ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n31\n -=== `"\',\n ""o o O O|) He may only take\n _\\ -/_ _\\o/ _ your ship.\n /| || |\\ /|\\ / |\\\n //| || |\\\\ //| | |\\\\\n || | || | \\\\ // | | | ||\n || |/ \\| \\\\ -==# | | | ||\n |! |====| \') \'\\ |====| /#\n =] |/|| | | || | "\n I ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n1\n -=== `"\',\n ""o o O O|)\n _\\ -/_ _\\o/ _\n /| || |\\ /|\\ / |\\\n //| || |\\\\ //| | |\\\\\n || | || | \\\\ // | | | ||\n || |/ \\| \\\\ -==# | | | ||\n |! |====| \') \'\\ |====| /#\n =] |/|| | | || | "\n I ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n32\n -=== `"\',\n Over my dead ""o o O O|)\n body! _\\ -/_ _\\o/ _\n /| || |\\ /|\\ / |\\\n //| || |\\\\ //| | |\\\\\n || | || | \\\\ // | | | ||\n || |/ \\| \\\\ -==# | | | ||\n |! |====| \') \'\\ |====| /#\n =] |/|| | | || | "\n I ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n1\n -=== `"\',\n ""o o O O|)\n _\\ -/_ _\\o/ _\n /| || |\\ /|\\ / |\\\n //| || |\\\\ //| | |\\\\\n || | || | \\\\ // | | | ||\n || |/ \\| \\\\ -==# | | | ||\n |! |====| \') \'\\ |====| /#\n =] |/|| | | || | "\n I ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n30\n -=== `"\',\n ""o o O O|) I\'ve been looking\n _\\ -/_ _\\o/ _ forward to this\n /| || |\\ /|\\ / |\\ for a long time!\n //| || |\\\\ //| | |\\\\\n || | || | \\\\ // | | | ||\n || |/ \\| \\\\ -==# | | | ||\n |! |====| \') \'\\ |====| /#\n =] |/|| | | || | "\n I ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n1\n -=== `"\',\n ""o o O O|)\n _\\ -/_ _\\o/ _\n /| || |\\ /|\\ / |\\\n //| || |\\\\ //| | |\\\\\n || | || | \\\\ // | | | ||\n || |/ \\| \\\\ -==# | | | ||\n |! |====| \') \'\\ |====| /#\n =] |/|| | | || | "\n I ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n26\n -=== `"\',\n I\'ll bet you ""o o O O|)\n have! _\\ -/_ _\\o/ _\n /| || |\\ /|\\ / |\\\n //| || |\\\\ //| | |\\\\\n || | || | \\\\ // | | | ||\n || |/ \\| \\\\ -==# | | | ||\n |! |====| \') \'\\ |====| /#\n =] |/|| | | || | "\n I ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n1\n -=== `"\',\n I\'ll bet you ""o o O O|)\n have! _\\ -/_ _\\o/ _\n /| || |\\ /|\\ / |\\\n //| || |\\\\ //| | |\\\\\n \\\\| || | \\\\ // | | | ||\n \\o===\\| \\\\ -==# | | | ||\n |#\'==| \') \'\\ |====| /#\n |/|| | | || | "\n ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n1\n -=== `"\',\n I\'ll bet you ""o o O O|)\n have! _\\ -/_ _\\o/ _\n || || |\\ /|\\ / |\\\n \\\\ || |\\\\ //| | |\\\\\n \\\\o=== \\\\ // | | | ||\n |\\(#\'| \\\\ -==# | | | ||\n |====| \') \'\\ |====| /#\n |/|| | | || | "\n ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n1\n -=== `"\',\n I\'ll bet you ""o o O O|)\n have! _\\ -/_ _\\o/ _\n || || |\\ /|\\ / |\\\n \\\\ || |\\\\ //| | |\\\\\n \\\\o===*** // | | | ||\n |\\(#\'| \\\\ -==# | | | ||\n |====| \') \'\\ |====| /#\n |/|| | | || | "\n ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n1\n -=== `"\',\n I\'ll bet you ""o o O O|)\n have! _\\ -/_ _\\o/ _\n || || |* /|\\ / |\\\n \\\\ || *** //| | |\\\\\n \\\\o=*********** // | | | ||\n |\\(#\'***\\\\ -==# | | | ||\n |====|* \') \'\\ |====| /#\n |/|| | | || | "\n ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n1\n -=== `"\',\n I\'ll bet you ""o o O O|)\n have! _\\ -/_* _\\o/ _\n || || *** /|\\ / |\\\n \\\\ ||***** //| | |\\\\\n \\\\o******************// | | | ||\n |\\(#*****\\ -==# | | | ||\n |====*** \') \'\\ |====| /#\n |/|| |* | || | "\n ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n1\n -=== `"\',\n ""o o O O|)\n _\\ -/_ _\\o/ _\n || || |* /|\\ / |\\\n \\\\ || *** //| | |\\\\\n \\\\o=*********************** | ||\n |\\(#\'***\\\\ -==# | |" | ||\n |====|* \') \'\\ |====| /#\n |/|| | | || | "\n ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n1\n -=== `"\',\n ""o o O O|)\n _\\ -/_ _\\O/ _\n || || |\\ /|\\ / |\\\n \\\\ || |*\\ //| *. |\\\\\n \\\\o==*********************** | ||\n |\\(#\'|* \\\\ -==# |\'* \'| ||\n |====| \') \'\\ |====| /#\n |/|| | | ||"| "\n ( )( ) | || |\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n1\n -=== `"\',\n ""o o O O|)\n _\\ -/_ _\\O/ _\n || || |\\ /|* / .\\\n \\\\ || |\\\\ //|*** |\\\\\n \\\\o=== \\\\ *****************| ||\n |\\(#\'| \\\\ -==# **** | ||\n |====| \') \'\\ .|====|\'/#\n |/|| | | || | "\n ( )( ) | || |\n |-||-| | || |"\n | || | | || |\n________________[_][__\\________________/__)(_)_____________________\n1\n -=== `"\',\n ""o o X X|)\n _\\ -/_ _\\** _ \'\n || || |\\ /***** \\\n \\\\ || |\\\\ /*******\\\\\n \\\\o=== \\\\ ***********| ||\n |\\(#\'| \\\\ -==# ******* ||\n |====| \') \'\\ *****| /#\n |/|| | |*** | "\n ( )( ) \' | || | \'\n |-||-| | || |\n | || | | || |\n________________[_][__\\________________/__)(_)_"___________________\n1\n -=== `"\',\n ""o o ***** \'\n _\\ -/_ ********\n || || |\\ *********\n \\\\ || |\\\\ **********\n \\\\o=== \\\\ *********||\n |\\(#\'| \\\\ -==#*********||\n |====| \') \'\\ ********/#\n |/|| | |***** "\n ( )( ) | || |\n |-||-| \' | || | \'\n | || | | || | "\n________________[_][__\\________________/__)(_)_____________________\n1\n -=== `**,\n ""o o *****\n _\\ -/_ ******** \'\n || || |\\ *********\n \\\\ || |\\\\ **********\n \\\\o=== \\\\ ***********|\n |\\(#\'| \\\\ -==#**********|\n |====| \') \'\\ *********#\n |/|| | |****** "\n ( )( ) | |**|\n |-||-| | || |\n | || | \' | || | \'\n________________[_][__\\________________/__)(_)______"______________\n1\n -=== `**,\n ""o o *****\n _\\ -/_ ********\n || || |\\ *********\n \\\\ || |\\\\ ********** \'\n \\\\o=== \\\\ ***********|\n |\\(#\'| \\\\ -==#**********|\n |====| \') \'\\ *********#\n |/|| | |****** "\n ( )( ) | |**|\n |-||-| | || |\n | || | | || |\n________________[_][__\\_________\'______/__)(_)_______"\'____________\n6\n\n\n\n\n\n\n\n\n\n\n\n\n\n7\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | :/----I-----\n__\\|________\\|________________________________________/_____===____\n2\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ /|\\ \\ |-O-| | | |\n | || \\ | \\_/___|_________|__|\n | | \\ | :/----I-----\n__\\|________\\|________________________________________/_____===____\n2\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ /|+ \\ |-O-| | | |\n | ||+| \\ | \\_/___|_________|__|\n | | | \\ | :/----I-----\n__\\|________\\|________________________________________/_____===____\n2\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / + \\ |-O-| | | |\n | ||+|+\\ | \\_/___|_________|__|\n | | |+| \\ | :/----I-----\n__\\|__|_____\\|________________________________________/_____===____\n2\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / + \\ |-O-| | | |\n | | || \\ | \\_/___|_________|__|\n | | + + +\\ | :/----I-----\n__\\|_|_|_|__\\|________________________________________/_____===____\n2\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / + \\ |-O-| | | |\n | | || \\ | \\_/___|_________|__|\n | | + + + | :/----I-----\n__\\|__|_|_|_\\|________________________________________/_____===____\n2\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | + \\ | \\_/___|_________|__|\n | | ||+ +\\+ | :/----I-----\n__\\|___|_|_|\\|________________________________________/_____===____\n2\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | + + + +| :/----I-----\n__\\|_||_|_|_||________________________________________/_____===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | + +\\+ + :/----I-----\n__\\|__||_|_|_|________________________________________/_____===____\n1\n\n\n\n\n What a piece\n of junk! _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | + +\\+ + :/----I-----\n__\\|__||_|_|_|________________________________________/_____===____\n2\n\n\n\n\n What a piece\n of junk! _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | + + +|+ :/----I-----\n__\\|__|_|_|_|||_______________________________________/_____===____\n2\n\n\n\n\n What a piece\n of junk! _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | +\\+ + + :/----I-----\n__\\|___|_|_|_|_|______________________________________/_____===____\n2\n\n\n\n\n What a piece\n of junk! _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | + +|+ + :/----I-----\n__\\|____|_|_|||_|_____________________________________/_____===____\n2\n\n\n\n\n What a piece\n of junk! _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\+ + + + :/----I-----\n__\\|_____|_|_|_|_|____________________________________/_____===____\n2\n\n\n\n\n What a piece\n of junk! _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ +|+ + + :/----I-----\n__\\|______|_|||_|_|___________________________________/_____===____\n2\n\n\n\n\n What a piece\n of junk! _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ + + + + :/----I-----\n__\\|_______|_|_|_|_|__________________________________/_____===____\n2\n\n\n\n\n What a piece\n of junk! _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ |+ + + + :/----I-----\n__\\|________|_|_|_|_|_________________________________/_____===____\n2\n\n\n\n\n What a piece\n of junk! _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ \' + + + + :/----I-----\n__\\|________\\|_|_|_|_|________________________________/_____===____\n2\n\n\n\n\n What a piece\n of junk! _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + :/----I-----\n__\\|________\\||_|_|_|_|_______________________________/_____===____\n2\n\n\n\n\n What a piece\n of junk! _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + :/----I-----\n__\\|________\\|_|_|_|_|_|______________________________/_____===____\n2\n\n\n\n\n What a piece\n of junk! _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + :/----I-----\n__\\|________\\|__|_|_|_|_|_____________________________/_____===____\n2\n\n\n\n\n What a piece\n of junk! _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + :/----I-----\n__\\|________\\|___|_|_|_|_|____________________________/_____===____\n2\n\n\n\n\n What a piece\n of junk! _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + :/----I-----\n__\\|________\\|____|_|_|_|_|___________________________/_____===____\n2\n\n\n\n\n What a piece\n of junk! _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + :/----I-----\n__\\|________\\|_____|_|_|_|_|__________________________/_____===____\n1\n\n\n\n\n What a piece\n of junk! _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + :/----I-----\n__\\|________\\|______|_|_|_|_|_________________________/_____===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + |/----I-----\n__\\|________\\|______|_|_|_|_|_________________________/_____===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + |/----I-----\n__\\|________\\|_______|_|_|_|_|________________________/_____===____\n1\n\n\n She\'ll make point\n five past light-speed!\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + |/----I-----\n__\\|________\\|_______|_|_|_|_|________________________/_____===____\n2\n\n\n She\'ll make point\n five past light-speed!\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|________|_|_|_|_|______________________|/_____===____\n1\n\n\n She\'ll make point\n five past light-speed!\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|_________|_|_|_|_|_____________________|/_____===____\n1\n\n\n She\'ll make point\n five past light-speed!\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|_________|_|_|_|_|____________________|_/_____===____\n2\n\n\n She\'ll make point\n five past light-speed!\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|__________|_|_|_|_|___________________|_/_____===____\n2\n\n\n She\'ll make point\n five past light-speed!\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|___________|_|_|_|_|_________________|__/_____===____\n1\n\n\n She\'ll make point\n five past light-speed!\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|____________|_|_|_|_|________________|__/_____===____\n1\n\n\n She\'ll make point\n five past light-speed!\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|____________|_|_|_|_|_______________|___/_____===____\n2\n\n\n She\'ll make point\n five past light-speed!\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|_____________|_|_|_|_|______________|___/_____===____\n2\n\n\n She\'ll make point\n five past light-speed!\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|______________|_|_|_|_|____________|____/_____===____\n2\n\n\n She\'ll make point\n five past light-speed!\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|_______________|_|_|_|_|___________|____/_____===____\n2\n\n\n She\'ll make point\n five past light-speed!\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|________________|_|_|_|_|__________|____/_____===____\n2\n\n\n She\'ll make point\n five past light-speed!\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|_________________|_|_|_|_|_________|____/_____===____\n2\n\n\n She\'ll make point\n five past light-speed!\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|__________________|_|_|_|_|________|____/_____===____\n2\n\n\n She\'ll make point\n five past light-speed!\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|___________________|_|_|_|_|_______|____/_____===____\n2\n\n\n She\'ll make point\n five past light-speed!\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|____________________|_|_|_|_|______|____/_____===____\n2\n\n\n She\'ll make point\n five past light-speed!\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|_____________________|_|_|_|_|_____|____/_____===____\n1\n\n\n She\'ll make point\n five past light-speed!\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|______________________|_|_|_|_|____|____/_____===____\n10\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|______________________|_|_|_|_|____|____/_____===____\n6\n\n\n If you\'ll just get on\n board we\'ll get out of here.\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|______________________|_|_|_|_|____|____/_____===____\n3\n\n\n If you\'ll just get on\n board we\'ll get out of here.\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|_______________________|_|_|_|_|___|____/_____===____\n3\n\n\n If you\'ll just get on\n board we\'ll get out of here.\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|________________________|_|_|_|_|__|____/_____===____\n3\n\n\n If you\'ll just get on\n board we\'ll get out of here.\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + + :/----I-----\n__\\|________\\|_________________________|_|_|_|_|_|____/_____===____\n3\n\n\n If you\'ll just get on\n board we\'ll get out of here.\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + ++ :/----I-----\n__\\|________\\|__________________________|_|_|_|_||____/_____===____\n3\n\n\n If you\'ll just get on\n board we\'ll get out of here.\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + :/----I-----\n__\\|________\\|___________________________|_|_|_|_|____/_____===____\n3\n\n\n If you\'ll just get on\n board we\'ll get out of here.\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + +++ :/----I-----\n__\\|________\\|____________________________|_|_|_|||___/_____===____\n3\n\n\n If you\'ll just get on\n board we\'ll get out of here.\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + :/----I-----\n__\\|________\\|_____________________________|_|_|_|_|__/_____===____\n3\n\n\n If you\'ll just get on\n board we\'ll get out of here.\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + +++ + :/----I-----\n__\\|________\\|______________________________|_|_|||_|_/_____===____\n3\n\n\n If you\'ll just get on\n board we\'ll get out of here.\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + + :/----I-----\n__\\|________\\|_______________________________|_|_|_|_|/_____===____\n3\n\n\n If you\'ll just get on\n board we\'ll get out of here.\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | +++ + |/----I-----\n__\\|________\\|________________________________|_|||_|_/_____===____\n3\n\n\n If you\'ll just get on\n board we\'ll get out of here.\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + :/----I-----\n__\\|________\\|_________________________________|_|_|_|/_____===____\n3\n\n\n If you\'ll just get on\n board we\'ll get out of here.\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | ++ + |/----I-----\n__\\|________\\|__________________________________|||_|_/_____===____\n3\n\n\n If you\'ll just get on\n board we\'ll get out of here.\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + + :/----I-----\n__\\|________\\|___________________________________|_|_|/_____===____\n3\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + |/----I-----\n__\\|________\\|___________________________________||_|_/_____===____\n3\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + + :/----I-----\n__\\|________\\|___________________________________|_|_|/_____===____\n3\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + |/----I-----\n__\\|________\\|___________________________________|__|_/_____===____\n2\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + :/----I-----\n__\\|________\\|___________________________________|___|/_____===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ /+\\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + :/----I-----\n__\\|________\\|___________________________________|___|/_____===____\n3\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ /+\\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + |/----I-----\n__\\|________\\|___________________________________|____/_____===____\n3\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ /+\\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + :/----I-----\n__\\|________\\|____________________________________|___/_____===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ /+\\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + :/----I-----\n__\\|________\\|_____________________________________|__/_____===____\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n /__\\ /__\\ /~~\\\n |<><>| |<><>| (O^O)\\\n (_/\\_) (_/\\_) / //, \\\\\n / \\ / \\ / //, \\\n ||/(===o //| __ |\\\\ / O\' \\\n | / \\ | // |/ \\| \\\\ /./| /|\\ |\n \\/][][\\/ // [][][] || // |\\ / | ||\n |\\ /| |\' |\\ /| [\' (# | | | \')\n |_||_| |_||_| I] | | |\n [ ][ ] [ ][ ] I | | |\n | || | | || | / | \\\n |_||_| |_||_| / _| \\\n______[_][_]_________[_][_]_________________________/__[_]_____\\___\n20\n /__\\ /__\\ /~~\\\n |<><>| |<><>| Which way? (O^O)\\\n (_/\\_) (_/\\_) / //, \\\\\n / \\ / \\ / //, \\\n ||/(===o //| __ |\\\\ / O\' \\\n | / \\ | // |/ \\| \\\\ /./| /|\\ |\n \\/][][\\/ // [][][] || // |\\ / | ||\n |\\ /| |\' |\\ /| [\' (# | | | \')\n |_||_| |_||_| I] | | |\n [ ][ ] [ ][ ] I | | |\n | || | | || | / | \\\n |_||_| |_||_| / _| \\\n______[_][_]_________[_][_]_________________________/__[_]_____\\___\n12\n /__\\ /__\\ /~~\\\n |<><>| |<><>| Which way? (O^O)\\\n (_/\\_) (_/\\_) / //, \\\\\n / \\ / \\ / //, \\\n ||/(===o //| __ |\\\\ / O\' \\\n | / \\ | // |/ \\| \\\\ /./| /|\\.\\\n \\/][][\\/ // [][][] || // |\\ / | \\\\\n |\\ /| |\' |\\ /| [\' (# | | | \')\n |_||_| |_||_| I] | | |\n [ ][ ] [ ][ ] I | | |\n | || | | || | / | \\\n |_||_| |_||_| / _| \\\n______[_][_]_________[_][_]_________________________/__[_]_____\\___\n6\n /__\\ /__\\ /~~\\\n |<><>| |<><>| (O^O)\\\n (_/\\_) (_/\\_) / //, \\\\\n / \\ / \\ / //, \\\n ||/(===o //| __ |\\\\ / O\' \\\n | / \\ | // |/ \\| \\\\ /./| /|\\.\\\n \\/][][\\/ // [][][] || // |\\ / | \\\\\n |\\ /| |\' |\\ /| [\' (# | | | \')\n |_||_| |_||_| I] | | |\n [ ][ ] [ ][ ] I | | |\n | || | | || | / | \\\n |_||_| |_||_| / _| \\\n______[_][_]_________[_][_]_________________________/__[_]_____\\___\n5\n\n\n\n\n\n\n\n\n\n\n\n\n\n7\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | + :/----I-----\n__\\|________\\|_____________________________________|__/_____===____\n2\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ /|\\ \\ |-O-| | | |\n | || \\ | \\_/___|_________|__|\n | | \\ | + :/----I-----\n__\\|________\\|_____________________________________|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ /|o \\ |-O-| | | |\n | ||o| \\ | \\_/___|_________|__|\n | | | \\ | + :/----I-----\n__\\|________\\|_____________________________________|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / o \\ |-O-| | | |\n | ||o|o\\ | \\_/___|_________|__|\n | | |o| \\ | + :/----I-----\n__\\|__|_____\\|_____________________________________|__/_____===____\n2\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ /oo \\ |-O-| | | |\n | | || \\ | \\_/___|_________|__|\n | | o o o\\ | + :/----I-----\n__\\|_|_|_|__\\|_____________________________________|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ /oo \\ |-O-| | | |\n | | || \\ | \\_/___|_________|__|\n | | o o o | + :/----I-----\n__\\|__|_|_|_\\|_____________________________________|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | oo \\ | \\_/___|_________|__|\n | | ||o o\\o | + :/----I-----\n__\\|___|_|_|\\|_____________________________________|__/_____===____\n2\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | oo o o o| + :/----I-----\n__\\|_||_|_|_||_____________________________________|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | oo o\\o o + :/----I-----\n__\\|__||_|_|_|_____________________________________|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | o o o o|o + :/----I-----\n__\\|__|_|_|_|||____________________________________|__/_____===____\n2\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | o o\\o o o + :/----I-----\n__\\|___|_|_|_|_|___________________________________|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | o o o|o o + :/----I-----\n__\\|____|_|_|||_|__________________________________|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | o\\o o o o + :/----I-----\n__\\|_____|_|_|_|_|_________________________________|__/_____===____\n2\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | o o|o o o + :/----I-----\n__\\|______|_|||_|_|________________________________|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\o o o o o + :/----I-----\n__\\|_______|_|_|_|_|_______________________________|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ o|o o o o + :/----I-----\n__\\|________|_|_|_|_|______________________________|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ o o o o o + :/----I-----\n__\\|________\\|_|_|_|_|_____________________________|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ o o o o o* + :/----I-----\n__\\|________\\|_|_|_|_|_____________________________|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ |o o o o o --- + :/----I-----\n__\\|________\\||_|_|_|_|____________________________|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o o o o --- + :/----I-----\n__\\|________\\|_|_|_|_|_|__________________________*|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o o o o --- --- + :/----I-----\n__\\|________\\|__|_|_|_|_|__________________________|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o o o o --- --- + :/----I-----\n__\\|________\\|__|_|_|_|_|__________________________|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o o o o --- * + :/----I-----\n__\\|________\\|___|_|_|_|_|_________________________|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | . \' \\_/___|_________|__|\n | | \\ | o o o o.*--- \'. \' + :/----I-----\n__\\|________\\|____|_|_|_|_|________________________|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o o.o . . .+ :/----I-----\n__\\|________\\|_____|_|_|o|_____________________.___|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o o o + :/----I-----\n__\\|________\\|_____|_|_|o|__.________________._____|._/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o o o* + :/----I-----\n__\\|________\\|______|_|_|_|________________________|__/_____===____\n1\n\n\n Stop that ship!\n\n Blast em!\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o o o --- + :/----I-----\n__\\|________\\|_______|_|o|_|_______________________|__/_____===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o o o --- + :/----I-----\n__\\|________\\|_______|_|o|_|______________________*|__/_____===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o o o ---* + :/----I-----\n__\\|________\\|_______|_|o|_|_______________________|__/_____===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o o o --- :. .+ :/----I-----\n__\\|________\\|_______|_|o|_|_______________________|__/_____===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | .\\_/___|_________|__|\n | | \\ | o o o o --- . + :/----I-----\n__\\|________\\|_______|_|o|_|________________.__.__.|__/_____===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | . . . \\_/___|_________|__|\n | | \\ | o o o *-- + :/----I-----\n__\\|________\\|_______|_|o|_|______________.________|__/_____===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | . \\_/___|_________|__|\n | | \\ | o o o * . + :/----I-----\n__\\|________\\|_______|_|o|_|_._____________________|__/_____===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | .o o o + :/----I-----\n__\\|________\\|_______|_|o|_o__________.____________|__/_____===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o o *+ :/----I-----\n__\\|________\\|_____._|_|o|_o________________________|_/_____===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o o --- + :/----I-----\n__\\|________\\|_______|_|o|_o_________________________|/_____===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o o* --- |/----I-----\n__\\|________\\|_______|_|o|_o__________________________/_____===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o o --- --- :/----I-----\n__\\|________\\|_______|_|o|_o__________________________/_____===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o o --- --- :/----I-----\n__\\|________\\|_______|_|o|_o__________________________/_____===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o *- --- ----I-----\n__\\|________\\|_______|_|o|_o________________________________===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \' \\_/___|_________|__|\n | | \\ | o o * . --- ----I-----\n__\\|________\\|_______|_|o|_o________________________________===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | . \\_/___|_________|__|\n | | \\ | o o --*----I-----\n__\\|________\\|_______|_|oo_o_.______________________________===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | . o o : ***---I-----\n__\\|________\\|_______|_|oo_o__________________________\'___"_===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o *---I-----\n__\\|________\\|____.__|_|oo_o_______________________"_.____._===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | . o o ----I-----\n__\\|________\\|_______|_|oo_o______________________._________===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o . ----I-----\n__\\|________\\|__.____|_|oo_o________________________________===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o ----I-----\n__\\|________\\|_._____|_|oo_o____________________.___________===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o ----I-----\n__\\|________\\|_._____|_|oo_o___________________.____________===____\n1\n\n\n\n\n\n _\n ________|_\n _______ _ ___ -------------\n / \\______\\ / \\ | | |\n |\\ / \\ \\ |-O-| | | |\n | | \\ | \\_/___|_________|__|\n | | \\ | o o ----I-----\n__\\|________\\|_._____|_|oo_o__________________._____________===____\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n3\n\n\n\n\n\n\n\n __________________________\n_ |--------------------------\n_|__ I | o o o o\n \\ .I. |\nO O |-. |I| o o o | __\n_____|_|____/[_]\\_____|_|_|_____________|__|__|____________________\n3\n\n\n\n\n\n\n\n __________________________\n_ |--------------------------\n_|__ I | o o o o\n \\ .I. |\nO O |-. |I| o o o | __\n_____|_|____/[_]\\______|_|_|____________|__|__|____________________\n10\n\n\n\n\n\n\n\n __________________________\n_ |--------------------------\n_|__ I | o o o o\n \\ .I. |\nO O |-. |I| o o o | __\n_____|_|____/[_]\\_______|_|_|___________|__|__|____________________\n1\n\n\n\n\n\n\n\n ___________-----_O________\n_ |--------------------------\n_|__ I | o o o o\n \\ .I. |\nO O |-. |I| o o o | __\n_____|_|____/[_]\\_______|_|_|___________|__|__|____________________\n1\n\n\n\n\n\n\n _ ____-----_O___\n ____(_)====[ ]======____\n_ |--------------------------\n_|__ I | o o o o\n \\ .I. |\nO O |-. |I| o o o | __\n_____|_|____/[_]\\_______|_|_|___________|__|__|____________________\n1\n\n\n\n\n\n _ ____-----_O___\n (_)====[ ]======\n _______~~~~-----~~~~~_____\n_ |--------------------------\n_|__ I | o o o o\n \\ .I. |\nO O |-. |I| o o o | __\n_____|_|____/[_]\\_______|_|_|___________|__|__|____________________\n1\n\n\n\n\n _ ____-----_O___\n (_)====[ ]======\n ~~~~-----~~~~~\n ________^____^____^_______\n_ |--------------------------\n_|__ I | o o o o\n \\ .I. |\nO O |-. |I| o o o | __\n_____|_|____/[_]\\_______|_|_|___________|__|__|____________________\n1\n\n\n\n _ ____-----_O___\n (_)====[ ]======\n ~~~~-----~~~~~\n ^ ^ ^\n __________________________\n_ |--------------------------\n_|__ I | o o o o\n \\ .I. |\nO O |-. |I| o o o | __\n_____|_|____/[_]\\_______|_|_|___________|__|__|____________________\n1\n\n\n _ ____-----_O___\n (_)====[ ]======\n ~~~~-----~~~~~\n ^ ^ ^\n\n __________________________\n_ |--------------------------\n_|__ I | o o o o\n \\ .I. |\nO O |-. |I| o o o | __\n_____|_|____/[_]\\_______|_|_|___________|__|__|____________________\n1\n\n _ ____-----_O___\n (_)====[ ]======\n ~~~~-----~~~~~\n ^ ^ ^\n\n\n __________________________\n_ |--------------------------\n_|__ I | o o o o\n \\ .I. |\nO O |-. |I| o o o | __\n_____|_|____/[_]\\_______|_|_|___________|__|__|____________________\n1\n _ ____-----_O___\n (_)====[ ]======\n ~~~~-----~~~~~\n ^ ^ ^\n\n\n\n __________________________\n_ |--------------------------\n_|__ I | o o o o\n \\ .I. |\nO O |-. |I| o o o | __\n_____|_|____/[_]\\_______|_|_|___________|__|__|____________________\n1\n (_)====[ ]======\n ~~~~-----~~~~~\n ^ ^ ^\n\n\n\n\n __________________________\n_ |--------------------------\n_|__ I | o o o o\n \\ .I. |\nO O |-. |I| o o o | __\n_____|_|____/[_]\\_______|_|_|___________|__|__|____________________\n1\n ~~~~-----~~~~~\n ^ ^ ^\n\n\n\n\n\n __________________________\n_ |--------------------------\n_|__ I | o o o o\n \\ .I. |\nO O |-. |I| o o o | __\n_____|_|____/[_]\\_______|_|_|___________|__|__|____________________\n1\n ^ ^ ^\n\n\n\n\n\n\n __________________________\n_ |--------------------------\n_|__ I | o o o o\n \\ .I. |\nO O |-. |I| o o o | __\n_____|_|____/[_]\\_______|_|_|___________|__|__|____________________\n6\n\n\n\n\n\n\n\n __________________________\n_ |--------------------------\n_|__ I | o o o o\n \\ .I. |\nO O |-. |I| o o o | __\n_____|_|____/[_]\\_______|_|_|___________|__|__|____________________\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n . . __---__ .\n . . . .-\'...:...\'-. .\n . / .__. : . . \\\n . . /. / \\.........\\ . . .\n / :| () |: : :\\\n . :....\\__/...........: .\n . . |___________________|\n |...................| . .\n . . : : : : : : :\n . \\................./ . .\n . \\ . . : . . / .\n . . . \\._........._./ . .\n -..___..- .\n2\n . . __---__ .\n . . . .-\'...:...\'-. .\n . / .__. : . . \\\n. . . /. / \\.........\\ . . .\n / :| () |: : :\\\n . :....\\__/...........: .\n . . |___________________|\n |...................| . .\n . . : : : : : : :\n . \\................./ . .\n . \\ . . : . . / .\n . . . \\._........._./ . .\n -..___..- .\n2\n . . __---__ .\n . . . .-\'...:...\'-. .\n . / .__. : . . \\\n . . . /. / \\.........\\ . . .\n / :| () |: : :\\\n . :....\\__/...........: .\n . . |___________________|\n |...................| .\n . . : : : : : : :\n. . \\................./ . .\n . \\ . . : . . / .\n . . . \\._........._./ . .\n -..___..- .\n2\n . . __---__ .\n . . . .-\'...:...\'-. .\n . / .__. : . . \\\n . . . /. / \\.........\\ . . .\n / :| () |: : :\\\n . :....\\__/...........: .\n . . |___________________|\n |...................| .\n . . : : : : : : :\n . . \\................./ . .\n . \\ . . : . . / .\n . . . \\._........._./ . .\n -..___..- .\n2\n . . __---__ .\n . . . .-\'...:...\'-. .\n . / .__. : . . \\\n . . . /. / \\.........\\ . . .\n / :| () |: : :\\\n . :....\\__/...........: .\n . . |___________________|\n |...................| .\n . . : : : : : : :\n . . \\................./ . .\n . \\ . . : . . / .\n . . . \\._........._./ . .\n -..___..- .\n2\n . . __---__ .\n . . . .-\'...:...\'-. .\n . / .__. : . . \\\n . . . /. / \\.........\\ . .\n. / :| () |: : :\\\n8 . :....\\__/...........: .\n8 . . |___________________|\n\' |...................| .\n . . : : : : : : :\n . . \\................./ .\n . \\ . . : . . / .\n . . . \\._........._./ . .\n. -..___..- .\n2\n . . __---__ .\n. . . . .-\'...:...\'-. .\n . / .__. : . . \\\n . . . /. / \\.........\\ . .\n8. / :| () |: : :\\\n88 . :....\\__/...........: .\n88 . . |___________________|\n8\' |...................| .\n . . : : : : : : :\n . . \\................./ .\n . \\ . . : . . / .\n . . . \\._........._./ . .\n . -..___..- .\n2\n . . __---__ .\n . . . . .-\'...:...\'-. .\n . / .__. : . . \\\n. . . . /. / \\.........\\ . .\n88. / :| () |: : :\\\n888 . :....\\__/...........: .\n888 . . |___________________|\n88\' |...................| .\n\' . . : : : : : : :\n . . \\................./ .\n. . \\ . . : . . / .\n . . . \\._........._./ . .\n . -..___..- .\n2\n . . __---__ .\n . . . . .-\'...:...\'-. .\n . / .__. : . . \\\n.. . . . /. / \\.........\\ . .\n888. / :| () |: : :\\\n8888 . :....\\__/...........: .\n8888 . . |___________________|\n888\' |...................|\n\'\' . . : : : : : : :\n . . \\................./ .\n . . \\ . . : . . / .\n . . . \\._........._./ . .\n . -..___..- .\n2\n . . __---__ .\n . . . . .-\'...:...\'-. .\n . / .__. : . . \\\n .. . . . /. / \\.........\\ . .\n8888. / :| () |: : :\\\n88888 . :....\\__/...........: .\n88888 . . |___________________|\n8888\' |...................|\n \'\' . . : : : : : : :\n . . \\................./ .\n . . \\ . . : . . / .\n. . . . \\._........._./ . .\n . -..___..- .\n2\n . . __---__ .\n. . . . . .-\'...:...\'-. .\n . / .__. : . . \\\n .. . . . /. / \\.........\\ . .\n.8888. / :| () |: : :\\\n888888 . :....\\__/...........: .\n888888 . . |___________________|\n\'8888\' |...................|\n \'\' . . : : : : : : :\n . . \\................./ .\n . . \\ . . : . . / .\n . . . . \\._........._./ . .\n . -..___..- .\n2\n . . __---__ .\n . . . . . .-\'...:...\'-. .\n . / .__. : . . \\\n .. . . . /. / \\.........\\ . .\n .8888. / :| () |: : :\\\n 888888 . :....\\__/...........: .\n 888888 . . |___________________|\n \'8888\' |...................|\n \'\' . . : : : : : : :\n . . \\................./ .\n . . \\ . . : . . / .\n . . . . \\._........._./ . .\n . -..___..- .\n2\n . . __---__ .\n . . . . . .-\'...:...\'-.\n . / .__. : . . \\\n. .. . . . /. / \\.........\\ . .\n .8888. / :| () |: : :\\\n 888888 . :....\\__/...........: .\n 888888 . . |___________________|\n \'8888\' |...................|\n. \'\' . . : : : : : : :\n . . \\................./ .\n . . \\ . . : . . / .\n . . . . \\._........._./ . .\n. . -..___..- .\n2\n . . __---__ .\n . . . . . .-\'...:...\'-.\n . / .__. : . . \\\n . .. . . . /. / \\.........\\ . .\n .8888. / :| () |: : :\\\n 888888 . :....\\__/...........: .\n 888888 . . |___________________|\n \'8888\' |...................|\n . \'\' . . : : : : : : :\n . . \\................./ .\n . . \\ . . : . . / .\n . . . . \\._........._./ . .\n . . -..___..-\n2\n. . . __---__ .\n . . . . . .-\'...:...\'-.\n . / .__. : . . \\\n . .. . . . /. / \\.........\\ . .\n .8888. / :| () |: : :\\\n 888888 . :....\\__/...........:\n 888888 . . |___________________|\n \'8888\' |...................|\n . \'\' . . : : : : : : :\n . . \\................./ .\n. . . \\ . . : . . / .\n . . . . \\._........._./ . .\n . . -..___..-\n2\n . . . __---__ .\n . . . . . .-\'...:...\'-.\n . / .__. : . . \\\n . .. . . . /. / \\.........\\ . .\n .8888. / :| () |: : :\\\n. 888888 . :....\\__/...........:\n 888888 . . |___________________|\n \'8888\' |...................|\n . \'\' . . : : : : : : :\n . . \\................./ .\n . . . \\ . . : . . / .\n. . . . . \\._........._./ .\n . . -..___..-\n1\n . . . __---__ .\n . . . . . .-\'...:...\'-.\n . / .__. : . . \\\n . .. . . . /. / \\.........\\ . .\n .8888. / :| () |: : :\\\n . 888888 . :....\\__/...........:\n 888888 . . |___________________|\n \'8888\' |...................|\n . \'\' . . : : : : : : :\n . . \\................./ .\n . . . \\ . . : . . / .\n . . . . . \\._........._./ .\n . . -..___..-\n1\n . . . __---__ .\n . . . . . .-\'...:...\'-.\n . / .__. : . . \\\n . .. . . . /. / \\.........\\ . .\n .8888. / :| () |: : :\\\n . 888888 . :....\\__/...........:\n 888888 . . |___________________|\n. \'8888\' |...................|\n . \'\' . . : : : : : : :\n . . \\................./ .\n . . . \\ . . : . . / .\n . . . . . \\._........._./ .\n . . -..___..-\n7\n . . . __---__ .\n . . . . . .-\'...:...\'-.\n. . / .__. : . . \\\n . .. . . . /. / \\.........\\ . .\n .8888. / :| () |: : :\\\n . 888888 . :....\\__/...........:\n 888888 . . |___________________|\n . \'8888\' |...................|\n . \'\' . . : : : : : : :\n . . \\................./ .\n . . . \\ . . : . . / .\n . . . . . \\._........._./ .\n . . -..___..-\n1\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n | |\n | |\n | .@@. |\n | @@@@ |\n | `@@\' |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n3\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n We\'ve | |\n entered | |\n the | .@@. |\n Alderaan | @@@@ |\n system. | `@@\' |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n3\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n We\'ve | |\n entered | |\n the | .@@. |\n Alderaan | @@@@ |\n system. | `@@\' |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n3\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n We\'ve | |\n entered | |\n the | .@@. |\n Alderaan | @@@@ |\n system. | `@@\' |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n4\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n We\'ve | |\n entered | |\n the | .@@. |\n Alderaan | @@@@ |\n system. | `@@\' |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n20\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n We\'ve | |\n entered | |\n the | .@@. |\n Alderaan | @@@@ |\n system. | `@@\' |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n6\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n | |\n | |\n | .@@. |\n | @@@@ |\n | `@@\' |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n5\n /~~\\\n ==== ===, |<><>|\n | o o @o o@) /_/\\_\\\n _\\ -/_ \\- / /\\___/\\\n /"\'==\'"\\ /~~ ~~\\ //|[ ] \\\\\n | /|:::|\\\\ / ( ) \\ // |[_] |\\\\\n |||| | \\\\ /_/\\ /\\_| \\\\ | |//\n |||| | () || \\\\ // || \\#|====#/\n ()|-==-| @ | | | @ /|\\ /I\\\n |----| | | | / | || I \\\n | || | | | | / | || | \\\n | || | / | \\ / | || | \\\n | || | ~~~~~~~~~ / | || | \\\n23\n I grow tired /~~\\\n ==== of asking this ===, |<><>|\n | o o so it will @o o@) /_/\\_\\\n _\\ -/_ be the last time. \\- / /\\___/\\\n /"\'==\'"\\ /~~ ~~\\ //|[ ] \\\\\n | /|:::|\\\\ / ( ) \\ // |[_] |\\\\\n |||| | \\\\ /_/\\ /\\_| \\\\ | |//\n |||| | () || \\\\ // || \\#|====#/\n ()|-==-| @ | | | @ /|\\ /I\\\n |----| | | | / | || I \\\n | || | | | | / | || | \\\n | || | / | \\ / | || | \\\n | || | ~~~~~~~~~ / | || | \\\n12\n I grow tired /~~\\\n ==== of asking this ===, |<><>|\n | o o so it will @o o@) /_/\\_\\\n _\\ -/_ be the last time. \\- / /\\___/\\\n /"\'==\'"\\ /~~ ~~\\ //|[ ] \\\\\n / /|:::|\\\\ / ( ) \\ // |[_] |\\\\\n \\\\|| |// /_/\\ /\\_| \\\\ | |//\n \\(| )/ || \\\\ // || \\#|====#/\n |-==-| @ | | | @ /|\\ /I\\\n |----| | | | / | || I \\\n | || | | | | / | || | \\\n | || | / | \\ / | || | \\\n | || | ~~~~~~~~~ / | || | \\\n1\n /~~\\\n ==== ===, |<><>|\n | o o @o o@) /_/\\_\\\n _\\ -/_ \\- / /\\___/\\\n /"\'==\'"\\ /~~ ~~\\ //|[ ] \\\\\n / /|:::|\\\\ / ( ) \\ // |[_] |\\\\\n \\\\|| |// /_/\\ /\\_| \\\\ | |//\n \\(| )/ || \\\\ // || \\#|====#/\n |-==-| @ | | | @ /|\\ /I\\\n |----| | | | / | || I \\\n | || | | | | / | || | \\\n | || | / | \\ / | || | \\\n | || | ~~~~~~~~~ / | || | \\\n22\n Where is the /~~\\\n ==== Rebel Base? ===, |<><>|\n | o o @o o@) /_/\\_\\\n _\\ -/_ \\- / /\\___/\\\n /"\'==\'"\\ /~~ ~~\\ //|[ ] \\\\\n / /|:::|\\\\ / ( ) \\ // |[_] |\\\\\n \\\\|| |// /_/\\ /\\_| \\\\ | |//\n \\(| )/ || \\\\ // || \\#|====#/\n |-==-| @ | | | @ /|\\ /I\\\n |----| | | | / | || I \\\n | || | | | | / | || | \\\n | || | / | \\ / | || | \\\n | || | ~~~~~~~~~ / | || | \\\n8\n Where is the /~~\\\n ==== Rebel Base? ===, |<><>|\n | o o @o o@) /_/\\_\\\n _\\ -/_ \\- / /\\___/\\\n /"\'==\'"\\ /~~ ~~\\ //|[ ] \\\\\n | /|:::|\\\\ / ( ) \\ // |[_] |\\\\\n |||| | \\\\ /_/\\ /\\_| \\\\ | |//\n |||| | () || \\\\ // || \\#|====#/\n ()|-==-| @ | | | @ /|\\ /I\\\n |----| | | | / | || I \\\n | || | | | | / | || | \\\n | || | / | \\ / | || | \\\n | || | ~~~~~~~~~ / | || | \\\n11\n /~~\\\n ==== ===, |<><>|\n | o o @o o@) /_/\\_\\\n _\\ -/_ \\- / /\\___/\\\n /"\'==\'"\\ /~~ ~~\\ //|[ ] \\\\\n | /|:::|\\\\ / ( ) \\ // |[_] |\\\\\n |||| | \\\\ /_/\\ /\\_| \\\\ | |//\n |||| | () || \\\\ // || \\#|====#/\n ()|-==-| @ | | | @ /|\\ /I\\\n |----| | | | / | || I \\\n | || | | | | / | || | \\\n | || | / | \\ / | || | \\\n | || | ~~~~~~~~~ / | || | \\\n30\n /~~\\\n ==== Dantooine. ===, |<><>|\n | o o @o o@) /_/\\_\\\n _\\ -/_ \\- / /\\___/\\\n /"\'==\'"\\ /~~ ~~\\ //|[ ] \\\\\n | /|:::|\\\\ / ( ) \\ // |[_] |\\\\\n |||| | \\\\ /_/\\ /\\_| \\\\ | |//\n |||| | () || \\\\ // || \\#|====#/\n ()|-==-| @ | | | @ /|\\ /I\\\n |----| | | | / | || I \\\n | || | | | | / | || | \\\n | || | / | \\ / | || | \\\n | || | ~~~~~~~~~ / | || | \\\n1\n /~~\\\n ==== ===, |<><>|\n | o o @o o@) /_/\\_\\\n _\\ -/_ \\- / /\\___/\\\n /"\'==\'"\\ /~~ ~~\\ //|[ ] \\\\\n | /|:::|\\\\ / ( ) \\ // |[_] |\\\\\n |||| | \\\\ /_/\\ /\\_| \\\\ | |//\n |||| | () || \\\\ // || \\#|====#/\n ()|-==-| @ | | | @ /|\\ /I\\\n |----| | | | / | || I \\\n | || | | | | / | || | \\\n | || | / | \\ / | || | \\\n | || | ~~~~~~~~~ / | || | \\\n4\n /~~\\\n ==== They\'re on ===, |<><>|\n | o o Dantooine. @o o@) /_/\\_\\\n _\\ -/_ \\- / /\\___/\\\n /"\'==\'"\\ /~~ ~~\\ //|[ ] \\\\\n | /|:::|\\\\ / ( ) \\ // |[_] |\\\\\n |||| | \\\\ /_/\\ /\\_| \\\\ | |//\n |||| | () || \\\\ // || \\#|====#/\n ()|-==-| @ | | | @ /|\\ /I\\\n |----| | | | / | || I \\\n | || | | | | / | || | \\\n | || | / | \\ / | || | \\\n | || | ~~~~~~~~~ / | || | \\\n28\n /~~\\\n ==== They\'re on ===, |<><>|\n | o o Dantooine. @- -@) /_/\\_\\\n _\\ -/_ \\- / /\\___/\\\n /"\'==\'"\\ /~~ ~~\\ //|[ ] \\\\\n | /|:::|\\\\ / ( ) \\ // |[_] |\\\\\n |||| | \\\\ /_/\\ /\\_| \\\\ | |//\n |||| | () || \\\\ // || \\#|====#/\n ()|-==-| @ | | | @ /|\\ /I\\\n |----| | | | / | || I \\\n | || | | | | / | || | \\\n | || | / | \\ / | || | \\\n | || | ~~~~~~~~~ / | || | \\\n4\n /~~\\\n ==== ===, |<><>|\n | o o @o o@) /_/\\_\\\n _\\ -/_ \\- / /\\___/\\\n /"\'==\'"\\ /~~ ~~\\ //|[ ] \\\\\n | /|:::|\\\\ / ( ) \\ // |[_] |\\\\\n |||| | \\\\ /_/\\ /\\_| \\\\ | |//\n |||| | () || \\\\ // || \\#|====#/\n ()|-==-| @ | | | @ /|\\ /I\\\n |----| | | | / | || I \\\n | || | | | | / | || | \\\n | || | / | \\ / | || | \\\n | || | ~~~~~~~~~ / | || | \\\n4\n You see, Lord /~~\\\n ==== Vader, she can ===, |<><>|\n | o o be reasonable. @o o@) /_/\\_\\\n _\\ -/_ \\- / /\\___/\\\n /"\'==\'"\\ /~~ ~~\\ //|[ ] \\\\\n | /|:::|\\\\ / ( ) \\ // |[_] |\\\\\n |||| | \\\\ /_/\\ /\\_| \\\\ | |//\n |||| | () || \\\\ // || \\#|====#/\n ()|-==-| @ | | | @ /|\\ /I\\\n |----| | | | / | || I \\\n | || | | | | / | || | \\\n | || | / | \\ / | || | \\\n | || | ~~~~~~~~~ / | || | \\\n7\n You see, Lord /~~\\\n ==== Vader, she can ===, |<><>|\n | o o be reasonable. @o o@) /_/\\_\\\n _\\ -/_ \\- / /\\___/\\\n /"\'==\'"\\ /~~ ~~\\ //|[ ] \\\\\n / /|:::|\\\\ / ( ) \\ // |[_] |\\\\\n \\\\|| | \\\\ /_/\\ /\\_| \\\\ | |//\n \\\\| | () || \\\\ // || \\#|====#/\n \')==-| @ | | | @ /|\\ /I\\\n |----| | | | / | || I \\\n | || | | | | / | || | \\\n | || | / | \\ / | || | \\\n | || | ~~~~~~~~~ / | || | \\\n22\n You see, Lord /~~\\\n ==== Vader, she can ===, |<><>|\n | o o be reasonable. @o o@) /_/\\_\\\n _\\ -/_ \\- / /\\___/\\\n /"\'==\'"\\ /~~ ~~\\ //|[ ] \\\\\n / /|:::|\\\\ / ( ) \\ // |[_] |\\\\\n \\\\|| | \\\\ /_/\\ /\\_| \\\\ | |//\n \\\\| | () || \\\\ // || \\#|====#/\n \')==-| @ | | | @ /|\\ /I\\\n |----| | | | / | || I \\\n | || | | | | / | || | \\\n | || | / | \\ / | || | \\\n | || | ~~~~~~~~~ / | || | \\\n2\n /~~\\\n ==== ===, |<><>|\n | o o @o o@) /_/\\_\\\n _\\ -/_ \\- / /\\___/\\\n /"\'==\'"\\ /~~ ~~\\ //|[ ] \\\\\n / /|:::|\\\\ / ( ) \\ // |[_] |\\\\\n \\\\|| | \\\\ /_/\\ /\\_| \\\\ | |//\n \\\\| | () || \\\\ // || \\#|====#/\n \')==-| @ | | | @ /|\\ /I\\\n |----| | | | / | || I \\\n | || | | | | / | || | \\\n | || | / | \\ / | || | \\\n | || | ~~~~~~~~~ / | || | \\\n28\n Proceed with /~~\\\n ==== the ===, |<><>|\n | o o demonstration! @o o@) /_/\\_\\\n _\\ -/_ \\- / /\\___/\\\n /"\'==\'"\\ /~~ ~~\\ //|[ ] \\\\\n / /|:::|\\\\ / ( ) \\ // |[_] |\\\\\n \\\\|| | \\\\ /_/\\ /\\_| \\\\ | |//\n \\\\| | () || \\\\ // || \\#|====#/\n \')==-| @ | | | @ /|\\ /I\\\n |----| | | | / | || I \\\n | || | | | | / | || | \\\n | || | / | \\ / | || | \\\n | || | ~~~~~~~~~ / | || | \\\n1\n Proceed with /~~\\\n ==== the ===, |<><>|\n | o o demonstration! @O O@) /_/\\_\\\n _\\ -/_ \\- / /\\___/\\\n /"\'==\'"\\ /~~ ~~\\ //|[ ] \\\\\n / /|:::|\\\\ / ( ) \\ // |[_] |\\\\\n \\\\|| | \\\\ /_/\\ /\\_| \\\\ | |//\n \\\\| | () || \\\\ // || \\#|====#/\n \')==-| @ | | | @ /|\\ /I\\\n |----| | | | / | || I \\\n | || | | | | / | || | \\\n | || | / | \\ / | || | \\\n | || | ~~~~~~~~~ / | || | \\\n1\n Proceed with /~~\\\n ==== the ===, |<><>|\n | o o demonstration! @O O@) /_/\\_\\\n _\\ -/_ \\o / /\\___/\\\n /"\'==\'"\\ /~~ ~~\\ //|[ ] \\\\\n / /|:::|\\\\ / ( ) \\ // |[_] |\\\\\n \\\\|| | \\\\ /_/\\ /\\_| \\\\ | |//\n \\\\| | () || \\\\ // || \\#|====#/\n \')==-| @ | | | @ /|\\ /I\\\n |----| | | | / | || I \\\n | || | | | | / | || | \\\n | || | / | \\ / | || | \\\n | || | ~~~~~~~~~ / | || | \\\n3\n /~~\\\n ==== ===, |<><>|\n | o o @o o@) /_/\\_\\\n _\\ -/_ \\o / /\\___/\\\n /"\'==\'"\\ /~~ ~~\\ //|[ ] \\\\\n / /|:::|\\\\ / ( ) \\ // |[_] |\\\\\n \\\\|| | \\\\ /_/\\ /\\_| \\\\ | |//\n \\\\| | () || \\\\ // || \\#|====#/\n \')==-| @ | | | @ /|\\ /I\\\n |----| | | | / | || I \\\n | || | | | | / | || | \\\n | || | / | \\ / | || | \\\n | || | ~~~~~~~~~ / | || | \\\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n33\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n | |\n You | |\n may fire | .@@. |\nwhen ready.| @@@@ |\n | `@@\' |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n1\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n | |\n | |\n | .@@. |\n | @@@@ |\n | `@@\' |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n31\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n | |\n | | What!\n | .@@. |\n | @@@@ |\n | `@@\' |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n3\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n | |\n | |\n | .@@. |\n | @@@@ |\n | `@@\' |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n2\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_, q q | / \\ |\n_[__|__|__ | | | |\n | | | | |\n | | | | |\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n2\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_, q q | / \\ |\n_[_|__|___ | | | |\n | | | | |\n | | | | |\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n3\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_,q q | / \\ |\n_[|__|____ | | | |\n | | | | |\n | | | | |\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\ |\n_[|__|____ | | | |\n | | | | |\n | | | | |\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\ |\n_[|__|____ | | | |\n | | | | | ......\n | | | | |\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\ |\n_[|__|____ | | | |\n | | | | | ............\n | | | | |\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\ |\n_[|__|____ | | | |\n | | | | ..................\n | | | | |\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\ |\n_[|__|____ | | | |\n | | | | ........................\n | | | | |\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\ |\n_[|__|____ | | | |\n | | | ...........................***\n | | | | |\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\ |\n_[|__|____ | | | |\n | | | .....................***...***\n | | | | |\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\ |\n_[|__|____ | | | |\n | | | ...............***...***...***\n | | | | |\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\ |\n_[|__|____ | | | |\n | | | .........***...***...****..***\n | | | | |\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\ |\n_[|__|____ | | | |\n | | | ...***...***...****..*****.***\n | | | | |\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\ |\n_[|__|____ | | | | **\n | | | ***|..***...****..*****..*****\n | | | | | **\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\ |\n_[|__|____ | | | | ******\n | | | **...****..*****..************\n | | | | | ******\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\ |\n_[|__|____ | | | ****** *******\n | | | *..*****..********************\n | | | | ****** *******\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\ |\n_[|__|____ | | |****** ****************\n | | | .*****************************\n | | | |****** ****************\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\ |\n_[|__|____ | | |****************\n | | | ******************************\n | | | |****************\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\ |\n_[|__|____ | | ******** |\n | | | ******************************\n | | | ******** |\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n2\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\ |\n_[|__|____ | | | |\n | | | ******************************\n | | | | |\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\ |\n_[|__|____ | | ..|.........|................\n | | | ******************************\n | | | \'\'|\'\'\'\'\'\'\'\'\'|\'\'\'\'\'\'\'\'\'\'\'\'\'\'\'\'\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\..........|..............\n_[|__|____ | | ****************************\n | | | ******************************\n | | | ****************************\n | | \\.___./\'\'\'\'\'\'\'\'\'\'|\'\'\'\'\'\'\'\'\'\'\'\'\'\'\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / ***************************\n_[|__|____ | | *****************************\n | | | ******************************\n | | | *****************************\n | | \\.___.***************************\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. ***************************\n_.q q | / ****************************\n_[|__|____ | | *****************************\n | | | ******************************\n | | | *****************************\n | | \\.___.****************************\n | | / ***************************\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / *************************\n_[|__|____ | | *****************************\n | | | ******************************\n | | | *****************************\n | | \\.___.*************************\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\..........|......\n_[|__|____ | | **********************\n | | | ******************************\n | | | **********************\n | | \\.___./\'\'\'\'\'\'\'\'\'\'|\'\'\'\'\'\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n1\n ---------------------\n |. ./\' |\n | \\ ./\' |\n | \'\\ .___. /\' |\n_.q q | / \\ |\n_[|__|____ | | | |\n | | | ******************************\n | | | | |\n | | \\.___./ |\n | | / \\. |\n | | /\' \'\\. |\n | |\' \'\\. |\n | ---------------------|\n5\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n | |\n | |\n | .@@. |\n | @@@@ |\n | `@@\' |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n1\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n | |\n | |\n | .@@. |\n | @@@@ ----|\n | `@@\' |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n1\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n | |\n | |\n | .@@. |\n | @@@@ --------|\n | `@@\' |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n1\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n | |\n | |\n | .@@. |\n | @@@@ ------------|\n | `@@\' |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n1\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n | |\n | |\n | .@@. |\n | @@@@ ----------------|\n | `@@\' |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n1\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n | |\n | |\n | .@@. |\n | @**--------------------|\n | `@@\' |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n4\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n | |\n | |\n | .**. |\n | ****-------------------|\n | `**\' |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n1\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n | |\n | |\n | .**. |\n | ****--------------- |\n | `**\' |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n1\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n | |\n | |\n | .**. |\n | ****----------- |\n | `**\' |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n1\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n | |\n | ** |\n | **** |\n | ******------ |\n | **** |\n | ** |\n `-_____ _____-\'\n ----____ ____----\n ----______----\n1\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n | \' ** \' |\n | \' *****# |\n | :******** " |\n | **#******* |\n | ******** |\n | \' ****#* \' |\n `-_____ " ** _____-\'\n ----____ \' " ____----\n ----______----\n1\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | \' |\n | " ** \'# |\n | \' \' ****** \' |\n | ******** \' |\n | \' #********** |\n | ******** |\n | \' : ****** \' |\n `-_____ " ** " _____-\'\n ----____ \' # ____----\n ----______----\n1\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | \' " # |\n | " \' ** |\n | ****** \' |\n | ******** \' |\n | \' # **** **** |\n | ******** |\n | \' ****** |\n `-_____ : " ** \' _____-\'\n ----____ \' : " ____----\n ----______----\n1\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | \' * * |\n | " * ** * \' |\n | * ****** * |\n | * ** ** * \' |\n | \' # * ** ** * |\n | * ** ** * |\n | * ****** * |\n `-_____: " * ** * \' _____-\'\n ----____ * * " ____----\n ----_____-----\n1\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | " * * |\n | * * |\n | * **** * |\n | * ** ** * \' |\n |\' # * ** ** * |\n | * ** ** * |\n | * **** * |\n `-_____" * * _____-\'\n ----____ * * ____----\n ----_____-----\n1\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n | * * |\n | * ** * |\n | * **** * \'|\n | # * ** ** * |\n | * **** * |\n | * ** * |\n `-_____ * * _____-\'\n ----____ ____----\n ----_____-----\n1\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n | * * |\n | * \' " * |\n | * ** * |\n | * **** * |\n | * ** * |\n | * " * |\n `-_____ : _____-\'\n ----____ ____----\n ----_____-----\n1\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | . . |\n | |\n | |\n | |\n | ** |\n | |\n | |\n `-_____ . _____-\'\n ----____ : ____----\n ----_____-----\n9\n ______----______\n __---------| | | | | |---------__\n .|__|__|__|__|__|__|____|__|__|__|__|__|__|.\n | |\n | |\n | |\n | |\n | |\n | |\n | |\n `-_____ _____-\'\n ----____ ____----\n ----_____-----\n7\n\n\n\n\n\n\n\n\n\n\n\n\n\n1\n ==== _ ====\n ~~o o /o\\ (o o")\n _\\ -/_ \\_/ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | \\\\ / /| | |\\ |\n || | | | \\\\ || | | | ||\n (\' |====| =)== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n___________/__][__\\___________________________________/____|[_]_\\__\n1\n ==== _ ====\n ~~o o /o\\ (o o")\n _\\ -/_ \\_/ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | \\\\ / /| | |\\ |\n || | | | \\\\ || | | | ||\n (\' |====| =)== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n___________/__][__\\___________________________________/____|[_]_\\__\n3\n ==== _ ====\n ~~o o /o\\ (o o")\n _\\ -/_ \\_/ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | \\\\ / /| | |\\ |\n || | | | \\\\ || | | | ||\n (\' |====| =)== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n___________/__][__\\___________________________________/____|[_]_\\__\n1\n ==== _ ====\n ~~o o /o\\ (o o")\n _\\ -/_ \\_/ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | \\\\ / /| | |\\ |\n || | | | \\\\ || | | | ||\n (\' |====| =)== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n___________/__][__\\___________________________________/____|[_]_\\__\n1\n ==== _ ====\n ~~o o /o\\ (o o")\n _\\ -/_ \\_/ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | \\\\ / /| | |\\ |\n || | | | \\\\ || | | | ||\n (\' |====| =)== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n___________/__][__\\___________________________________/____|[_]_\\__\n2\n ==== _ ====\n ~~o o /o\\ (o o")\n _\\ -/_ \\_/ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | \\\\ / /| | |\\ |\n || | | | \\\\ || | | | ||\n (\' |====| =)== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n___________/__][__\\___________________________________/____|[_]_\\__\n1\n ==== _ ====\n ~~o o /o\\ (o o")\n _\\ -/_ \\_/ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | \\\\ / /| | |\\ |\n || | | | \\\\ || | | | ||\n (\' |====| =)== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n___________/__][__\\___________________________________/____|[_]_\\__\n1\n ==== _ ====\n ~~o o /o\\ (o o")\n _\\ -/_ \\_/ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | \\\\ / /| | |\\ |\n || | | | \\\\ || | | | ||\n (\' |====| =)== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n___________/__][__\\___________________________________/____|[_]_\\__\n3\n ==== _ ====\n ~~o o /o\\ (o o")\n _\\ -/_ \\_/ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | \\\\ / /| | |\\ |\n || | | | \\\\ || | | | ||\n (\' |====| =)== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n___________/__][__\\___________________________________/____|[_]_\\__\n1\n ==== _ ====\n ~~o o /o\\ (o o")\n _\\ -/_ \\_/ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | \\\\ / /| | |\\ |\n || | | | \\\\ || | | | ||\n (\' |====| =)== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n___________/__][__\\___________________________________/____|[_]_\\__\n1\n ==== _ ====\n ~~o o /o\\ (o o")\n _\\ -/_ \\_/ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | \\\\ / /| | |\\ |\n || | | | \\\\ || | | | ||\n (\' |====| =)== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n___________/__][__\\___________________________________/____|[_]_\\__\n3\n ==== _ ====\n ~~o o /o\\ (o o")\n _\\ -/_ \\_/ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | \\\\ / /| | |\\ |\n || | | | \\\\ || | | | ||\n (\' |====| =)== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n___________/__][__\\___________________________________/____|[_]_\\__\n1\n ==== _ ====\n ~~o o /o\\ (o o")\n _\\ -/_ .....\\_/ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | \\\\ / /| | |\\ |\n || | | | \\\\ || | | | ||\n (\' |====| =)== (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n___________/__][__\\___________________________________/____|[_]_\\__\n1\n ==== _ ====\n ~~o o /o\\ (o o")\n _\\ -/_ ..... \\_/ _\\- /_\n / \\ / \\ / \\ / \\\n //| | |\\\\ / \\/ \\\n || | | | \\\\ /0 / /| | |\\ |\n || | | | \\\\// || | | | ||\n (\' |====| <) (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n___________/__][__\\___________________________________/____|[_]_\\__\n1\n ==== _ ====\n ~~o o /o\\ (o o")\n _\\ -/_ ..... \\_/ _\\- /_\n / \\ / \\ . / \\ / \\\n //| | |\\\\ .*\' / \\/ \\\n || | | | \\\\ /*\' / /| | |\\ |\n || | | | \\\\// || | | | ||\n (\' |====| <) (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n___________/__][__\\___________________________________/____|[_]_\\__\n1\n ==== _ ====\n ~~o o . /o\\ (o o")\n _\\ -/_ ..... .*\' \\_/ _\\- /_\n / \\ / \\ .*\' / \\ / \\\n //| | |\\\\ .*\' / \\/ \\\n || | | | \\\\ /*\' / /| | |\\ |\n || | | | \\\\// || | | | ||\n (\' |====| <) (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n___________/__][__\\___________________________________/____|[_]_\\__\n1\n ==== .* _ ====\n ~~O O .*\' /o\\ (o o")\n _\\ o/_. .*\' \\_/ _\\- /_\n / \\ / \\ .*\' / \\ / \\\n //| | |\\\\ .*\' / \\/ \\\n || | | | \\\\ /*\' / /| | |\\ |\n || | | | \\\\// || | | | ||\n (\' |====| <) (` | | | `)\n | || | | | |\n (_)(_) | |\\ |\n |_||_| / || \\\n |_||_| / ||_|\\\n___________/__][__\\___________________________________/____|[_]_\\__\n1\n ==== _ ====\n ~~o o /o\\ (o o")\n _\\ o/_ .* \\_/ _\\- /_\n / \\ / \\ .*\' / \\ / \\\n //| | |\\\\ .*\' / \\/ \\\n || | | | \\\\ .*\' / /| | |\\ |\n || | | | \\\\ /*\' || | | | ||\n (\' |====| /)/ (` | | | `)\n | || | <\\ ) | | === | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n14\n ####\n I told you {"o o}\n I\'d outrun { =}\n them. {~~ //~} ___\n {{~{ //}~}} __o____O___ /() \\\n {} {// } {} / =- /\\ \\ _|_____|_\n {} // } {} ( /> <\\ ) | | === | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n10\n ####\n I told you {o o"}\n I\'d outrun {= }\n them. {~~ //~} ___\n {{~{ //}~}} __o____O___ /() \\\n {} {// } {} / =- /\\ \\ _|_____|_\n {} // } {} ( /> <\\ ) | | === | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n2\n ####\n I told you {"o o}\n I\'d outrun { =}\n them. {~~ //~} ___\n {{~{ //}~}} __o____O___ /() \\\n {} {// } {} / =- /\\ \\ _|_____|_\n {} // } {} ( /> <\\ ) | | === | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n3\n ####\n I told you {"o o}\n I\'d outrun { =}\n them. {~~ //~} ___\n {{~{ //}~}} __o____O___ /() \\\n {} {// } {} / =- /\\ \\ _|_____|_\n {} // } {{{@ /> <\\ ) | | === | |\n {} H{{}}} \\___________/ |_| O |_|\n @ H"||"} \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n I told you {"o o}\n I\'d outrun { =}\n them. {~~ //~} ___\n {{~{ //}~}} ___o___O___ /() \\\n {} {// } {} / =- /\\ \\ _|_____|_\n {} // } {{{@ >\\ <\\ ) | | === | |\n {} H{{}}} \\___________/ |_| O |_|\n @ H"||"} \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n I told you {"o o}\n I\'d outrun { =}\n them. {~~ //~} ___\n {{~{ //}~}} ___o___O___ /() \\\n {} {// } {} / =- /\\ \\ _|_____|_\n {} // } {} ( >\\ <\\ ) | | === | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n6\n ####\n {"o o}\n { =}\n {~~ //~} ___\n {{~{ //}~}} ___o___O___ /() \\\n {} {// } {} / =- /\\ \\ _|_____|_\n {} // } {} ( >\\ <\\ ) | | === | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n14\n ####\n {"o o} Now be\n { =} careful R2.\n {~~ //~} ___\n {{~{ //}~}} ___o___O___ /() \\\n {} {// } {} / =- /\\ \\ _|_____|_\n {} // } {} ( >\\ <\\ ) | | === | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n {"o o} Now be\n { =} careful R2.\n {~~ //~} ___\n {{~{ //}~}} ___o___O___ /() \\\n {} {// } {} / =- /\\ \\ _|_____|_\n {} // } {} ( >\\ <\\ ) | |-=== | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n {"o o} Now be\n { =} careful R2.\n {~~ //~} ___\n {{~{ //}~}} ___o___O___ /() \\\n {} {// } {} / =- /\\ \\ _|_____|_\n {} // } {} ( >\\ <\\ ) | --=== | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n {"o o} Now be\n { =} careful R2.\n {~~ //~} ___\n {{~{ //}~}} ___o___O___ /() \\\n {} {// } {} / =- /\\ \\ _|_____|_\n {} // } {} ( >\\ <\\ ) |---=== | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n {"o o} Now be\n { =} careful R2.\n {~~ //~} ___\n {{~{ //}~}} ___o___O___ /() \\\n {} {// } {} / =- /\\ \\ _|_____|_\n {} // } {} ( >\\ <\\ ) ----=== | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n {"o o} Now be\n { =} careful R2.\n {~~ //~} ___\n {{~{ //}~}} ___o___O___ /() \\\n {} {// } {} / =- /\\ \\ _|_____|_\n {} // } {} ( >\\ <\\ ) -----=== | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n2\n ####\n {"o o} Now be\n { =} careful R2.\n {~~ //~} ___\n {{~{ //}~}} ___o___O___ /() \\\n {} {// } {} / =- /\\ \\ _|_____|_\n {} // } {} ( >\\ <\\ )------=== | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n2\n ####\n {"o o} Now be\n { =} careful R2.\n {~~ //~} ___\n {{~{ //}~}} ___o__O____ /() \\\n {} {// } {} / =- >\\ \\ _|_____|_\n {} // } {} ( >\\ /\\ )------=== | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n {"o o}\n { =}\n {~~ //~} ___\n {{~{ //}~}} ___o__O____ /() \\\n {} {// } {} / =- >\\ \\ _|_____|_\n {} // } {} ( >\\ /\\ ) -----=== | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n {"o o}\n { =}\n {~~ //~} ___\n {{~{ //}~}} ___o_O_____ /() \\\n {} {// } {} / =--> \\ _|_____|_\n {} // } {} ( >\\/< ) ----=== | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n {"o o}\n { =}\n {~~ //~} ___\n {{~{ //}~}} ____oO_____ /() \\\n {} {// } {} / -/=> \\ _|_____|_\n {} // } {} ( />/\\ ) |---=== | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n {"o o}\n { =}\n {~~ //~} o ___\n {{~{ //}~}} ___/\\O_____ /() \\\n {} {// } {} / /> > \\ _|_____|_\n {} // } {} ( /\\ ) | --=== | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n {"o o}\n { =}\n {~~ //~} \\--o ___\n {{~{ //}~}} __/_\\O_____ /() \\\n {} {// } {} / | \\ _|_____|_\n {} // } {} ( / \\ ) | |-=== | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n {"o o}\n { =} ,\n {~~ //~} \\--o ___\n {{~{ //}~}} ___>\\O/____ /() \\\n {} {// } {} / | \\ _|_____|_\n {} // } {} ( / \\ ) | | === | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n6\n ####\n {"O O}\n { =} ,\n {~~ //~} \\--o ___\n {{~{ //}~}} ___>\\O/____ /() \\\n {} {// } {} / | \\ _|_____|_\n {} // } {} ( / \\ ) | | === | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n {"o o}\n { =}\n {~~ //~} ___\n {{~{ //}~}} ____\\O/____ /() \\\n {} {// } {} / >-|o \\ _|_____|_\n {} // } {} ( / \\ ) | | === | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n6\n ####\n {"o o}\n { =}\n {~~ //~} ___\n {{~{ //}~}} _____O_____ /() \\\n {} {// } {} / /|\\ \\ _|_____|_\n {} // } {} ( / \\ ) | | === | |\n {} H{{}}} {} \\___>-\\o____/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n {"o o}\n { =}\n {~~ //~} ___\n {{~{ //}~}} _____O_____ /() \\\n {} {// } {} / /|\\ \\ _|_____|_\n {} // } {} ( / \\ ) | | === | |\n {} H{{}}} {} \\___~-~o____/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n {"o o}\n { =}\n {~~ //~} ___\n {{~{ //}~}} _____O_____ /() \\\n {} {// } {} / /|\\ \\ _|_____|_\n {} // } {} ( / \\ ) | | === | |\n {} H{{}}} {} \\___>~\\~____/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n {"o o}\n { =}\n {~~ //~} ___\n {{~{ //}~}} _____O_____ /() \\\n {} {// } {} / /|\\ \\ _|_____|_\n {} // } {} ( / \\ ) | | === | |\n {} H{{}}} {} \\___~-~o____/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n {"o o}\n { =}\n {~~ //~} ___\n {{~{ //}~}} _____O_____ /() \\\n {} {// } {} / /|\\ \\ _|_____|_\n {} // } {} ( / \\ ) | | === | |\n {} H{{}}} {} \\___>~\\~____/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n {"o o}\n { =}\n {~~ //~} ___\n {{~{ //}~}} _____O_____ /() \\\n {} {// } {} / /|\\ \\ _|_____|_\n {} // } {} ( / \\ ) | | === | |\n {} H{{}}} {} \\___~-~o____/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n {"o o}\n { =}\n {~~ //~} ___\n {{~{ //}~}} _____O_____ /() \\\n {} {// } {} / /|\\ \\ _|_____|_\n {} // } {} ( / \\ ) | | === | |\n {} H{{}}} {} \\___>~\\~____/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n1\n ####\n {"o o}\n { =}\n {~~ //~} ___\n {{~{ //}~}} _____O_____ /() \\\n {} {// } {} / /|\\ \\ _|_____|_\n {} // } {} ( / \\ ) | | === | |\n {} H{{}}} {} \\___~~~~____/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n6\n ####\n {"o o}\n { =}\n {~~ //~} ___\n {{~{ //}~}} _____O_____ /() \\\n {} {// } {} / /|\\ \\ _|_____|_\n {} // } {} ( / \\ ) | | === | |\n {} H{{}}} {} \\___________/ |_| O |_|\n @ H"||"} @ \\ / || O ||\n {"||"} | | ||__*__||\n {"||"} | | |~ \\___/ ~|\n {"||"} | | /=\\ /=\\ /=\\\n_______________[_][_]________/_______\\_____[_]_[_]_[_]_____________\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n2\n _-=-. ====\n ((___) (o o")\n _\\ -/_ _\\- /_\n / \\ / \\ _ / \\ / \\\n //| | |\\\\ /o\\ / \\/ \\\n || | | | \\\\ \\_/ / /| | |\\ |\n || | | | \\\\ /o || | | | ||\n (\' |====| /)/ (` | | | `)\n | || | =<| .\n .| . . .\n | .\n | .\n | .\n . . . .\n1\n . . . .\n. .\n .\n | . O\n . | . . .\n | . . .\n | .\n|>=<| .\n . | . . .\n | .\n | .\n .| .\n . . . .\n1\n . . . .\n. .\n .\n | . O\n . | . . .\n | . . .\n\\ | .\n-|>=<| .\n/ . | . . .\n | .\n | .\n . | .\n . . . .\n1\n . . . .\n. .\n .\n | . O\n . | . . .\n_ | . . .\n\'\\ | .\nO-|>=<| .\n_/. | . . .\n | .\n | .\n . | .\n . . . .\n1\n . . . .\n. .\n .\n | . O\n . |. . .\n _ | . . .\n/\'\\ | .\n-O-|>=<| .\n\\_/ | . . .\n | .\n | .\n . | .\n . . . .\n1\n . . . .\n. .\n .\n | . O\n . | . .\n _ | . . .\n /\'\\ | .\n|-O-|>=<| .\n \\_/ | . . .\n | .\n |.\n . | .\n . . . .\n1\n . . . .\n. .\n .\n | . O\n . .| . .\n _ | . . .\n /\'\\ | .\n<|-O-|>=<| .\n \\_/ | . . .\n | .\n |\n . | .\n . . . .\n1\n . . . .\n. .\n .\n | . O\n . . | . .\n _ | . . .\n /\'\\ | .\n=<|-O-|>=<| .\n .\\_/ | . . .\n | .\n .|\n . | .\n . . . .\n1\n . . . .\n. .\n .\n | . O\n . . | . .\n _ | . . .\n /\'\\ | .\n>=<|-O-|>=<| .\n . \\_/ | . . .\n | .\n . |\n . | .\n . . . .\n1\n . . . .\n. .\n .\n| | . O\n| . . | . .\n| _ | . . .\n| /\'\\ | .\n|>=<|-O-|>=<| .\n| . \\_/ | . . .\n| | .\n| . |\n| . | .\n . . . .\n1\n . . . .\n. .\n .\n | | . O\n |. . | . .\n | _ | . . .\n | /\'\\ | .\n |>=<|-O-|>=<| .\n |. \\_/ | . . .\n | | .\n | . |\n | . | .\n . . . .\n1\n . . . .\n. .\n .\n | | . O\n | . | . .\n | _ |. . .\n | /\'\\ | .\n |>=<|-O-|>=<| .\n | \\_/ | . . .\n | |.\n | . |\n |. | .\n . . . .\n1\n . . . .\n. .\n .\n | | . O\n .| . | . .\n | _ | . .\n | /\'\\ | .\n |>=<|-O-|>=<| .\n .| \\_/ | . . .\n | |\n | . |\n | | .\n . . . .\n1\n . . . .\n. .\n .\n | | . O\n . | . | . .\n | _ .| . .\n | /\'\\ | .\n |>=<|-O-|>=<| .\n . | \\_/ | . . .\n | .|\n | . |\n .| | .\n . . . .\n1\n . . . .\n. .\n .\n | | . O\n . | . | . .\n | _ . | . .\n | /\'\\ | .\n |>=<|-O-|>=<| .\n . | \\_/ | . . .\n | . |\n | . |\n . | | .\n . . . .\n1\n . . . .\n. .\n .\n | | . O\n . | . | . .\n | _ . | . .\n | /\'\\ | .\n |>=<|-O-|>=<| .\n . | \\_/ | . . .\n | . |\n | . |\n . | | .\n . . . .\n1\n . . . .\n. .\n .\n | | . O\n . |. | . .\n | _ . | . .\n | /\'\\ | .\n |>=<|-O-|>=<| .\n . | \\_/ | . . .\n | . |\n | . |\n . | | .\n . . . .\n1\n . . . .\n. .\n .\n . O\n . . . .\n | . | . .\n | | .\n |=()=| .\n . | | . . .\n | . |\n .\n . .\n . . . .\n1\n . . . .\n. .\n .\n . O\n . . . .\n | . | . .\n | | .\n |=()=| .\n . | | . . .\n | . |\n .\n . .\n . . . .\n1\n . . . .\n. .\n .\n . O\n . . . .\n |. | . .\n | | .\n |=()=| .\n . | | . . .\n |. |\n .\n . .\n . . . .\n1\n . . . .\n. .\n .\n . O\n . . . .\n . . .\n | | .\n |-O-| .\n . | | . . .\n .\n .\n . .\n . . . .\n1\n . . . .\n. .\n .\n . O\n . . . .\n . . .\n | |.\n |-O-| .\n . | | . . .\n .\n .\n . .\n . . . .\n1\n . . . .\n. .\n .\n . O\n . . . .\n . . .\n | |\n |-O-| .\n . | | . . .\n .\n .\n . .\n . . . .\n1\n . . . .\n. .\n .\n . O\n . . . .\n . . .\n | .|\n |-O-| .\n . | | . . .\n .\n .\n . .\n . . . .\n1\n . . . .\n. .\n .\n . O\n . . . .\n . . .\n .\n |o| .\n . . . .\n .\n .\n . .\n . . . .\n1\n . . . .\n. .\n .\n . O\n . . . .\n . . .\n .\n |o| .\n . . . .\n .\n .\n . .\n . . . .\n1\n . . . .\n. .\n .\n . O\n . . . .\n . . .\n .\n |o| .\n . . . .\n .\n .\n . .\n . . . .\n1\n . . . .\n. .\n .\n . O\n . . . .\n . . .\n .\n |o| .\n . . . .\n .\n .\n . .\n . . . .\n1\n . . . .\n. .\n .\n . O\n . . . .\n . . .\n .\n |o| .\n . . . .\n .\n .\n . .\n . . . .\n1\n . . . .\n. .\n .\n . O\n . . . .\n . . .\n .\n * .\n . . . .\n .\n .\n . .\n . . . .\n1\n . . . .\n. .\n .\n . O\n . . . .\n . . .\n .\n * .\n . . . .\n .\n .\n . .\n . . . .\n1\n . . . .\n. .\n .\n . O\n . . . .\n . . .\n .\n * .\n . . . .\n .\n .\n . .\n . . . .\n1\n . . . .\n. .\n .\n . O\n . . . .\n . . .\n .\n * .\n . . . .\n .\n .\n . .\n . . . .\n1\n . . . .\n. .\n .\n . O\n . . . .\n . . .\n .\n . .\n . . . .\n .\n .\n . .\n . . . .\n1\n . . . .\n. .\n .\n . O\n . . . .\n . . .\n .\n . .\n . . . .\n .\n .\n . .\n . . . .\n1\n . . . .\n. .\n .\n . O\n . . . .\n . . .\n .\n . .\n . . . .\n .\n .\n . .\n . . . .\n10\n . . . .\n. .\n .\n . O\n . . . .\n . . .\n .\n .\n . . . .\n .\n .\n . .\n . . . .\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n4\n ==== #### ===- ====\n ~~o o {"o o} o o"" (o o")\n _\\ -/_ { =} _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n11\n ==== #### He\'s heading for ===- ====\n ~~o o {"o o} that small moon! o o"" (o o")\n _\\ -/_ { =} _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n19\n ==== #### He\'s heading for ===- ====\n ~~o o {"o o} that small moon! o o"" (- -")\n _\\ -/_ { =} _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n6\n ==== #### ===- ====\n ~~o o {"o o} o o"" (- -")\n _\\ -/_ { =} _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n4\n ==== #### That\'s no moon. ===- ====\n ~~o o {"o o} o o"" (- -")\n _\\ -/_ { =} _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n2\n ==== #### That\'s no moon. ===- ====\n ~~o o {"o o} o o"" (o o")\n _\\ -/_ { =} _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n23\n ==== #### That\'s no moon. -=== ====\n ~~o o {"o o} ""o o (o o")\n _\\ -/_ { =} _\\ -/_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n1\n ==== #### -=== ====\n ~~o o {"o o} ""o o (o o")\n _\\ -/_ { =} _\\ -/_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n24\n ==== #### It\'s a -=== ====\n ~~o o {"o o} space station! ""o o (o o")\n _\\ -/_ { =} _\\ -/_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n7\n ==== #### It\'s a -=== ====\n ~~O O {"o o} space station! ""o o (o o")\n _\\ o/_ { =} _\\ -/_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n1\n ==== #### It\'s a ===- ====\n ~~O O {"o o} space station! o o"" (o o")\n _\\ o/_ { =} _\\o /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n3\n ==== #### It\'s a ===- ====\n ~~o o {"o o} space station! o o"" (o o")\n _\\ o/_ { =} _\\o /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n3\n ==== #### ===- ====\n ~~o o {"o o} o o"" (o o")\n _\\ o/_ { =} _\\o /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n3\n ==== #### ===- ====\n ~~o o {"o o} o o"" (o o")\n _\\ -/_ { =} _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n3\n ==== #### ===- ====\n o o~~ {"o o} o o"" (o o")\n _\\- /_ { =} _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n15\n ==== #### ===- ====\n o o~~ {o o"} o o"" (o o")\n _\\- /_ {= } _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n14\n . . __---__ .\n . . . .-\'...:...\'-. .\n . / .__. : . . \\\n . . /. / \\.........\\ . . .\n / :| () |: : :\\\n . :....\\__/...........: .\n . . |___________________|\n |...................| . .\n . . : : : : : : :\n . \\................./ . .\n . \\ . . : . . / .\n . . . \\._........._./ . .\n -..___..- .\n1\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n ==== #### ===- ====\n o o~~ {o o"} o o"" (o o")\n _\\- /_ {= } _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n22\n ==== #### I have a very ===- ====\n o o~~ {o o"} bad feeling o o"" (o o")\n _\\- /_ {= } about this! _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n4\n ==== #### ===- ====\n o o~~ {o o"} o o"" (o o")\n _\\- /_ {= } _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n11\n ==== #### Turn the ship ===- ====\n o o~~ {o o"} around. o o"" (o o")\n _\\- /_ {= } _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n12\n ==== #### Turn the ship ===- ====\n ~~o o {o o"} around. o o"" (o o")\n _\\ -/_ {= } _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n4\n ==== #### ===- ====\n ~~o o {o o"} o o"" (o o")\n _\\ -/_ {= } _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n10\n ==== #### I think you\'re ===- ====\n ~~o o {o o"} right. o o"" (o o")\n _\\ -/_ {= } _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} Full reverse! /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n12\n ==== #### I think you\'re ===- ====\n ~~o o {"o o} right. o o"" (o o")\n _\\ -/_ { =} _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} Full reverse! /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n1\n ==== #### ===- ====\n ~~o o {"o o} o o"" (o o")\n _\\ -/_ { =} _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n9\n ==== #### Chewie, lock in ===- ====\n ~~o o {"o o} the auxiliary o o"" (o o")\n _\\ -/_ { =} power! _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n11\n ==== #### Chewie, lock in ===- ====\n o o~~ {"o o} the auxiliary o o"" (o o")\n _\\- /_ { =} power! _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n6\n ==== #### ===- ====\n o o~~ {"o o} o o"" (o o")\n _\\- /_ { =} _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n2\n ==== #### Why are we still ===- ====\n o o~~ {"o o} moving towards o o"" (o o")\n _\\- /_ { =} it? _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n2\n ==== #### Why are we still ===- ====\n o o~~ {"o o} moving towards o o"" (o o")\n _\\o /_ { =} it? _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n2\n ==== #### Why are we still ===- ====\n ~~o o {"o o} moving towards o o"" (o o")\n _\\ o/_ { =} it? _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n16\n ==== #### Why are we still ===- ====\n ~~o o {"o o} moving towards o o"" (o o")\n _\\ -/_ { =} it? _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n4\n ==== #### ===- ====\n ~~o o {"o o} o o"" (o o")\n _\\ -/_ { =} _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n24\n ==== #### We\'re caught in ===- ====\n ~~o o {"o o} a tractor beam! o o"" (o o")\n _\\ -/_ { =} _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n20\n ==== #### I\'m going to have ===- ====\n ~~o o {"o o} to shut down. o o"" (o o")\n _\\ -/_ { =} _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n6\n ==== #### ===- ====\n ~~o o {"o o} o o"" (o o")\n _\\ -/_ { =} _\\- /_ _\\- /_\n / \\ / \\ {~~ //~} /| || |\\ / \\ / \\\n \\ | || {{~{ //}~}} //| || |\\\\ / \\/ \\/\n \\ | || {} {// } {} // | || |// | /| |/\n \\---------{}--------{}-------------//-------//--------------/\n {} @ (\' (\'\n @\n\n\n\n___________________________________________________________________\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _\\\\_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _\\\\_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _\\\\_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _\\\\_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _\\\\_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _\\\\_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _\\\\_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _\\\\_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _\\\\_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _\\\\_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _\\\\_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _\\\\_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _||_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _||_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _||_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _||_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _||_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _||_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _||_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _||_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _||_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _||_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _||_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _||_ _\\\\_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _||_ _||_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _//_ _||_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _//_ _||_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _//_ _||_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _//_ _||_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n2\n |____________________________________\n |\n |_\n |\n ___(___ |\n ===o====== |\n ^^ ^ |\n |\n |\n _|\n _//_ _||_ |\n __________|----|______|----|________|\n | /______\\ /______\\\n6\n\n\n\n\n\n\n\n\n\n\n\n\n\n4\n /~~\\\n |<><>|\n /_/\\_\\\n /\\___/\\ ====\n // [ ]|\\\\ o o |\n //| [_]| \\\\ _\\- /_\n \\\\| | // /"\'==\'"\\\n #|====|# | | ::: |\n /|\\ /I\\ || | ||\n-------------------------------------------------------------------\n\n\n\n4\n /~~\\\n |<><>|\n /_/\\_\\\n /\\___/\\ ====\n // [ ]|\\\\ | o o\n //| [_]| \\\\ _\\ -/_\n \\\\| | // /"\'==\'"\\\n #|====|# | | ::: |\n /|\\ /I\\ || | ||\n-------------------------------------------------------------------\n\n\n\n25\n /~~\\\n |<><>|\n /_/\\_\\\n /\\___/\\ ==== Yes?\n // [ ]|\\\\ | o o\n //| [_]| \\\\ _\\ -/_\n \\\\| | // /"\'==\'"\\\n #|====|# | | ::: |\n /|\\ /I\\ || | ||\n-------------------------------------------------------------------\n\n\n\n5\n /~~\\\n |<><>|\n /_/\\_\\\n /\\___/\\ ====\n // [ ]|\\\\ | o o\n //| [_]| \\\\ _\\ -/_\n \\\\| | // /"\'==\'"\\\n #|====|# | | ::: |\n /|\\ /I\\ || | ||\n-------------------------------------------------------------------\n\n\n\n36\n /~~\\ We\'ve captured a\n |<><>| freighter entering\n /_/\\_\\ the remains of the\n /\\___/\\ ==== Alderaan system.\n // [ ]|\\\\ | o o\n //| [_]| \\\\ _\\ -/_\n \\\\| | // /"\'==\'"\\\n #|====|# | | ::: |\n /|\\ /I\\ || | ||\n-------------------------------------------------------------------\n\n\n\n3\n /~~\\\n |<><>|\n /_/\\_\\\n /\\___/\\ ====\n // [ ]|\\\\ | o o\n //| [_]| \\\\ _\\ -/_\n \\\\| | // /"\'==\'"\\\n #|====|# | | ::: |\n /|\\ /I\\ || | ||\n-------------------------------------------------------------------\n\n\n\n40\n /~~\\ Its markings\n |<><>| match those of a\n /_/\\_\\ ship that blasted\n /\\___/\\ ==== its way out of\n // [ ]|\\\\ | o o Mos Eisley!\n //| [_]| \\\\ _\\ -/_\n \\\\| | // /"\'==\'"\\\n #|====|# | | ::: |\n /|\\ /I\\ || | ||\n-------------------------------------------------------------------\n\n\n\n2\n /~~\\\n |<><>|\n /_/\\_\\\n /\\___/\\ ====\n // [ ]|\\\\ | o o\n //| [_]| \\\\ _\\ -/_\n \\\\| | // /"\'==\'"\\\n #|====|# | | ::: |\n /|\\ /I\\ || | ||\n-------------------------------------------------------------------\n\n\n\n3\n /~~\\ They must be\n |<><>| trying to return\n /_/\\_\\ the stolen plans\n /\\___/\\ to the Princess. ====\n // [ ]|\\\\ | o o\n //| [_]| \\\\ _\\ -/_\n \\\\| | // /"\'==\'"\\\n #|====|# | | ::: |\n /|\\ /I\\ || | ||\n-------------------------------------------------------------------\n\n\n\n33\n /~~\\ They must be\n |<><>| trying to return\n /_/\\_\\ the stolen plans\n /\\___/\\ to the Princess. ====\n // [ ]|\\\\ o o |\n //| [_]| \\\\ _\\- /_\n \\\\| | // /"\'==\'"\\\n #|====|# | | ::: |\n /|\\ /I\\ || | ||\n-------------------------------------------------------------------\n\n\n\n3\n /~~\\\n |<><>|\n /_/\\_\\\n /\\___/\\ ====\n // [ ]|\\\\ o o |\n //| [_]| \\\\ _\\- /_\n \\\\| | // /"\'==\'"\\\n #|====|# | | ::: |\n /|\\ /I\\ || | ||\n-------------------------------------------------------------------\n\n\n\n6\n /~~\\ She may yet\n |<><>| be of some use\n /_/\\_\\ to us.\n /\\___/\\ ====\n // [ ]|\\\\ o o |\n //| [_]| \\\\ _\\- /_\n \\\\| | // /"\'==\'"\\\n #|====|# | | ::: |\n /|\\ /I\\ || | ||\n-------------------------------------------------------------------\n\n\n\n14\n /~~\\ She may yet\n |<><>| be of some use\n /_/\\_\\ to us.\n /\\___/\\ # ====\n // [ ]|\\\\// o o |\n //| [_]| \\/ _\\- /_\n \\\\| | /"\'==\'"\\\n #|====| | | ::: |\n /|\\ /I\\ || | ||\n-------------------------------------------------------------------\n\n\n\n2\n /~~\\ She may yet\n |<><>| be of some use\n /_/\\_\\ to us.\n /\\___/\\ ====\n // [ ]|\\\\ o o |\n //| [_]| \\\\ _\\- /_\n \\\\| | \\\\ /"\'==\'"\\\n #|====| # | | ::: |\n /|\\ /I\\ || | ||\n-------------------------------------------------------------------\n\n\n\n4\n /~~\\\n |<><>|\n /_/\\_\\\n /\\___/\\ ====\n // [ ]|\\\\ o o |\n //| [_]| \\\\ _\\- /_\n \\\\| | \\\\ /"\'==\'"\\\n #|====| # | | ::: |\n /|\\ /I\\ || | ||\n-------------------------------------------------------------------\n\n\n\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo + O :/----I-----\n____||||_||||___________ __|_|___________/_____===____\n | |\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo + O :/----I-----\n____||||_||||___________ __|_|___________/_____===____\n | |\n | oooo |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo + O :/----I-----\n____||||_||||___________ __|_|___________/_____===____\n | oooo |\n | |||| |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo + O :/----I-----\n____||||_||||___________ oooo __|_|___________/_____===____\n | |||| |\n |------------|\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||___________ |||| __|_|___________/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||___________ |||| __|_|___________/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||___________|||| __|_|___________/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||__________|||| __|_|___________/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||_________|||| __|_|___________/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||________|||| __|_|___________/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||_______|||| __|_|___________/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||______||||_ __|_|___________/_____===____\n |------------|\n | |\n1\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||_____||||__ __|_|___________/_____===____\n |------------|\n | |\n1\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||_____||||__ __|__|__________/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||____||||___ __|__|__________/_____===____\n |------------|\n | |\n2\n\n\n\n There\'s no one _\n on board sir. ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||___||||____ __|__|__________/_____===____\n |------------|\n | |\n2\n\n\n\n There\'s no one _\n on board sir. ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||__||||_____ __|__|__________/_____===____\n |------------|\n | |\n17\n\n\n\n There\'s no one _\n on board sir. ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||_||||______ __|__|__________/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||_||||______ __|__|__________/_____===____\n |------------|\n | |\n25\n\n\n\n It must be a _\n decoy. ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||_||||______ __|__|__________/_____===____\n |------------|\n | |\n4\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||_||||______ __|__|__________/_____===____\n |------------|\n | |\n26\n\n Did you find\n any droids?\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||_||||______ __|__|__________/_____===____\n |------------|\n | |\n4\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||_||||______ __|__|__________/_____===____\n |------------|\n | |\n20\n\n\n\n No sir. _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||_||||______ __|__|__________/_____===____\n |------------|\n | |\n1\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||_||||______ __|__|__________/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||_||||______ __|_|___________/_____===____\n |------------|\n | |\n34\n\n Send a scanning\n crew aboard.\n _\n I want every part ________|_\n of this ship _ ___ -------------\n checked. / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||_||||______ __|_|___________/_____===____\n |------------|\n | |\n1\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||_||||______ __|_|___________/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||_||||______ __|__|__________/_____===____\n |------------|\n | |\n19\n\n I sense something...\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||_||||______ __|___|_________/_____===____\n |------------|\n | |\n1\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||_||||______ __|___|_________/_____===____\n |------------|\n | |\n30\n\n ...A presence I\'ve\n not felt since...\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||_||||______ __|___|_________/_____===____\n |------------|\n | |\n4\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n oooo oooo oooo + O :/----I-----\n____||||_||||_||||______ __|___|_________/_____===____\n |------------|\n | |\n1\n\n\n\n\n\n\n\n\n\n\n\n\n\n13\n \\ __\\ /__ /\n | | | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / \\ |---|\n | | / \\ | |\n ________|---|/ \\|---|___________\n / \\\n / \\\n________/_______________________________________________\\__________\n\n1\n \\ __\\ /__ /\n | | | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / \\ \\ | |\n ________|---|/ / \\ \\|---|___________\n / / \\ \\\n / /____________________________________\\ \\\n________/_______________________________________________\\__________\n\n1\n \\ __\\ /__ /\n | | | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / \\ \\ | |\n ________|---|/ / \\ \\|---|___________\n / / \\ \\\n / /_________________________===-_______\\ \\\n________/_______________________________________________\\__________\n\n1\n \\ __\\ /__ /\n | | | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / \\ \\ | |\n ________|---|/ / \\ \\|---|___________\n / / ===- \\ \\\n / /_________________________o o""______\\ \\\n________/_______________________________________________\\__________\n\n1\n \\ __\\ /__ /\n | | | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / \\ \\ | |\n ________|---|/ / ===- \\ \\|---|___________\n / / o o"" \\ \\\n / /_________________________\\- /_______\\ \\\n________/_______________________________________________\\__________\n\n1\n \\ __\\ /__ /\n | | | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ===- \\ \\ | |\n ________|---|/ / o o"" \\ \\|---|___________\n / / _\\- /_ \\ \\\n / /_________====__________/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n1\n \\ __\\ /__ /\n | | | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ===- \\ \\ | |\n ________|---|/ / o o"" \\ \\|---|___________\n / / ==== _\\- /_ \\ \\\n / /________~~o o__________/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n1\n \\ __\\ /__ /\n | | | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ===- \\ \\ | |\n ________|---|/ / ==== o o"" \\ \\|---|___________\n / / ~~o o _\\- /_ \\ \\\n / /_________\\ -/__________/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n1\n \\ __\\ /__ /\n | | | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ===- \\ \\ | |\n ________|---|/ / ~~o o o o"" \\ \\|---|___________\n / / _\\ -/_ _\\- /_ \\ \\\n / /_______/__\\ /_\\________/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n4\n \\ __\\ /__ /\n | | | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== -=== \\ \\ | |\n ________|---|/ / ~~o o ""o o \\ \\|---|___________\n / / _\\ -/_ _\\ -/_ \\ \\\n / /_______/__\\ /_\\________/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n4\n \\ __\\ /__ /\n | | | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ===- \\ \\ | |\n ________|---|/ / ~~o o o o"" \\ \\|---|___________\n / / _\\ -/_ _\\- /_ \\ \\\n / /_______/__\\ /_\\________/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n2\n \\ __\\ /__ /\n | | | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== -=== \\ \\ | |\n ________|---|/ / ~~o o ""o o \\ \\|---|___________\n / / _\\ -/_ _\\ -/_ \\ \\\n / /_______/__\\ /_\\________/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n4\n \\ __\\ /__ /\n | | | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ===- \\ \\ | |\n ________|---|/ / ~~o o o o"" \\ \\|---|___________\n / / _\\ -/_ _\\- /_ \\ \\\n / /_______/__\\ /_\\________/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n34\n \\ __\\ It\'s lucky you had /__ /\n | | these compartments. | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ===- \\ \\ | |\n ________|---|/ / ~~o o o o"" \\ \\|---|___________\n / / _\\ -/_ _\\- /_ \\ \\\n / /_______/__\\ /_\\________/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n29\n \\ __\\ I use them for /__ /\n | | smuggling. | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ===- \\ \\ | |\n ________|---|/ / ~~o o o o"" \\ \\|---|___________\n / / _\\ -/_ _\\- /_ \\ \\\n / /_______/__\\ /_\\________/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n1\n \\ __\\ /__ /\n | | | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ===- \\ \\ | |\n ________|---|/ / ~~o o o o"" \\ \\|---|___________\n / / _\\ -/_ _\\- /_ \\ \\\n / /_______/__\\ /_\\________/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n30\n \\ __\\ I never thought /__ /\n | | I\'d be smuggling | |\n |---| myself. |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ===- \\ \\ | |\n ________|---|/ / ~~o o o o"" \\ \\|---|___________\n / / _\\ -/_ _\\- /_ \\ \\\n / /_______/__\\ /_\\________/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n2\n \\ __\\ /__ /\n | | | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ===- \\ \\ | |\n ________|---|/ / ~~o o o o"" \\ \\|---|___________\n / / _\\ -/_ _\\- /_ \\ \\\n / /_______/__\\ /_\\________/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n31\n \\ __\\ Even if I could /__ /\n | | take off, I\'d never | |\n |---| get past that |---|\n | | tractor beam. | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ===- \\ \\ | |\n ________|---|/ / ~~o o o o"" \\ \\|---|___________\n / / _\\ -/_ _\\- /_ \\ \\\n / /_______/__\\ /_\\________/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n1\n \\ __\\ Even if I could /__ /\n | | take off, I\'d never | |\n |---| get past that |---|\n | | tractor beam. | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ===- \\ \\ | |\n ________|---|/ / ~~o o o o"" \\ \\|---|___________\n / / _\\ -/_ _\\- /_ \\ \\\n / /_______/__\\ /_\\__====__/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n1\n \\ __\\ Even if I could /__ /\n | | take off, I\'d never | |\n |---| get past that |---|\n | | tractor beam. | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ===- \\ \\ | |\n ________|---|/ / ~~o o o o"" \\ \\|---|___________\n / / _\\ -/_ ==== _\\- /_ \\ \\\n / /_______/__\\ /_\\_("o o)_/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n1\n \\ __\\ Even if I could /__ /\n | | take off, I\'d never | |\n |---| get past that |---|\n | | tractor beam. | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ===- \\ \\ | |\n ________|---|/ / ~~o o ==== o o"" \\ \\|---|___________\n / / _\\ -/_ ("o o) _\\- /_ \\ \\\n / /_______/__\\ /_\\__\\_-/__/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n1\n \\ __\\ Even if I could /__ /\n | | take off, I\'d never | |\n |---| get past that |---|\n | | tractor beam. | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ==== ===- \\ \\ | |\n ________|---|/ / ~~o o ("o o) o o"" \\ \\|---|___________\n / / _\\ -/_ _\\ -/_ _\\- /_ \\ \\\n / /_______/__\\ /_\\/_\\__/_\\/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n5\n \\ __\\ /__ /\n | | | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ==== ===- \\ \\ | |\n ________|---|/ / ~~o o ("o o) o o"" \\ \\|---|___________\n / / _\\ -/_ _\\ -/_ _\\- /_ \\ \\\n / /_______/__\\ /_\\/_\\__/_\\/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n25\n \\ __\\ /__ /\n | | Leave that | |\n |---| to me! |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ==== ===- \\ \\ | |\n ________|---|/ / ~~o o ("o o) o o"" \\ \\|---|___________\n / / _\\ -/_ _\\ -/_ _\\- /_ \\ \\\n / /_______/__\\ /_\\/_\\__/_\\/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n3\n \\ __\\ /__ /\n | | | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ==== ===- \\ \\ | |\n ________|---|/ / ~~o o ("o o) o o"" \\ \\|---|___________\n / / _\\ -/_ _\\ -/_ _\\- /_ \\ \\\n / /_______/__\\ /_\\/_\\__/_\\/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n35\n \\ __\\ Damn fool! /__ /\n | | I knew that you | |\n |---| were going to |---|\n | | say that. | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ==== ===- \\ \\ | |\n ________|---|/ / ~~o o ("o o) o o"" \\ \\|---|___________\n / / _\\ -/_ _\\ -/_ _\\- /_ \\ \\\n / /_______/__\\ /_\\/_\\__/_\\/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n6\n \\ __\\ /__ /\n | | | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ==== ===- \\ \\ | |\n ________|---|/ / ~~o o ("o o) o o"" \\ \\|---|___________\n / / _\\ -/_ _\\ -/_ _\\- /_ \\ \\\n / /_______/__\\ /_\\/_\\__/_\\/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n21\n \\ __\\ /__ /\n | | Who is more foolish? | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ==== ===- \\ \\ | |\n ________|---|/ / ~~o o ("o o) o o"" \\ \\|---|___________\n / / _\\ -/_ _\\ -/_ _\\- /_ \\ \\\n / /_______/__\\ /_\\/_\\__/_\\/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n3\n \\ __\\ /__ /\n | | | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ==== ===- \\ \\ | |\n ________|---|/ / ~~o o ("o o) o o"" \\ \\|---|___________\n / / _\\ -/_ _\\ -/_ _\\- /_ \\ \\\n / /_______/__\\ /_\\/_\\__/_\\/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n30\n \\ __\\ /__ /\n | | The fool or the fool | |\n |---| who follows him? |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ==== ===- \\ \\ | |\n ________|---|/ / ~~o o ("o o) o o"" \\ \\|---|___________\n / / _\\ -/_ _\\ -/_ _\\- /_ \\ \\\n / /_______/__\\ /_\\/_\\__/_\\/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n6\n \\ __\\ /__ /\n | | | |\n |---| |---|\n | | | |\n |---| |---|\n | | _________________________ | |\n |---| / _______________________ \\ |---|\n | | / / ==== ==== ===- \\ \\ | |\n ________|---|/ / ~~o o ("o o) o o"" \\ \\|---|___________\n / / _\\ -/_ _\\ -/_ _\\- /_ \\ \\\n / /_______/__\\ /_\\/_\\__/_\\/|_||_|\\_____\\ \\\n________/_______________________________________________\\__________\n\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n4\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n + + o o :/----I-----\n________________________ __|==|_____|__|_/_____===____\n |------------|\n | |\n25\n\n\n The ship\'s\n all yours. _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n + + o o :/----I-----\n________________________ __|==|_____|__|_/_____===____\n |------------|\n | |\n6\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n + + o o :/----I-----\n________________________ __|==|_____|__|_/_____===____\n |------------|\n | |\n36\n\n\n If the scanners detect\n anything report it _\n immediately. ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n + + o o :/----I-----\n________________________ __|==|_____|__|_/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n + + o o :/----I-----\n________________________ __|==|_____|__|_/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n + + o o :/----I-----\n________________________ ___|==|____|__|_/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n + + o o :/----I-----\n________________________ ____|==|___|__|_/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n + + o o :/----I-----\n________________________ _____|==|__|__|_/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n + + o o :/----I-----\n________________________ ______|==|_|__|_/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n + +o o :/----I-----\n________________________ _______|==||__|_/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n + + o :/----I-----\n________________________ ________|==|__|_/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n + o+ o :/----I-----\n________________________ _________|==|_|_/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n +o +o :/----I-----\n________________________ __________|==||_/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n + o :/----I-----\n________________________ ___________|==|_/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n o+ o+ :/----I-----\n________________________ ___________||=||/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n o +o +:/----I-----\n________________________ ___________|_||=/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n o o :/----I-----\n________________________ ___________|__|=/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n o o+=:/----I-----\n________________________ ___________|__||/_____===____\n |------------|\n | |\n2\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n o o |:/----I-----\n________________________ ___________|__|_/_____===____\n |------------|\n | |\n18\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n o o :/----I-----\n________________________ ___________|__|_/_____===____\n |------------|\n | |\n15\n\n Hey down there!\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n o o :/----I-----\n________________________ ___________|__|_/_____===____\n |------------|\n | |\n17\n\n Hey down there!\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n o o :/----I-----\n________________________ ____________|_|_/_____===____\n |------------|\n | |\n3\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n o o :/----I-----\n________________________ ____________|_|_/_____===____\n |------------|\n | |\n20\n\n Could you give us\n a hand with this?\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n o o :/----I-----\n________________________ ____________|_|_/_____===____\n |------------|\n | |\n1\n\n Could you give us\n a hand with this?\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n o o :/----I-----\n________________________ ____________|__|/_____===____\n |------------|\n | |\n1\n\n Could you give us\n a hand with this?\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n o |:/----I-----\n________________________ _____________|__/_____===____\n |------------|\n | |\n1\n\n Could you give us\n a hand with this?\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n o :/----I-----\n________________________ ______________|_/_____===____\n |------------|\n | |\n1\n\n Could you give us\n a hand with this?\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n o :/----I-----\n________________________ _______________|/_____===____\n |------------|\n | |\n1\n\n Could you give us\n a hand with this?\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n |:/----I-----\n________________________ ________________/_____===____\n |------------|\n | |\n5\n\n Could you give us\n a hand with this?\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n :/----I-----\n________________________ ________________/_____===____\n |------------|\n | |\n10\n\n\n\n _\n ________|_\n _ ___ -------------\n / \\ | | |\n |-O-| | | |\n \\_/___|_________|__|\n :/----I-----\n________________________ ________________/_____===____\n |------------|\n | |\n7\n\n\n\n\n\n\n\n\n\n\n\n\n\n4\n ==== _________________________\n | o o |\\ _____________________ /|\n _\\ -/_ | | | |\n / / \\ | | | |\n | /| ""|\\\\ | | | |\n |||| | \\\\ | | | |\n |||| | () | |_____________________| |\n ()|-==-| |/_______________________\\|\n |----|\n | || |\n | || |\n |_||_|\n_____________________[_][__\\_______________________________________\n31\n ==== _________________________\n TK-421. | o o |\\ _____________________ /|\n Why aren\'t you _\\ -/_ | | | |\n at your post? / / \\ | | | |\n | /| ""|\\\\ | | | |\n |||| | \\\\ | | | |\n |||| | () | |_____________________| |\n ()|-==-| |/_______________________\\|\n |----|\n | || |\n | || |\n |_||_|\n_____________________[_][__\\_______________________________________\n3\n ==== _________________________\n | o o |\\ _____________________ /|\n _\\ -/_ | | | |\n / / \\ | | | |\n | /| ""|\\\\ | | | |\n |||| | \\\\ | | | |\n |||| | () | |_____________________| |\n ()|-==-| |/_______________________\\|\n |----|\n | || |\n | || |\n |_||_|\n_____________________[_][__\\_______________________________________\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n13\n /__\\\n |<><>|\n (_/\\_)\n / \\\n //| __ |\\\\\n // |/ \\| \\\\\n // [][][] ||\n |\' |\\ /| \'|\n |_||_|\n [ ][ ]\n | || |\n |_||_|\n_____________________________/__][_]_______________________________\n17\n /__\\\n |<><>|\n |, (_/\\_) ,|\n \\\\ / \\ //\n \\\\//| __ |\\\\//\n \\/ |/ \\| \\/\n [][][]\n |\\ /|\n |_||_|\n [ ][ ]\n | || |\n |_||_|\n_____________________________/__][_]_______________________________\n4\n /__\\\n |<><>|\n (_/\\_)\n / \\\n //| __ |\\\\\n // |/ \\| \\\\\n || [][][] ||\n |\' |\\ /| \'|\n |_||_|\n [ ][ ]\n | || |\n |_||_|\n_____________________________/__][_]_______________________________\n4\n /__\\\n |<><>|\n (_/\\_)\n / \\\n //| __ |\\\\\n // |/ \\| \\\\\n || [][][] \\\\\n |\' |\\ /| \'|\n |_||_|\n [ ][ ]\n | || |\n |_||_|\n_____________________________/__][_]_______________________________\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n3\n ==== _________________________\n | o o |\\ _____________________ /|\n _\\ -/_ | | | |\n / / \\ | | | |\n | /| ""|\\\\ | | | |\n |||| | \\\\ | | | |\n |||| | () | |_____________________| |\n ()|-==-| |/_______________________\\|\n |----|\n | || |\n | || |\n |_||_|\n_____________________[_][__\\_______________________________________\n6\n ==== _________________________\n Take over. | o o |\\ _____________________ /|\n We\'ve got a bad _\\ -/_ | | | |\n transmitter. / / \\ | | | |\n | /| ""|\\\\ | | | |\n |||| | \\\\ | | | |\n |||| | () | |_____________________| |\n ()|-==-| |/_______________________\\|\n |----|\n | || |\n | || |\n |_||_|\n_____________________[_][__\\_______________________________________\n16\n ==== _________________________\n Take over. o o | |\\ _____________________ /|\n We\'ve got a bad _\\- /_ | | | |\n transmitter. / / \\ | | | |\n | /| ""|\\\\ | | | |\n |||| | \\\\ | | | |\n |||| | () | |_____________________| |\n ()|-==-| |/_______________________\\|\n |----|\n | || |\n | || |\n |_||_|\n_____________________[_][__\\_______________________________________\n7\n ==== _________________________\n Take over. | o o |\\ _____________________ /|\n We\'ve got a bad _\\ -/_ | | | |\n transmitter. / / \\ | | | |\n | /| ""|\\\\ | | | |\n |||| | \\\\ | | | |\n |||| | () | |_____________________| |\n ()|-==-| |/_______________________\\|\n |----|\n | || |\n | || |\n |_||_|\n_____________________[_][__\\_______________________________________\n6\n ==== _________________________\n | o o |\\ _____________________ /|\n _\\ -/_ | | | |\n / / \\ | | | |\n | /| ""|\\\\ | | | |\n |||| | \\\\ | | | |\n |||| | () | |_____________________| |\n ()|-==-| |/_______________________\\|\n |----|\n | || |\n | || |\n |_||_|\n_____________________[_][__\\_______________________________________\n32\n ==== _________________________\n I\'ll see | o o |\\ _____________________ /|\n what I can do. _\\ -/_ | | | |\n / / \\ | | | |\n | /| ""|\\\\ | | | |\n |||| | \\\\ | | | |\n |||| | () | |_____________________| |\n ()|-==-| |/_______________________\\|\n |----|\n | || |\n | || |\n |_||_|\n_____________________[_][__\\_______________________________________\n5\n ==== _________________________\n | o o |\\ _____________________ /|\n _\\ -/_ | | | |\n / / \\ | | | |\n | /| ""|\\\\ | | | |\n |||| | \\\\ | | | |\n |||| | () | |_____________________| |\n ()|-==-| |/_______________________\\|\n |----|\n | || |\n | || |\n |_||_|\n_____________________[_][__\\_______________________________________\n4\n\n\n\n\n\n\n\n\n\n\n\n\n\n8\n ==== | |\n | o o | |\n _\\ -/_ | |\n / / \\ | |\n | /| ""||| __ | |\n |||| ||| |o=|| |\n |||| ||| |__|| |\n ()|-==-|() | |\n |----| | |\n | || | | |\n | || | | |\n |_||_| | |\n________[_][__\\______|____________________________|________________\n2\n ==== | |\n | o o | |\n _\\ -/_ | |\n / / \\ | |\n | /| ""|\\\\ __ | |\n |||| | \\\\|o=|| |\n |||| | \\()_|| |\n ()|-==-| | |\n |----| | |\n | || | | |\n | || | | |\n |_||_| | |\n________[_][__\\______|____________________________|________________\n2\n ==== | |\n | o o | |\n _\\ -/_ | |\n / / \\ | |\n | /| ""|\\\\ __ | |\n |||| | \\\\|*=|| |\n |||| | \\()_|| |\n ()|-==-| | |\n |----| | |\n | || | | |\n | || | | |\n |_||_| | |\n________[_][__\\______|____________________________|________________\n2\n ==== | |\n | o o | |\n _\\ -/_ | |\n / / \\ | |\n | /| ""|\\\\ __ | |\n |||| | \\\\|o=|| |\n |||| | \\()_|| |\n ()|-==-| | |\n |----| | |\n | || | | |\n | || | | |\n |_||_| | |\n________[_][__\\______|____________________________|________________\n2\n ==== | |\n | o o | |\n _\\ -/_ | |\n / / \\ | |\n | /| ""|\\\\ __ | |\n |||| | \\\\|*=|| |\n |||| | \\()_|| |\n ()|-==-| | |\n |----| | |\n | || | | |\n | || | | |\n |_||_| | |\n________[_][__\\______|____________________________|________________\n1\n ==== | |\n | o o | |\n _\\ -/_ | |\n / / \\ | |\n | /| ""|\\\\ __ | |\n |||| | \\\\|o=|| |\n |||| | \\()_|| |\n ()|-==-| | |\n |----| | |\n | || | | |\n | || | | |\n |_||_| | |\n________[_][__\\______|\\__________________________/|________________\n1\n ==== | |\n | o o | |\n _\\ -/_ | |\n / / \\ | |\n | /| ""|\\\\ __ | |\n |||| | \\\\|o=|| |\n |||| | \\()_|| |\n ()|-==-| | |\n |----| | |\n | || | | |\n | || | | |\n |_||_| |\\__________________________/|\n________[_][__\\______|____[_][_]________/__][_]___|_______________\n1\n ==== | |\n | o o | |\n _\\ -/_ | |\n / / \\ | |\n | /| ""|\\\\ __ | |\n |||| | \\\\|o=|| |\n |||| | \\()_|| |\n ()|-==-| | |\n |----| | |\n | || | | |\n | || | |\\__________________________/|\n |_||_| | {"||"} |_||_| |\n________[_][__\\______|____[_][_]________/__][_]___|_______________\n1\n ==== | |\n | o o | |\n _\\ -/_ | |\n / / \\ | |\n | /| ""|\\\\ __ | |\n |||| | \\\\|o=|| |\n |||| | \\()_|| |\n ()|-==-| | |\n |----| | |\n | || | |\\__________________________/|\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n________[_][__\\______|____[_][_]________/__][_]___|_______________\n1\n ==== | |\n | o o | |\n _\\ -/_ | |\n / / \\ | |\n | /| ""|\\\\ __ | |\n |||| | \\\\|o=|| |\n |||| | \\()_|| |\n ()|-==-| | |\n |----| |\\__________________________/|\n | || | | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n________[_][__\\______|____[_][_]________/__][_]___|_______________\n1\n ==== | |\n | o o | |\n _\\ -/_ | |\n / / \\ | |\n | /| ""|\\\\ __ | |\n |||| | \\\\|o=|| |\n |||| | \\()_|| |\n ()|-==-| |\\__________________________/|\n |----| | @ H"||"} @ |_||_| |\n | || | | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n________[_][__\\______|____[_][_]________/__][_]___|_______________\n1\n ==== | |\n | o o | |\n _\\ -/_ | |\n / / \\ | |\n | /| ""|\\\\ __ | |\n |||| | \\\\|o=|| |\n |||| | \\()_||\\__________________________/|\n ()|-==-| | {} H{{}}} {} |\\ /| |\n |----| | @ H"||"} @ |_||_| |\n | || | | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n________[_][__\\______|____[_][_]________/__][_]___|_______________\n1\n ==== | |\n | o o | |\n _\\ -/_ | |\n / / \\ | |\n | /| ""|\\\\ __ | |\n |||| | \\\\|o=||\\__________________________/|\n |||| | \\()_|| {} // } {} \\/][][\\/ |\n ()|-==-| | {} H{{}}} {} |\\ /| |\n |----| | @ H"||"} @ |_||_| |\n | || | | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n________[_][__\\______|____[_][_]________/__][_]___|_______________\n1\n ==== | |\n | o o | |\n _\\ -/_ | |\n / / \\ | |\n | /| ""|\\\\ __ |\\__________________________/|\n |||| | \\\\|o=|| {} {// } {} | / \\ | |\n |||| | \\()_|| {} // } {} \\/][][\\/ |\n ()|-==-| | {} H{{}}} {} |\\ /| |\n |----| | @ H"||"} @ |_||_| |\n | || | | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n________[_][__\\______|____[_][_]________/__][_]___|_______________\n1\n ==== | |\n | o o | |\n _\\ -/_ | |\n / / \\ |\\__________________________/|\n | /| ""|\\\\ __ | {{~{ //}~}} ||/(===o |\n |||| | \\\\|o=|| {} {// } {} | / \\ | |\n |||| | \\()_|| {} // } {} \\/][][\\/ |\n ()|-==-| | {} H{{}}} {} |\\ /| |\n |----| | @ H"||"} @ |_||_| |\n | || | | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n________[_][__\\______|____[_][_]________/__][_]___|_______________\n1\n ==== | |\n | o o | |\n _\\ -/_ |\\__________________________/|\n / / \\ | {~~ //~} / \\ |\n | /| ""|\\\\ __ | {{~{ //}~}} ||/(===o |\n |||| | \\\\|o=|| {} {// } {} | / \\ | |\n |||| | \\()_|| {} // } {} \\/][][\\/ |\n ()|-==-| | {} H{{}}} {} |\\ /| |\n |----| | @ H"||"} @ |_||_| |\n | || | | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n________[_][__\\______|____[_][_]________/__][_]___|_______________\n1\n ==== | |\n | o o |\\__________________________/|\n _\\ -/_ | {= } (/\\__) |\n / / \\ | {~~ //~} / \\ |\n | /| ""|\\\\ __ | {{~{ //}~}} ||/(===o |\n |||| | \\\\|o=|| {} {// } {} | / \\ | |\n |||| | \\()_|| {} // } {} \\/][][\\/ |\n ()|-==-| | {} H{{}}} {} |\\ /| |\n |----| | @ H"||"} @ |_||_| |\n | || | | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n________[_][__\\______|____[_][_]________/__][_]___|_______________\n1\n ==== |\\__________________________/|\n | o o | {o o"} |><> | |\n _\\ -/_ | {= } (/\\__) |\n / / \\ | {~~ //~} / \\ |\n | /| ""|\\\\ __ | {{~{ //}~}} ||/(===o |\n |||| | \\\\|o=|| {} {// } {} | / \\ | |\n |||| | \\()_|| {} // } {} \\/][][\\/ |\n ()|-==-| | {} H{{}}} {} |\\ /| |\n |----| | @ H"||"} @ |_||_| |\n | || | | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n________[_][__\\______|____[_][_]________/__][_]___|_______________\n2\n ==== | #### /__\\ |\n | o o | {o o"} |><> | |\n _\\ -/_ | {= } (/\\__) |\n / / \\ | {~~ //~} / \\ |\n | /| ""|\\\\ __ | {{~{ //}~}} ||/(===o |\n |||| | \\\\|o=|| {} {// } {} | / \\ | |\n |||| | \\()_|| {} // } {} \\/][][\\/ |\n ()|-==-| | {} H{{}}} {} |\\ /| |\n |----| | @ H"||"} @ |_||_| |\n | || | | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n________[_][__\\______|____[_][_]________/__][_]___|_______________\n2\n ==== | #### /__\\ |\n | O O | {o o"} |><> | |\n _\\ -/_ | {= } (/\\__) |\n / / \\ | {~~ //~} / \\ |\n | /| ""|\\\\ __ | {{~{ //}~}} ||/(===o |\n |||| | \\\\|o=|| {} {// } {} | / \\ | |\n |||| | \\()_|| {} // } {} \\/][][\\/ |\n ()|-==-| | {} H{{}}} {} |\\ /| |\n |----| | @ H"||"} @ |_||_| |\n | || | | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n________[_][__\\______|____[_][_]________/__][_]___|_______________\n3\n ==== | #### /__\\ |\n | O O | {o o"} |><> | |\n _\\ o/_ | {= } (/\\__) |\n / / \\ | {~~ //~} / \\ |\n | /| ""|\\\\ __ | {{~{ //}~}} ||/(===o |\n |||| | \\\\|o=|| {} {// } {} | / \\ | |\n |||| | \\()_|| {} // } {} \\/][][\\/ |\n ()|-==-| | {} H{{}}} {} |\\ /| |\n |----| | @ H"||"} @ |_||_| |\n | || | | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n________[_][__\\______|____[_][_]________/__][_]___|_______________\n1\n ==== | #### /__\\ |\n | o o | {o o"} |><> | |\n _\\ o/_ | {= } (/\\__) |\n / / \\ | {~~ //~} / \\ |\n | /| ""|\\\\ __ | {{~{ //}~}} ||/(===o |\n |||| | \\\\|o=|| {} {// } {} | / \\ | |\n |||| | \\()_|| {} // } {} \\/][][\\/ |\n ()|-==-| | {} H{{}}} {} |\\ /| |\n |----| | @ H"||"} @ |_||_| |\n | || | | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n________[_][__\\______|____[_][_]________/__][_]___|_______________\n1\n ==== | #### /__\\ |\n | o o | {o o"} |><> | |\n _\\ o/_ | {= } (/\\__) |\n / / \\ | {~~ //~} / \\ |\n | /| ""|\\\\ __ | {{~{ //}~}} ||/(===o |\n |||| | \\\\|o=|| {} {// } {} | / \\ | |\n |||| | \\()_|| {} // } {} \\/][][\\/ |\n ()|-==-| | {} H{{}}} {} |\\ /| |\n |----| | @ H"||"} @ |_||_| |\n | || | | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n________[_][__\\______|____[_][_]________/__][_]___|_______________\n1\n ==== | #### /__\\ |\n | o o | {o o"} |><> | |\n _\\ o/_ | {= } (/\\__) |\n / / \\ | {~~ //~} / \\ |\n | /| ""|\\\\ __ | {{~{ //}~}} ||/(===o |\n |||| | \\\\|o=|| {} {// } {} | / \\ | |\n |||| | \\()_|| {} // } {} \\/][][\\/ |\n ()|-==-| | {} H{{}}} {} |\\ /| |\n |----| | @ H"||"} @ |_||_| |\n | || | | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n________[_][__\\______|____[_][_]________/__][_]___|_______________\n1\n ==== | #### /__\\ |\n | o o | {o o"} |><> | |\n _\\ o/_ | {= } (/\\__) |\n / / \\ | {~~ //~} / \\ |\n | /| ""|\\\\ __ | {{~{ //}~}} ||/(===o |\n |||| | \\\\|o=|| {} {// } {} | / \\ | |\n |||| | \\()_|| {} // } {} \\/][][\\/ |\n ()|-==-| | {} H{{}}} {} |\\ /| |\n |----| | @ H"||"} @ |_||_| |\n | || | | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n________[_][__\\______|____[_][_]________/__][_]___|_______________\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n1\n -=== | _______\n | o o | "" / \\ o*oo\n _\\ -/_ | :. | | o**o\n / / \\ | | | *oo*\n // | "\'|\\\\ | ## | | o**o\n // || | \\\\ | ## \\_______/\n // || | =]==- |______________________\n () |-==-| #) /\n |----| |------------------------\n | || | | (*)\n | || | |\n |_||_| |\n______________[_][__\\_____________________|________________________\n2\n -=== | _______\n | o o | "" / \\ oo*o\n _\\ -/_ | :. | | o**o\n / / \\ | | | *oo*\n // | "\'|\\\\ | ## | | o**o\n // || | \\\\ | ## \\_______/\n // || | =]==- |______________________\n () |-==-| #) /\n |----| |------------------------\n | || | | (*)\n | || | |\n |_||_| |\n______________[_][__\\_____________________|________________________\n1\n -=== | _______\n | o o | "" / \\ oo*o\n _\\ -/_ | :. | | o**o\n / / \\ | | | *oo*\n // | "\'|\\\\ | ## | |-----\n // || | \\\\ | ## \\_______/\n // || | =]==- |______________________\n () |-==-| #) /\n |----| |------------------------\n | || | | (*)\n | || | |\n |_||_| |\n______________[_][__\\_____________________|________________________\n1\n -=== | _______\n | o o | "" / \\ oo*o\n _\\ -/_ | :. | | o**o\n / / \\ | | | *oo*\n // | "\'|\\\\ | ## | ----- o*oo\n // || | \\\\ | ## \\_______/\n // || | =]==- |______________________\n () |-==-| #) /\n |----| |------------------------\n | || | | (*)\n | || | |\n |_||_| |\n______________[_][__\\_____________________|________________________\n1\n -=== | _______\n | o o | "" / \\ oo*o\n _\\ -/_ | :. | | o**o\n / / \\ | | | *oo*\n // | "\'|\\\\ | ## |----- | o*oo\n // || | \\\\ | ## \\_______/\n // || | =]==- |______________________\n () |-==-| #) /\n |----| |------------------------\n | || | | (*)\n | || | |\n |_||_| |\n______________[_][__\\_____________________|________________________\n1\n -=== | _______\n | o o | "" / \\ oo*o\n _\\ -/_ | :. | | o**o\n / / \\ | | | *oo*\n // | "\'|\\\\ | ----- | o**o\n // || | \\\\ | ## \\_______/\n // || | =]==- |______________________\n () |-==-| #) /\n |----| |------------------------\n | || | | (*)\n | || | |\n |_||_| |\n______________[_][__\\_____________________|________________________\n1\n -=== | _______\n | o o | "" / \\ oo*o\n _\\ -/_ | :. | | o**o\n / / \\ | | | *oo*\n // | "\'|\\\\ -----## | | o**o\n // || | \\\\ | ## \\_______/\n // || | =]==- |______________________\n () |-==-| #) /\n |----| |------------------------\n | || | | (*)\n | || | |\n |_||_| |\n______________[_][__\\_____________________|________________________\n1\n -=== | _______\n | o o | "" / \\ oo*o\n _\\ -/_ | :. | | o**o\n / / \\ | | | *oo*\n // | "\'|\\\\ ----- | ## | | o**o\n // || | \\\\ | ## \\_______/\n // || | =]==- |______________________\n () |-==-| #) /\n |----| |------------------------\n | || | | (*)\n | || | |\n |_||_| |\n______________[_][__\\_____________________|________________________\n1\n -=== | _______\n | o o | "" / \\ oo*o\n _\\ o/_ | :. | | o**o\n / / \\ | | | *oo*\n // | "\'|\\\\ ----- | ## | | o*oo\n // || | \\\\ | ## \\_______/\n // || | =]==- |______________________\n () |-==-| #) /\n |----| |------------------------\n | || | | (*)\n | || | |\n |_||_| |\n______________[_][__\\_____________________|________________________\n1\n -=== | _______\n | o o | "" / \\ oo*o\n _\\ o/_ | :. | | o**o\n / / \\ | | | *oo*\n // | "\'|\\\\ ----- | ## | | o*oo\n // || | \\\\ | ## \\_______/\n // || | =]==- |______________________\n () |-==-| #) /\n |----| |------------------------\n | || | | (*)\n | || | |\n |_||_| |\n______________[_][__\\_____________________|________________________\n1\n -=== | _______\n | o o | "" / \\ oo*o\n _\\ o/_ | :. | | o**o\n / / \\ | | | *oo*\n // | "\'|\\----- | ## | | o*oo\n // || | \\\\ | ## \\_______/\n // || | =]==- |______________________\n () |-==-| #) /\n |----| |------------------------\n | || | | (*)\n | || | |\n |_||_| |\n______________[_][__\\_____________________|________________________\n1\n -=== | _______\n | o o | "" / \\ oo*o\n _\\ o/_ | :. | | o**o\n / / \\ | | | *oo*\n // | *---\\ | ## | | o**o\n // || | \\\\ | ## \\_______/\n // || | =]==- |______________________\n () |-==-| #) /\n |----| |------------------------\n | || | | (*)\n | || | |\n |_||_| |\n______________[_][__\\_____________________|________________________\n1\n -=== | _______\n | O O | "" / \\ oo*o\n _\\ */_ | :. | | o**o\n / /* \\ | | | *oo*\n // *****\\\\ | ## | | o**o\n // || * | \\\\ | ## \\_______/\n // || * | =]==- |______________________\n () |-==-| #) /\n |----| |------------------------\n | || | | (*)\n | || | |\n |_||_| |\n______________[_][__\\_____________________|________________________\n1\n -=== | _______\n | O*O | "" / \\ oo*o\n . _\\***_. | :. | | o**o\n /.*****\\ | | | *oo*\n //*******\\ | ## | | o**o\n //.|*****.\\\\ | ## \\_______/\n // ||***|.=]==- |______________________\n () |-=*-| #) /\n |----| |------------------------\n | || | | (*)\n | || | |\n |_||_| |\n______________[_][__\\_____________________|________________________\n1\n -=*= | _______\n |.***. . | "" / \\ oo*o\n . ._***** | :. | | o**o\n /******* | | | *oo*\n /*********. | ## | | o*oo\n // *******\\\\ | ## \\_______/\n //. .***** =]==- |______________________\n () |-***|. #) /\n |--*-| |------------------------\n | || | | (*)\n | || | |\n |_||_| |\n______________[_][__\\_____________________|________________________\n1\n . -=== | _______\n . | X*X | "" / \\ oo*o\n _\\***_ . | :. | | o**o\n . / *****\\ | | | *oo*\n //*******\\ | ## | | o*oo\n // |***** \\\\ . | ## \\_______/\n // ||***| =]==- |______________________\n () |-=*-| #) /\n . |----| |------------------------\n | || | . | (*)\n | || | |\n |_||_| |\n______________[_][__\\_____________________|________________________\n1\n -=== | _______\n . | X X | "" / \\ oo*o\n . _\\ * _ | :. | | o**o\n / ***\\\\ . | | | *oo*\n //|*****\\\\ | ## | | o*oo\n . // ||*** \\\\ | ## \\_______/\n // || * | =]==- |______________________\n () |-==-| #) . /\n |----| |------------------------\n | || | | (*)\n . | || | |\n |_||_| . |\n______________[_][__\\_____________________|________________________\n1\n -=== | _______\n . | X X | "" / \\ oo*o\n _\\ - _ | :. | | o**o\n / /* \\\\ | | | *oo*\n //||*** \\\\ | ## | | o**o\n // || * | \\\\ | ## \\_______/\n // || # | =]==- |______________________\n () |-==-| #) /\n |----| |------------------------\n | || | | (*)\n | || | . |\n . |_||_| |\n______________[_][__\\_____________________|________________________\n1\n -=== | _______\n . | X X | "" / \\ oo*o\n _\\ - _ | :. | | o**o\n / /# \\\\ | | | *oo*\n //||### \\\\ | ## | | o**o\n // ||###| \\\\ | ## \\_______/\n // || # | =]==- |______________________\n () |-==-| #) /\n |----| |------------------------\n | || | | (*)\n | || | . |\n . |_||_| |\n______________[_][__\\_____________________|________________________\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n2\n ===- | #### ==== |\n o o"" | {o o"} o o~~ |\n _\\- /_ | {= } _\\- /_ |\n / \\ | {~~ //~} / \\ |\n //| __ |\\\\ __ | {{~{ //}~}} ||/(===o |\n // |/ \\| \\\\ |o=|| {} {// } {} | / \\ | |\n// [][][] || |__|| {} // } {} \\/][][\\/ |\n|\' |\\ /| [# | {} H{{}}} {} |\\ /| |\n |_||_| I] | @ H"||"} @ |_||_| |\n [ ][ ] I | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n___/__][_]___________|____[_][_]________/__][_]___|_______________\n4\n -=== | #### ==== |\n ""o o | {o o"} o o~~ |\n _\\ -/_ | {= } _\\- /_ |\n / \\ | {~~ //~} / \\ |\n //| __ |\\\\ __ | {{~{ //}~}} ||/(===o |\n // |/ \\| \\\\ |o=|| {} {// } {} | / \\ | |\n// [][][] || |__|| {} // } {} \\/][][\\/ |\n|\' |\\ /| [# | {} H{{}}} {} |\\ /| |\n |_||_| I] | @ H"||"} @ |_||_| |\n [ ][ ] I | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n___/__][_]___________|____[_][_]________/__][_]___|_______________\n3\n ===- | #### ==== |\n o o"" | {o o"} o o~~ |\n _\\- /_ | {= } _\\- /_ |\n / \\ | {~~ //~} / \\ |\n //| __ |\\\\ __ | {{~{ //}~}} ||/(===o |\n // |/ \\| \\\\ |o=|| {} {// } {} | / \\ | |\n// [][][] || |__|| {} // } {} \\/][][\\/ |\n|\' |\\ /| [# | {} H{{}}} {} |\\ /| |\n |_||_| I] | @ H"||"} @ |_||_| |\n [ ][ ] I | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n___/__][_]___________|____[_][_]________/__][_]___|_______________\n1\n -=== | #### ==== |\n ""o o | {o o"} o o~~ |\n _\\ -/_ | {= } _\\- /_ |\n / \\ | {~~ //~} / \\ |\n //| __ |\\\\ __ | {{~{ //}~}} ||/(===o |\n // |/ \\| \\\\ |o=|| {} {// } {} | / \\ | |\n// [][][] || |__|| {} // } {} \\/][][\\/ |\n|\' |\\ /| [# | {} H{{}}} {} |\\ /| |\n |_||_| I] | @ H"||"} @ |_||_| |\n [ ][ ] I | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n___/__][_]___________|____[_][_]________/__][_]___|_______________\n8\n -=== | #### ==== |\n ""o o | {o o"} o o~~ | Between his\n _\\ -/_ | {= } _\\- /_ | howling and\n / \\ | {~~ //~} / \\ | your blasting\n //| __ |\\\\ __ | {{~{ //}~}} ||/(===o | everything in\n // |/ \\| \\\\ |o=|| {} {// } {} | / \\ | | sight...\n// [][][] || |__|| {} // } {} \\/][][\\/ |\n|\' |\\ /| [# | {} H{{}}} {} |\\ /| |\n |_||_| I] | @ H"||"} @ |_||_| |\n [ ][ ] I | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n___/__][_]___________|____[_][_]________/__][_]___|_______________\n9\n ===- | #### ==== |\n o o"" | {o o"} o o~~ | Between his\n _\\- /_ | {= } _\\- /_ | howling and\n / \\ | {~~ //~} / \\ | your blasting\n //| __ |\\\\ __ | {{~{ //}~}} ||/(===o | everything in\n // |/ \\| \\\\ |o=|| {} {// } {} | / \\ | | sight...\n// [][][] || |__|| {} // } {} \\/][][\\/ |\n|\' |\\ /| [# | {} H{{}}} {} |\\ /| |\n |_||_| I] | @ H"||"} @ |_||_| |\n [ ][ ] I | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n___/__][_]___________|____[_][_]________/__][_]___|_______________\n7\n -=== | #### ==== |\n ""o o | {o o"} o o~~ | Between his\n _\\ -/_ | {= } _\\- /_ | howling and\n / \\ | {~~ //~} / \\ | your blasting\n //| __ |\\\\ __ | {{~{ //}~}} ||/(===o | everything in\n // |/ \\| \\\\ |o=|| {} {// } {} | / \\ | | sight...\n// [][][] || |__|| {} // } {} \\/][][\\/ |\n|\' |\\ /| [# | {} H{{}}} {} |\\ /| |\n |_||_| I] | @ H"||"} @ |_||_| |\n [ ][ ] I | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n___/__][_]___________|____[_][_]________/__][_]___|_______________\n7\n ===- | #### ==== |\n o o"" | {o o"} o o~~ | Between his\n _\\- /_ | {= } _\\- /_ | howling and\n / \\ | {~~ //~} / \\ | your blasting\n //| __ |\\\\ __ | {{~{ //}~}} ||/(===o | everything in\n // |/ \\| \\\\ |o=|| {} {// } {} | / \\ | | sight...\n// [][][] || |__|| {} // } {} \\/][][\\/ |\n|\' |\\ /| [# | {} H{{}}} {} |\\ /| |\n |_||_| I] | @ H"||"} @ |_||_| |\n [ ][ ] I | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n___/__][_]___________|____[_][_]________/__][_]___|_______________\n1\n -=== | #### ==== |\n ""o o | {o o"} o o~~ |\n _\\ -/_ | {= } _\\- /_ |\n / \\ | {~~ //~} / \\ |\n //| __ |\\\\ __ | {{~{ //}~}} ||/(===o |\n // |/ \\| \\\\ |o=|| {} {// } {} | / \\ | |\n// [][][] || |__|| {} // } {} \\/][][\\/ |\n|\' |\\ /| [# | {} H{{}}} {} |\\ /| |\n |_||_| I] | @ H"||"} @ |_||_| |\n [ ][ ] I | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n___/__][_]___________|____[_][_]________/__][_]___|_______________\n14\n -=== | #### ==== |\n ""o o | {o o"} o o~~ | ...it\'s a\n _\\ -/_ | {= } _\\- /_ | wonder the\n / \\ | {~~ //~} / \\ | whole station\n //| __ |\\\\ __ | {{~{ //}~}} ||/(===o | doesn\'t know\n // |/ \\| \\\\ |o=|| {} {// } {} | / \\ | | we\'re here!\n// [][][] || |__|| {} // } {} \\/][][\\/ |\n|\' |\\ /| [# | {} H{{}}} {} |\\ /| |\n |_||_| I] | @ H"||"} @ |_||_| |\n [ ][ ] I | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n___/__][_]___________|____[_][_]________/__][_]___|_______________\n12\n -=== | #### ==== |\n ""o o | {"o o} o o~~ | ...it\'s a\n _\\ -/_ | { =} _\\- /_ | wonder the\n / \\ | {~~ //~} / \\ | whole station\n //| __ |\\\\ __ | {{~{ //}~}} ||/(===o | doesn\'t know\n // |/ \\| \\\\ |o=|| {} {// } {} | / \\ | | we\'re here!\n// [][][] || |__|| {} // } {} \\/][][\\/ |\n|\' |\\ /| [# | {} H{{}}} {} |\\ /| |\n |_||_| I] | @ H"||"} @ |_||_| |\n [ ][ ] I | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n___/__][_]___________|____[_][_]________/__][_]___|_______________\n4\n -=== | #### ==== |\n ""o o | {o o"} o o~~ | ...it\'s a\n _\\ -/_ | {= } _\\- /_ | wonder the\n / \\ | {~~ //~} / \\ | whole station\n //| __ |\\\\ __ | {{~{ //}~}} ||/(===o | doesn\'t know\n // |/ \\| \\\\ |o=|| {} {// } {} | / \\ | | we\'re here!\n// [][][] || |__|| {} // } {} \\/][][\\/ |\n|\' |\\ /| [# | {} H{{}}} {} |\\ /| |\n |_||_| I] | @ H"||"} @ |_||_| |\n [ ][ ] I | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n___/__][_]___________|____[_][_]________/__][_]___|_______________\n1\n -=== | #### ==== |\n ""o o | {o o"} o o~~ |\n _\\ -/_ | {= } _\\- /_ |\n / \\ | {~~ //~} / \\ |\n //| __ |\\\\ __ | {{~{ //}~}} ||/(===o |\n // |/ \\| \\\\ |o=|| {} {// } {} | / \\ | |\n// [][][] || |__|| {} // } {} \\/][][\\/ |\n|\' |\\ /| [# | {} H{{}}} {} |\\ /| |\n |_||_| I] | @ H"||"} @ |_||_| |\n [ ][ ] I | {"||"} [ ][ ] |\n | || | | {"||"} | || | |\n |_||_| | {"||"} |_||_| |\n___/__][_]___________|____[_][_]________/__][_]___|_______________\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n3\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. | | o**o\n / \\ ___ | | | *oo*\n //|/.\\|\\\\ / ()\\ | ## | | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. | | o**o\n / \\ ___ | | | *oo*\n //|/.\\|\\\\ / ()\\ | ## | | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n /~\\ | _______\n ( oo| We found the | "" / \\ oo*o\n _\\=/_ computer outlet | :. | | o**o\n / \\ sir! ___ | | | *oo*\n //|/.\\|\\\\ / ()\\ | ## | | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n3\n /~\\ | _______\n ( oo| We found the | "" / \\ oo*o\n _\\=/_ computer outlet | :. | | o**o\n / \\ sir! ___ | | | *oo*\n //|/.\\|\\\\ / ()\\ | ## | | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n3\n /~\\ | _______\n ( oo| We found the | "" / \\ oo*o\n _\\=/_ computer outlet | :. | | o**o\n / \\ sir! ___ | | | *oo*\n //|/.\\|\\\\ / ()\\ | ## | | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n3\n /~\\ | _______\n ( oo| We found the | "" / \\ oo*o\n _\\=/_ computer outlet | :. | | o**o\n / \\ sir! ___ | | | *oo*\n //|/.\\|\\\\ / ()\\ | ## | | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n3\n /~\\ | _______\n ( oo| We found the | "" / \\ oo*o\n _\\=/_ computer outlet | :. | | o**o\n / \\ sir! ___ | | | *oo*\n //|/.\\|\\\\ / ()\\ | ## | | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n3\n /~\\ | _______\n ( oo| We found the | "" / \\ oo*o\n _\\=/_ computer outlet | :. | | o**o\n / \\ sir! ___ | | | *oo*\n //|/.\\|\\\\ / ()\\ | ## | | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n3\n /~\\ | _______\n ( oo| We found the | "" / \\ oo*o\n _\\=/_ computer outlet | :. | | o**o\n / \\ sir! ___ | | | *oo*\n //|/.\\|\\\\ / ()\\ | ## | | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n3\n /~\\ | _______\n ( oo| We found the | "" / \\ oo*o\n _\\=/_ computer outlet | :. | | o**o\n / \\ sir! ___ | | | *oo*\n //|/.\\|\\\\ / ()\\ | ## | | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n3\n /~\\ | _______\n ( oo| We found the | "" / \\ oo*o\n _\\=/_ computer outlet | :. | | o**o\n / \\ sir! ___ | | | *oo*\n //|/.\\|\\\\ / ()\\ | ## | | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n /~\\ | _______\n ( oo| We found the | "" / \\ oo*o\n _\\=/_ computer outlet | :. | | o**o\n / \\ sir! ___ | | | *oo*\n //|/.\\|\\\\ / ()\\ | ## | | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. | | o**o\n / \\ ___ | | | *oo*\n //|/.\\|\\\\ / ()\\ | ## | | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. | | o**o\n / \\ ___ | | | *oo*\n //|/.\\|\\\\ / ()\\ | ## | | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n3\n ==== ==== |\n (o o") o o~~ |\n _\\- /_ _\\- /_ |\n / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\n Plug in. (o o") o o~~ |\n He should be able _\\- /_ _\\- /_ |\n to interpret / \\ / \\ / \\ |\n the entire / \\/ \\ //| __ |\\\\ __ |\n Imperial / /| | |\\ | // |/ \\| || |o=||\n network. || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n2\n ==== ==== |\n Plug in. (o o") ~~o o |\n He should be able _\\- /_ _\\ -/_ |\n to interpret / \\ / \\ / \\ |\n the entire / \\/ \\ //| __ |\\\\ __ |\n Imperial / /| | |\\ | // |/ \\| || |o=||\n network. || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\n Plug in. (o o") ~~o o |\n He should be able _\\- /_ _\\ -/_ |\n to interpret / \\ / \\ / \\ |\n the entire / \\/ \\ //| __ |\\\\ __ |\n Imperial / /| | |\\ | // |/ \\| \\\\ |o=||\n network. || | | | || // [][][] \\\\|__||\n (\' | | | \') |\' |\\ /| \') |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\n Plug in. (o o") ~~o o |\n He should be able _\\- /_ _\\ -/_ |\n to interpret / \\ / \\ / \\ |\n the entire / \\/ \\ //| __ |\\\\ __ |\n Imperial / /| | |\\ | // |/ \\| \\\\ |*=||\n network. || | | | || // [][][] \\\\|__||\n (\' | | | \') |\' |\\ /| \') |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\\________\n Plug in. (o o") ~~o o |\n He should be able _\\- /_ _\\ -/_ |\n to interpret / \\ / \\ / \\ |\n the entire / \\/ \\ //| __ |\\\\ __ |\n Imperial / /| | |\\ | // |/ \\| \\\\ |*=||\n network. || | | | || // [][][] \\\\|__||\n (\' | | | \') |\' |\\ /| \') |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\n Plug in. (o o") ~~o o |\\________\n He should be able _\\- /_ _\\ -/_ |\n to interpret / \\ / \\ / \\ |\n the entire / \\/ \\ //| __ |\\\\ __ |\n Imperial / /| | |\\ | // |/ \\| \\\\ |o=||\n network. || | | | || // [][][] \\\\|__||\n (\' | | | \') |\' |\\ /| \') |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\n Plug in. (o o") ~~o o |\n He should be able _\\- /_ _\\ -/_ |\\________\n to interpret / \\ / \\ / \\ |\n the entire / \\/ \\ //| __ |\\\\ __ |\n Imperial / /| | |\\ | // |/ \\| \\\\ |o=||\n network. || | | | || // [][][] \\\\|__||\n (\' | | | \') |\' |\\ /| \') |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\n Plug in. (o o") ~~o o |\n He should be able _\\- /_ _\\ -/_ |\n to interpret / \\ / \\ / \\ |\\________\n the entire / \\/ \\ //| __ |\\\\ __ |\n Imperial / /| | |\\ | // |/ \\| \\\\ |*=||\n network. || | | | || // [][][] \\\\|__||\n (\' | | | \') |\' |\\ /| \') |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\n Plug in. (o o") ~~o o |\n He should be able _\\- /_ _\\ -/_ |\n to interpret / \\ / \\ / \\ |\n the entire / \\/ \\ //| __ |\\\\ __ |\\________\n Imperial / /| | |\\ | // |/ \\| \\\\ |*=||\n network. || | | | || // [][][] \\\\|__||\n (\' | | | \') |\' |\\ /| \') |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\n Plug in. (o o") ~~o o |\n He should be able _\\- /_ _\\ -/_ |\n to interpret / \\ / \\ / \\ |\n the entire / \\/ \\ //| __ |\\\\ __ |\n Imperial / /| | |\\ | // |/ \\| \\\\ |o=||\\________\n network. || | | | || // [][][] \\\\|__||\n (\' | | | \') |\' |\\ /| \') |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\n Plug in. (o o") ~~o o |\n He should be able _\\- /_ _\\ -/_ |\n to interpret / \\ / \\ / \\ |\n the entire / \\/ \\ //| __ |\\\\ __ |\n Imperial / /| | |\\ | // |/ \\| \\\\ |o=||\n network. || | | | || // [][][] \\\\|__||\\________\n (\' | | | \') |\' |\\ /| \') |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\n Plug in. (o o") o o~~ |\n He should be able _\\- /_ _\\- /_ |\n to interpret / \\ / \\ / \\ |\n the entire / \\/ \\ //| __ |\\\\ __ |\n Imperial / /| | |\\ | // |/ \\| || |o=||\n network. || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\\________\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\n Plug in. (o o") o o~~ |\n He should be able _\\- /_ _\\- /_ |\n to interpret / \\ / \\ / \\ |\n the entire / \\/ \\ //| __ |\\\\ __ |\n Imperial / /| | |\\ | // |/ \\| || |o=||\n network. || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\\________\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\n Plug in. (o o") o o~~ |\n He should be able _\\- /_ _\\- /_ |\n to interpret / \\ / \\ / \\ |\n the entire / \\/ \\ //| __ |\\\\ __ |\n Imperial / /| | |\\ | // |/ \\| || |o=||\n network. || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\\________\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\n Plug in. (o o") o o~~ |\n He should be able _\\- /_ _\\- /_ |\n to interpret / \\ / \\ / \\ |\n the entire / \\/ \\ //| __ |\\\\ __ |\n Imperial / /| | |\\ | // |/ \\| || |o=||\n network. || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\\________\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\n Plug in. (o o") o o~~ |\n He should be able _\\- /_ _\\- /_ |\n to interpret / \\ / \\ / \\ |\n the entire / \\/ \\ //| __ |\\\\ __ |\n Imperial / /| | |\\ | // |/ \\| || |o=||\n network. || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\\________\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\n Plug in. (o o") o o~~ |\n He should be able _\\- /_ _\\- /_ |\n to interpret / \\ / \\ / \\ |\n the entire / \\/ \\ //| __ |\\\\ __ |\n Imperial / /| | |\\ | // |/ \\| || |o=||\n network. || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|\\________\n13\n ==== ==== |\n Plug in. (o o") o o~~ |\n He should be able _\\- /_ _\\- /_ |\n to interpret / \\ / \\ / \\ |\n the entire / \\/ \\ //| __ |\\\\ __ |\n Imperial / /| | |\\ | // |/ \\| || |o=||\n network. || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n6\n ==== ==== |\n (o o") o o~~ |\n _\\- /_ _\\- /_ |\n / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n3\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. | | o**o\n / \\ ___ | | | *oo*\n //|/.\\|\\\\ / ()\\ | ## | | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n3\n /~\\ | _______\n ( oo| He says he\'s | "" / # /\\ \\ *ooo\n _\\=/_ found the main | :. | # / O| | o**o\n / \\ controls to ___ | |###======| *oo*\n //|/.\\|\\\\ the power beam / ()\\ | ## | #____| | o*oo\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n /~\\ | _______\n ( oo| He says he\'s | "" / \\ oo*o\n _\\=/_ found the main | :. | | o**o\n / \\ controls to ___ | | | *oo*\n //|/.\\|\\\\ the power beam / ()\\ | ## | | o**o\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| He says he\'s | "" / ||OO \\ ooo*\n _\\=/_ found the main | :. | ||OO__| o**o\n / \\ controls to ___ | | // ____| o*o*\n //|/.\\|\\\\ the power beam / ()\\ | ## | //##.. | o**o\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n /~\\ | _______\n ( oo| He says he\'s | "" / ||OO \\ ooo*\n _\\=/_ found the main | :. | ||OO__| o**o\n / \\ controls to ___ | | // ____| o*o*\n //|/.\\|\\\\ the power beam / ()\\ | ## | //##.. | o*oo\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n /~\\ | _______\n ( oo| He says he\'s | "" / \\ ooo*\n _\\=/_ found the main | :. | | o**o\n / \\ controls to ___ | | | o*o*\n //|/.\\|\\\\ the power beam / ()\\ | ## | | o*oo\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n /~\\ | _______\n ( oo| He says he\'s | "" /< \\\\ \\ ooo*\n _\\=/_ found the main | :. | < || | o*o*\n / \\ controls to ___ | |=========| *oo*\n //|/.\\|\\\\ the power beam / ()\\ | ## | OOO> \\\\| o*oo\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| He says he\'s | "" /< \\\\ \\ ooo*\n _\\=/_ found the main | :. | < || | o*o*\n / \\ controls to ___ | |=========| *oo*\n //|/.\\|\\\\ the power beam / ()\\ | ## | OOO> \\\\| o**o\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n /~\\ | _______\n ( oo| He says he\'s | "" / \\ ooo*\n _\\=/_ found the main | :. | | o*o*\n / \\ controls to ___ | | | *oo*\n //|/.\\|\\\\ the power beam / ()\\ | ## | | o**o\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n3\n /~\\ | _______\n ( oo| He says he\'s | "" / | | \\ oo*o\n _\\=/_ found the main | :. |== ====| o*o*\n / \\ controls to ___ | | | |#<> | *o*o\n //|/.\\|\\\\ the power beam / ()\\ | ## |_/ \\___| o*oo\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n /~\\ | _______\n ( oo| He says he\'s | "" / \\ oo*o\n _\\=/_ found the main | :. | | o*o*\n / \\ controls to ___ | | | *o*o\n //|/.\\|\\\\ the power beam / ()\\ | ## | | o**o\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| He says he\'s | "" /_______\\ *o*o\n _\\=/_ found the main | :. |[][][]===| o**o\n / \\ controls to ___ | |_________| *oo*\n //|/.\\|\\\\ the power beam / ()\\ | ## |[][][]===| ***o\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n /~\\ | _______\n ( oo| He says he\'s | "" /_______\\ *o*o\n _\\=/_ found the main | :. |[][][]===| o**o\n / \\ controls to ___ | |_________| *oo*\n //|/.\\|\\\\ the power beam / ()\\ | ## |[][][]===| **oo\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n /~\\ | _______\n ( oo| He says he\'s | "" / \\ *o*o\n _\\=/_ found the main | :. | | o**o\n / \\ controls to ___ | | | *oo*\n //|/.\\|\\\\ the power beam / ()\\ | ## | | **oo\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n /~\\ | _______\n ( oo| He says he\'s | "" /--\\ .\\ oo*o\n _\\=/_ found the main | :. | |..\\ . | o**o\n / \\ controls to ___ | | |:: | . | *oo*\n //|/.\\|\\\\ the power beam / ()\\ | ## |=====|. .| o*oo\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| He says he\'s | "" /--\\ .\\ oo*o\n _\\=/_ found the main | :. | |..\\ . | o**o\n / \\ controls to ___ | | |:: | . | *oo*\n //|/.\\|\\\\ the power beam / ()\\ | ## |=====|. .| o**o\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n /~\\ | _______\n ( oo| He says he\'s | "" / \\ oo*o\n _\\=/_ found the main | :. | | o**o\n / \\ controls to ___ | | | *oo*\n //|/.\\|\\\\ the power beam / ()\\ | ## | | o**o\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n3\n /~\\ | _______\n ( oo| He says he\'s | "" / || || \\ oo*o\n _\\=/_ found the main | :. |__OO_OO__| o**o\n / \\ controls to ___ | |__ _ __| *oo*\n //|/.\\|\\\\ the power beam / ()\\ | ## | OO OO | oo**\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n /~\\ | _______\n ( oo| He says he\'s | "" / \\ oo*o\n _\\=/_ found the main | :. | | o**o\n / \\ controls to ___ | | | *oo*\n //|/.\\|\\\\ the power beam / ()\\ | ## | | oo**\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n3\n /~\\ | _______\n ( oo| He says he\'s | "" / .o. \\ oo*o\n _\\=/_ found the main | :. | o|||o | oooo\n / \\ controls to ___ | | o | o | *oo*\n //|/.\\|\\\\ the power beam / ()\\ | ## |/__/_\\__\\| oo**\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n /~\\ | _______\n ( oo| He says he\'s | "" / \\ oo*o\n _\\=/_ found the main | :. | | oooo\n / \\ controls to ___ | | | *oo*\n //|/.\\|\\\\ the power beam / ()\\ | ## | | oo**\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n6\n /~\\ | _______\n ( oo| He says he\'s | "" / \\ oo*o\n _\\=/_ found the main | :. | .o. | *ooo\n / \\ controls to ___ | |___ooo___| *oo*\n //|/.\\|\\\\ the power beam / ()\\ | ## |---------| o*oo\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| He says he\'s | "" / \\ oo*o\n _\\=/_ found the main | :. | .*. | *ooo\n / \\ controls to ___ | |___ooo___| *oo*\n //|/.\\|\\\\ the power beam / ()\\ | ## |---------| o*oo\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| He says he\'s | "" / \\ oo*o\n _\\=/_ found the main | :. | .o. | *ooo\n / \\ controls to ___ | |___ooo___| *oo*\n //|/.\\|\\\\ the power beam / ()\\ | ## |---------| o*oo\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| He says he\'s | "" / \\ oo*o\n _\\=/_ found the main | :. | .*. | *ooo\n / \\ controls to ___ | |___ooo___| *oo*\n //|/.\\|\\\\ the power beam / ()\\ | ## |---------| o*oo\n || \\_/ || holding the _|_____|_ | ## \\_______/\n || |\\ /| || ship here. | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. | .o. | *ooo\n / \\ ___ | |___ooo___| *oo*\n //|/.\\|\\\\ / ()\\ | ## |---------| o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. | .*. | *ooo\n / \\ ___ | |___ooo___| *oo*\n //|/.\\|\\\\ / ()\\ | ## |---------| o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. | .o. | *ooo\n / \\ ___ | |___ooo___| *oo*\n //|/.\\|\\\\ / ()\\ | ## |---------| o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. | .*. | *ooo\n / \\ ___ | |___ooo___| *oo*\n //|/.\\|\\\\ / ()\\ | ## |---------| o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. | .o. | *ooo\n / \\ ___ | |___ooo___| *oo*\n //|/.\\|\\\\ / ()\\ | ## |---------| o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. | .*. | *ooo\n / \\ ___ | |___ooo___| *oo*\n //|/.\\|\\\\ / ()\\ | ## |---------| o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. | .o. | *ooo\n / \\ ___ | |___ooo___| *oo*\n //|/.\\|\\\\ / ()\\ | ## |---------| o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. | .*. | *ooo\n / \\ ___ | |___ooo___| *oo*\n //|/.\\|\\\\ / ()\\ | ## |---------| o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. | .o. | *ooo\n / \\ ___ | |___ooo___| *oo*\n //|/.\\|\\\\ / ()\\ | ## |---------| o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. | .*. | *ooo\n / \\ ___ | |___ooo___| *oo*\n //|/.\\|\\\\ / ()\\ | ## |---------| o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. | .o. | *ooo\n / \\ ___ | |___ooo___| *oo*\n //|/.\\|\\\\ / ()\\ | ## |---------| o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n3\n ==== ==== |\n (o o") o o~~ |\n _\\- /_ _\\- /_ |\n / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\n ("o o) o o~~ |\n _\\ -/_ _\\- /_ |\n / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n6\n ==== ==== |\n I don\'t think ("o o) o o~~ |\n you boys can help. _\\ -/_ _\\- /_ |\n / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n19\n ==== ==== |\n I don\'t think (o o") o o~~ |\n you boys can help. _\\- /_ _\\- /_ |\n / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\n (o o") o o~~ |\n _\\- /_ _\\- /_ |\n / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n8\n ==== ==== |\n I must go alone. (o o") o o~~ |\n _\\- /_ _\\- /_ |\n / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n15\n ==== ==== |\n I must go alone. ("o o) o o~~ |\n _\\ -/_ _\\- /_ |\n / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n6\n ==== ==== |\n ("o o) o o~~ |\n _\\ -/_ _\\- /_ |\n / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n25\n ==== I want to ==== |\n ("o o) go with you! o o~~ |\n _\\ -/_ _\\- /_ |\n / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n4\n ==== ==== |\n ("o o) o o~~ |\n _\\ -/_ _\\- /_ |\n / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n30\n ==== ==== |\n Be patient, Luke. ("o o) o o~~ |\n Stay and watch _\\ -/_ _\\- /_ |\n over the droids. / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\n ("o o) o o~~ |\n _\\ -/_ _\\- /_ |\n / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n20\n ==== But he can... ==== |\n ("o o) o o~~ |\n _\\ -/_ _\\- /_ |\n / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\n ("o o) o o~~ |\n _\\ -/_ _\\- /_ |\n / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n29\n ==== ==== |\n Your destiny ("o o) o o~~ |\n lies along a _\\ -/_ _\\- /_ |\n different path to / \\ / \\ / \\ |\n mine. / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n2\n ==== ==== |\n ("o o) o o~~ |\n _\\ -/_ _\\- /_ |\n / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n21\n ==== ==== |\n The Force will ("o o) o o~~ |\n be with you... _\\ -/_ _\\- /_ |\n / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n1\n ==== ==== |\n ("o o) o o~~ |\n _\\ -/_ _\\- /_ |\n / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n20\n ==== ==== |\n ("o o) o o~~ |\n ...always! _\\ -/_ _\\- /_ |\n / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n6\n ==== ==== |\n ("o o) o o~~ |\n _\\ -/_ _\\- /_ |\n / \\ / \\ / \\ |\n / \\/ \\ //| __ |\\\\ __ |\n / /| | |\\ | // |/ \\| || |o=||\n || | | | || // [][][] || |__||\n (\' | | | \') |\' |\\ /| \'| |\n | | | |_||_| |\n | |\\ | [ ][ ] |\n / || \\ | || | |\n / ||_|\\ |_||_| |\n__________________/____|[_]_\\______________[_][__\\_______|_________\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n17\n -=== ####\n ""o o {"o o}\n _\\ -/_ { =}\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n // |/ \\| \\\\ {} {// } {}\n // [][][] || {} // } {}\n |\' |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n4\n -=== ####\n ""o o {o o"}\n _\\ -/_ {= }\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n // |/ \\| \\\\ {} {// } {}\n // [][][] || {} // } {}\n |\' |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n38\n -=== ####\n Where did ""o o {o o"}\n you dig up _\\ -/_ {= }\n that old / \\ {~~ //~}\n fossil! //| __ |\\\\ {{~{ //}~}}\n // |/ \\| \\\\ {} {// } {}\n // [][][] || {} // } {}\n |\' |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n2\n -=== ####\n ""o o {o o"}\n _\\ -/_ {= }\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n // |/ \\| \\\\ {} {// } {}\n // [][][] || {} // } {}\n |\' |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n3\n -=== ####\n ""o o {"o o}\n _\\ -/_ { =}\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n // |/ \\| \\\\ {} {// } {}\n // [][][] || {} // } {}\n |\' |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n ==== |\n ~~o o |\n _\\ -/_ |\n / \\ |\n //| __ |\\\\ __ |\n // |/ \\| || |o=||\n // [][][] || |__||\n |\' |\\ /| \'| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n_____________________________________[_][__\\_______|_______________\n3\n ==== |\n o o~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n // |/ \\| || |o=||\n // [][][] || |__||\n |\' |\\ /| \'| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n_____________________________________[_][__\\_______|_______________\n5\n ==== |\n o o~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n // |/ \\| || |o=||\n // [][][] || |__||\n |\' |\\ /| \'| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][__\\_______|_______________\n5\n ==== |\n o o~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n \\\\|/ \\|// |o=||\n #[][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][__\\_______|_______________\n19\n ==== |\n Ben is o o~~ |\n a great man! _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n \\\\|/ \\|// |o=||\n #[][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][__\\_______|_______________\n13\n ==== |\n Ben is o o~~ |\n a great man! _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n \\\\|/ \\|// |o=||\n #[][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n5\n ==== |\n o o~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n \\\\|/ \\|// |o=||\n #[][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n1\n\n\n\n\n\n\n\n\n\n\n\n\n\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. | | o**o\n / \\ ___ | | | *oo*\n //|/.\\|\\\\ / ()\\ | ## | | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n3\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. | | o**o\n / \\ ___ | | | *oo*\n //|/.\\|\\\\ /() \\ | ## | | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. | | o**o\n / \\ ___ | | | *oo*\n //|/.\\|\\\\ / ()\\ | ## | | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. |__[]_[]__| o**o\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ / ()\\ | ## | [] [] | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. |__[]_[]__| o**o\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ /() \\ | ## | [] [] | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. |__[]_[]__| o**o\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ / ()\\ | ## | [] [] | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n3\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. |__[]_[]__| o**o\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ /() \\ | ## | [] [] | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. |__[]_[]__| o**o\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ / ()\\ | ## | [] [] | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. |__[]_[]__| o**o\n / \\ # ___ | |__ _ __| *oo*\n //|/.\\|\\\\// / ()\\ | ## | [] [] | o**o\n || \\_/ \\/ _|_____|_ | ## \\_______/\n || |\\ /| | | === | | |______________________\n # \\_ _/ |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. |__[]_[]__| o**o\n / \\ # ___ | |__ _ __| *oo*\n //|/.\\|\\\\// /() \\ | ## | [] [] | o**o\n || \\_/ \\/ _|_____|_ | ## \\_______/\n || |\\ /| | | === | | |______________________\n # \\_ _/ |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. |__[]_[]__| o**o\n / \\ # ___ | |__ _ __| *oo*\n //|/.\\|\\\\// / ()\\ | ## | [] [] | o**o\n || \\_/ \\/ _|_____|_ | ## \\_______/\n || |\\ /| | | === | | |______________________\n # \\_ _/ |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. |__[]_[]__| o**o\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ / ()\\ | ## | [] [] | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n3\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. |__[]_[]__| o**o\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ /() \\ | ## | [] [] | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. |__[]_[]__| o**o\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ / ()\\ | ## | [] [] | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. |__[]_[]__| o**o\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ /() \\ | ## | [] [] | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. |__[]_[]__| o**o\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ / ()\\ | ## | [] [] | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n3\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. |__[]_[]__| o**o\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ /() \\ | ## | [] [] | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. |__[]_[]__| o**o\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ / ()\\ | ## | [] [] | o**o\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. |__[]_[]__| o**o\n / \\ # ___ | |__ _ __| *oo*\n //|/.\\|\\\\// / ()\\ | ## | [] [] | o**o\n || \\_/ \\/ _|_____|_ | ## \\_______/\n || |\\ /| | | === | | |______________________\n # \\_ _/ |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. |__[]_[]__| o**o\n / \\ # ___ | |__ _ __| *oo*\n //|/.\\|\\\\// /() \\ | ## | [] [] | o**o\n || \\_/ \\/ _|_____|_ | ## \\_______/\n || |\\ /| | | === | | |______________________\n # \\_ _/ |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ oo*o\n _\\=/_ | :. |__[]_[]__| o**o\n / \\ # ___ | |__ _ __| *oo*\n //|/.\\|\\\\// / ()\\ | ## | [] [] | o**o\n || \\_/ \\/ _|_____|_ | ## \\_______/\n || |\\ /| | | === | | |______________________\n # \\_ _/ |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n3\n ==== |\n o o~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n // |/ \\| || |o=||\n // [][][] || |__||\n |\' |\\ /| \'| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n4\n ==== |\n o o~~ |\n _\\o /_ |\n / \\ |\n //| __ |\\\\ __ |\n // |/ \\| || |o=||\n // [][][] || |__||\n |\' |\\ /| \'| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n4\n ==== |\n o o~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n // |/ \\| || |o=||\n // [][][] || |__||\n |\' |\\ /| \'| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n18\n ==== |\n o o~~ |\n What is it? _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n // |/ \\| || |o=||\n // [][][] || |__||\n |\' |\\ /| \'| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n1\n ==== |\n o o~~ |\n What is it? _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n || |/ \\| || |o=||\n || [][][] || |__||\n |\' |\\ /| \'| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n6\n ==== |\n o o~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n || |/ \\| || |o=||\n || [][][] || |__||\n |\' |\\ /| \'| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n4\n\n\n\n\n\n\n\n\n\n\n\n\n\n11\n /~\\ | _______\n ( oo| He says he\'s | "" / \\ ooo*\n _\\=/_ found her... | :. |__[]_[]__| o*o*\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ / ()\\ | ## | [] [] | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n18\n /~\\ | _______\n ( oo| He says he\'s | "" / \\ ooo*\n _\\=/_ found her... | :. |__[]_[]__| o*o*\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ /() \\ | ## | [] [] | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n3\n /~\\ | _______\n ( oo| | "" / \\ ooo*\n _\\=/_ | :. |__[]_[]__| o*o*\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ /() \\ | ## | [] [] | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n10\n /~\\ | _______\n ( oo| And keeps repeating | "" / \\ ooo*\n _\\=/_ she\'s here. | :. |__[]_[]__| o*o*\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ /() \\ | ## | [] [] | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n5\n /~\\ | _______\n ( oo| And keeps repeating | "" / \\ ooo*\n _\\=/_ she\'s here. | :. |__[]_[]__| o*o*\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ / ()\\ | ## | [] [] | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n8\n /~\\ | _______\n ( oo| And keeps repeating | "" / \\ ooo*\n _\\=/_ she\'s here. | :. |__[]_[]__| o*o*\n / \\ # ___ | |__ _ __| *oo*\n //|/.\\|\\\\// / ()\\ | ## | [] [] | o*oo\n || \\_/ \\/ _|_____|_ | ## \\_______/\n || |\\ /| | | === | | |______________________\n # \\_ _/ |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n6\n /~\\ | _______\n ( oo| | "" / \\ ooo*\n _\\=/_ | :. |__[]_[]__| o*o*\n / \\ # ___ | |__ _ __| *oo*\n //|/.\\|\\\\// / ()\\ | ## | [] [] | o*oo\n || \\_/ \\/ _|_____|_ | ## \\_______/\n || |\\ /| | | === | | |______________________\n # \\_ _/ |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n1\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n ==== |\n o o~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n \\\\|/ \\|// |o=||\n #[][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n22\n ==== |\n o o~~ |\n Well who... _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n \\\\|/ \\|// |o=||\n #[][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n2\n ==== |\n o o~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n \\\\|/ \\|// |o=||\n #[][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n19\n ==== |\n o o~~ |\n who has he found? _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n \\\\|/ \\|// |o=||\n #[][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n4\n ==== |\n o o~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n \\\\|/ \\|// |o=||\n #[][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n1\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n /~\\ | _______\n ( oo| | "" / \\ ooo*\n _\\=/_ | :. |__[]_[]__| o*o*\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ / ()\\ | ## | [] [] | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n16\n /~\\ | _______\n ( oo| Princess Leia. | "" / \\ ooo*\n _\\=/_ | :. |__[]_[]__| o*o*\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ / ()\\ | ## | [] [] | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n4\n /~\\ | _______\n ( oo| | "" / \\ ooo*\n _\\=/_ | :. |__[]_[]__| o*o*\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ / ()\\ | ## | [] [] | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n2\n ==== |\n o o~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n \\\\|/ \\|// |o=||\n #[][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n1\n ==== |\n O O~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n \\\\|/ \\|// |o=||\n #[][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n3\n ==== |\n O O~~ |\n _\\o /_ |\n / \\ |\n //| __ |\\\\ __ |\n \\\\|/ \\|// |o=||\n #[][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n2\n ==== |\n o o~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n \\\\|/ \\|// |o=||\n #[][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n11\n ==== |\n o o~~ |\n The princess? _\\- /_ |\n / \\ |\n She\'s here? //| __ |\\\\ __ |\n \\\\|/ \\|// |o=||\n #[][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n13\n ==== |\n o o~~ |\n The princess? _\\- /_ |\n / \\ |\n She\'s here? //| __ |\\\\ __ |\n || |/ \\| || |o=||\n || [][][] || |__||\n |\' |\\ /| \'| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n4\n ==== |\n o o~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n || |/ \\| || |o=||\n || [][][] || |__||\n |\' |\\ /| \'| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n9\n -=== ####\n ""o o {"o o}\n _\\ -/_ { =}\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n // |/ \\| \\\\ {} {// } {}\n // [][][] || {} // } {}\n |\' |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n6\n -=== ####\n ""o o {o o"}\n _\\ -/_ {= }\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n // |/ \\| \\\\ {} {// } {}\n // [][][] || {} // } {}\n |\' |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n6\n -=== ####\n ""o o {o o"}\n _\\ -/_ {= }\n # / \\ {~~ //~}\n \\\\//| __ |\\\\ {{~{ //}~}}\n \\/ |/ \\| \\\\ {} {// } {}\n [][][] || {} // } {}\n |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n11\n -=== ####\n ""o o {o o"}\n Princess? _\\ -/_ {= }\n # / \\ {~~ //~}\n \\\\//| __ |\\\\ {{~{ //}~}}\n \\/ |/ \\| \\\\ {} {// } {}\n [][][] || {} // } {}\n |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n10\n -=== ####\n ""o o {"o o}\n Princess? _\\ -/_ { =}\n # / \\ {~~ //~}\n \\\\//| __ |\\\\ {{~{ //}~}}\n \\/ |/ \\| \\\\ {} {// } {}\n [][][] || {} // } {}\n |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n5\n -=== ####\n ""o o {"o o}\n _\\ -/_ { =}\n # / \\ {~~ //~}\n \\\\//| __ |\\\\ {{~{ //}~}}\n \\/ |/ \\| \\\\ {} {// } {}\n [][][] || {} // } {}\n |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n5\n /~\\ | _______\n ( oo| | "" / \\ ooo*\n _\\=/_ | :. |__[]_[]__| o*o*\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ / ()\\ | ## | [] [] | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n6\n /~\\ | _______\n ( oo| Level 5. | "" / \\ ooo*\n _\\=/_ Detention block | :. |__[]_[]__| o*o*\n / \\ AA-23. ___ | |__ _ __| *oo*\n //|/.\\|\\\\ / ()\\ | ## | [] [] | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n6\n /~\\ | _______\n ( oo| Level 5. | "" / \\ ooo*\n _\\=/_ Detention block | :. |__[]_[]__| o*o*\n / \\ AA-23. ___ | |__ _ __| *oo*\n //|/.\\|\\\\ /() \\ | ## | [] [] | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n7\n /~\\ | _______\n ( oo| Level 5. | "" / \\ ooo*\n _\\=/_ Detention block | :. |__[]_[]__| o*o*\n / \\ # AA-23. ___ | |__ _ __| *oo*\n //|/.\\|\\\\// /() \\ | ## | [] [] | o*oo\n || \\_/ \\/ _|_____|_ | ## \\_______/\n || |\\ /| | | === | | |______________________\n # \\_ _/ |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n3\n /~\\ | _______\n ( oo| Level 5. | "" / \\ ooo*\n _\\=/_ Detention block | :. |__[]_[]__| o*o*\n / \\ # AA-23. ___ | |__ _ __| *oo*\n //|/.\\|\\\\// /() \\ | ## | [] [] | o*oo\n || \\_/ \\/ _|_____|_ | ## \\_______/\n || |\\ /| | | === | | |______________________\n # \\_ _/ |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n7\n /~\\ | _______\n ( oo| Level 5. | "" / \\ ooo*\n _\\=/_ Detention block | :. |__[]_[]__| o*o*\n / \\ # AA-23. ___ | |__ _ __| *oo*\n //|/.\\|\\\\// / ()\\ | ## | [] [] | o*oo\n || \\_/ \\/ _|_____|_ | ## \\_______/\n || |\\ /| | | === | | |______________________\n # \\_ _/ |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n /~\\ | _______\n ( oo| | "" / \\ ooo*\n _\\=/_ | :. |__[]_[]__| o*o*\n / \\ # ___ | |__ _ __| *oo*\n //|/.\\|\\\\// / ()\\ | ## | [] [] | o*oo\n || \\_/ \\/ _|_____|_ | ## \\_______/\n || |\\ /| | | === | | |______________________\n # \\_ _/ |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n6\n /~\\ | _______\n ( oo| | "" / \\ ooo*\n _\\=/_ | :. |__[]_[]__| o*o*\n / \\ # ___ | |__ _ __| *oo*\n //|/.\\|\\\\// /() \\ | ## | [] [] | o*oo\n || \\_/ \\/ _|_____|_ | ## \\_______/\n || |\\ /| | | === | | |______________________\n # \\_ _/ |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n7\n /~\\ | _______\n ( oo| I\'m afraid she\'s | "" / \\ ooo*\n _\\=/_ scheduled for | :. |__[]_[]__| o*o*\n / \\ # termination. ___ | |__ _ __| *oo*\n //|/.\\|\\\\// /() \\ | ## | [] [] | o*oo\n || \\_/ \\/ _|_____|_ | ## \\_______/\n || |\\ /| | | === | | |______________________\n # \\_ _/ |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n9\n /~\\ | _______\n ( oo| I\'m afraid she\'s | "" / \\ ooo*\n _\\=/_ scheduled for | :. |__[]_[]__| o*o*\n / \\ termination. ___ | |__ _ __| *oo*\n //|/.\\|\\\\ /() \\ | ## | [] [] | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n6\n /~\\ | _______\n ( oo| I\'m afraid she\'s | "" / \\ ooo*\n _\\=/_ scheduled for | :. |__[]_[]__| o*o*\n / \\ termination. ___ | |__ _ __| *oo*\n //|/.\\|\\\\ / ()\\ | ## | [] [] | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n7\n /~\\ | _______\n ( oo| I\'m afraid she\'s | "" / \\ ooo*\n _\\=/_ scheduled for | :. |__[]_[]__| o*o*\n / \\ termination. ___ | |__ _ __| *oo*\n //|/.\\|\\\\ / ()\\ | ## | [] [] | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n5\n /~\\ | _______\n ( oo| | "" / \\ ooo*\n _\\=/_ | :. |__[]_[]__| o*o*\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ / ()\\ | ## | [] [] | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n | | | /=\\ /=\\ /=\\ |\n____/_]_[_\\___________________[_]_[_]_[_]_|________________________\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n -=== ####\n ""o o {"o o}\n _\\ -/_ { =}\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n // |/ \\| \\\\ {} {// } {}\n // [][][] || {} // } {}\n |\' |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n9\n -=== ####\n What are you ""o o {o o"}\n talking _\\ -/_ {= }\n about? # / \\ {~~ //~}\n \\\\//| __ |\\\\ {{~{ //}~}}\n \\/ |/ \\| \\\\ {} {// } {}\n [][][] || {} // } {}\n |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n9\n -=== ####\n What are you ""o o {"o o}\n talking _\\ -/_ { =}\n about? # / \\ {~~ //~}\n \\\\//| __ |\\\\ {{~{ //}~}}\n \\/ |/ \\| \\\\ {} {// } {}\n [][][] || {} // } {}\n |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n2\n -=== ####\n What are you ""o o {"o o}\n talking _\\ -/_ { =}\n about? / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n // |/ \\| \\\\ {} {// } {}\n |\' [][][] || {} // } {}\n |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n5\n -=== ####\n ""o o {"o o}\n _\\ -/_ { =}\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n // |/ \\| \\\\ {} {// } {}\n |\' [][][] || {} // } {}\n |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n5\n ==== |\n o o~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n || |/ \\| || |o=||\n || [][][] || |__||\n |\' |\\ /| \'| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n29\n ==== |\n o o~~ |\n She\'s the one _\\- /_ |\n in the message. / \\ |\n //| __ |\\\\ __ |\n || |/ \\| || |o=||\n || [][][] || |__||\n |\' |\\ /| \'| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n2\n ==== |\n o o~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n || |/ \\| || |o=||\n || [][][] || |__||\n |\' |\\ /| \'| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n2\n ==== |\n o o~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n \\\\|/ \\|// |o=||\n #[][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n16\n ==== |\n o o~~ |\n We\'ve got to _\\- /_ |\n help her! / \\ |\n //| __ |\\\\ __ |\n \\\\|/ \\|// |o=||\n #[][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n17\n ==== |\n o o~~ |\n We\'ve got to _\\- /_ |\n help her! / \\ |\n //| __ |\\\\ __ |\n // |/ \\|// |o=||\n /\' [][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n1\n ==== |\n o o~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n // |/ \\|// |o=||\n /\' [][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n5\n ==== |\n o o~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n \\\\|/ \\|// |o=||\n #[][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n4\n -=== ####\n ""o o {"o o}\n _\\ -/_ { =}\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n // |/ \\| \\\\ {} {// } {}\n // [][][] || {} // } {}\n |\' |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n2\n -=== ####\n ""o o {o o"}\n _\\ -/_ {= }\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n // |/ \\| \\\\ {} {// } {}\n // [][][] || {} // } {}\n |\' |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n8\n -=== ####\n I\'m not ""o o {o o"}\n going anywhere. _\\ -/_ {= }\n # / \\ {~~ //~}\n \\\\//| __ |\\\\ {{~{ //}~}}\n \\/ |/ \\| \\\\ {} {// } {}\n [][][] || {} // } {}\n |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n2\n -=== ####\n I\'m not ""o o {"o o}\n going anywhere. _\\ -/_ { =}\n # / \\ {~~ //~}\n \\\\//| __ |\\\\ {{~{ //}~}}\n \\/ |/ \\| \\\\ {} {// } {}\n [][][] || {} // } {}\n |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n17\n -=== ####\n I\'m not ""o o {"o o}\n going anywhere. _\\ -/_ { =}\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n \\\\|/ \\| \\\\ {} {// } {}\n #[][][] || {} // } {}\n |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n6\n -=== ####\n ""o o {"o o}\n _\\ -/_ { =}\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n \\\\|/ \\| \\\\ {} {// } {}\n #[][][] || {} // } {}\n |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n19\n ==== |\n ~~o o |\n _\\ -/_ |\n / \\ |\n //| __ |\\\\ __ |\n || |/ \\| || |o=||\n || [][][] || |__||\n |\' |\\ /| \'| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n5\n ==== |\n o o~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n || |/ \\| || |o=||\n || [][][] || |__||\n |\' |\\ /| \'| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n11\n ==== |\n o o~~ |\n She\'s rich... _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n || |/ \\| || |o=||\n || [][][] || |__||\n |\' |\\ /| \'| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n11\n ==== |\n o o~~ |\n She\'s rich... _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n \\\\|/ \\|// |o=||\n #[][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n4\n ==== |\n o o~~ |\n _\\- /_ |\n / \\ |\n //| __ |\\\\ __ |\n \\\\|/ \\|// |o=||\n #[][][]# |__||\n |\\ /| |\n |_||_| |\n [ ][ ] |\n | || | |\n |_||_| |\n____________________________________/__][_]________|_______________\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n4\n -=== ####\n ""o o {"o o}\n _\\ -/_ { =}\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n // |/ \\| \\\\ {} {// } {}\n // [][][] || {} // } {}\n |\' |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n2\n -=== ####\n ""o o {o o"}\n _\\ -/_ {= }\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n // |/ \\| \\\\ {} {// } {}\n // [][][] || {} // } {}\n |\' |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n14\n -=== ####\n Rich? ""o o {o o"}\n _\\ -/_ {= }\n # / \\ {~~ //~}\n \\\\//| __ |\\\\ {{~{ //}~}}\n \\/ |/ \\| \\\\ {} {// } {}\n [][][] || {} // } {}\n |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n3\n -=== ####\n Rich? ""o o {o o"}\n _\\ -/_ {= }\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n // |/ \\| \\\\ {} {// } {}\n // [][][] || {} // } {}\n # |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n3\n -=== ####\n Rich? ""o o {"o o}\n _\\ -/_ { =}\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n // |/ \\| \\\\ {} {// } {}\n // [][][] || {} // } {}\n # |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n5\n -=== ####\n ""o o {"o o}\n _\\ -/_ { =}\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n // |/ \\| \\\\ {} {// } {}\n // [][][] || {} // } {}\n # |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n2\n -=== ####\n What\'s ""o o {o o"}\n your plan? _\\ -/_ {= }\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n // |/ \\| \\\\ {} {// } {}\n // [][][] || {} // } {}\n # |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n2\n -=== ####\n What\'s ""o o {o o"}\n your plan? _\\ -/_ {= }\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n \\\\|/ \\| \\\\ {} {// } {}\n #[][][] || {} // } {}\n |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n14\n -=== ####\n What\'s ""o o {"o o}\n your plan? _\\ -/_ { =}\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n \\\\|/ \\| \\\\ {} {// } {}\n #[][][] || {} // } {}\n |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n6\n -=== ####\n ""o o {"o o}\n _\\ -/_ { =}\n / \\ {~~ //~}\n //| __ |\\\\ {{~{ //}~}}\n \\\\|/ \\| \\\\ {} {// } {}\n #[][][] || {} // } {}\n |\\ /| [# {} H{{}}} {}\n |_||_| I] @ H"||"} @\n [ ][ ] I {"||"}\n | || | {"||"}\n |_||_| {"||"}\n__________________/__][_]________________[_][_]____________________\n1\n\n\n\n\n\n\n\n\n\n\n\n\n\n5\n -=== #### ====\n ""o o {"o o} o o~~\n _\\ -/_ { =} _\\- /_\n / \\ {~~ //~} / \\\n //| __ |\\\\ {{~{ //}~}} //| __ |\\\\\n \\\\|/ \\| || {} {// } {} // |/ \\|//\n #[][][] || {} // } {} # [][][]#\n |\\ /| # {} H{{}}} {} [ |\\ /|\n |_||_| @ H"||"} @ [ |_||_|\n [ ][ ] {"||"} [ ][ ]\n | || | {"||"} | || |\n |_||_| {"||"} |_||_|\n____[_][__\\_________________[_][_]__________________/__][_]________\n11\n -=== #### ====\n ""o o {"o o} I\'m going o o~~\n _\\ -/_ { =} to put _\\- /_\n / \\ {~~ //~} these on / \\\n //| __ |\\\\ {{~{ //}~}} you. //| __ |\\\\\n \\\\|/ \\| || {} {// } {} // |/ \\|//\n #[][][] || {} // } {} # [][][]#\n |\\ /| # {} H{{}}} {} [ |\\ /|\n |_||_| @ H"||"} @ [ |_||_|\n [ ][ ] {"||"} [ ][ ]\n | || | {"||"} | || |\n |_||_| {"||"} |_||_|\n____[_][__\\_________________[_][_]__________________/__][_]________\n6\n -=== #### ====\n ""o o {"O O} I\'m going o o~~\n _\\ -/_ { -} to put _\\- /_\n / \\ {~~ //~} these on / \\\n //| __ |\\\\ {{~{ //}~}} you. //| __ |\\\\\n \\\\|/ \\| || {} {// } {} // |/ \\|//\n #[][][] || {} // } {} # [][][]#\n |\\ /| # {} H{{}}} {} [ |\\ /|\n |_||_| @ H"||"} @ [ |_||_|\n [ ][ ] {"||"} [ ][ ]\n | || | {"||"} | || |\n |_||_| {"||"} |_||_|\n____[_][__\\_________________[_][_]__________________/__][_]________\n2\n -=== #### ====\n ""o o {"o o} I\'m going o o~~\n _\\ -/_ { -} to put _\\- /_\n / \\ {~~ //~} these on / \\\n //| __ |\\\\ {{~{ //}~}} you. //| __ |\\\\\n \\\\|/ \\| || {} {// } {} // |/ \\|//\n #[][][] || {} // } {} # [][][]#\n |\\ /| # {} H{{}}} {} [ |\\ /|\n |_||_| @ H"||"} @ [ |_||_|\n [ ][ ] {"||"} [ ][ ]\n | || | {"||"} | || |\n |_||_| {"||"} |_||_|\n____[_][__\\_________________[_][_]__________________/__][_]________\n1\n -=== #### ====\n ""o o {"o o} I\'m going o o~~\n _\\ -/_ { O} to put _\\- /_\n / \\ {~~ //~} these on / \\\n //| __ |\\\\ {{~{ //}~}} you. //| __ |\\\\\n \\\\|/ \\| || {} {// } {} // |/ \\|//\n #[][][] || {} // } {} # [][][]#\n |\\ /| # {} H{{}}} {} [ |\\ /|\n |_||_| @ H"||"} @ [ |_||_|\n [ ][ ] {"||"} [ ][ ]\n | || | {"||"} | || |\n |_||_| {"||"} |_||_|\n____[_][__\\_________________[_][_]__________________/__][_]________\n2\n -=== #### ====\n ""o o {"o o} I\'m going O O~~\n _\\ -/_ { O} to put _\\- /_\n / \\ {~~ //~} these on / \\\n //| __ |\\\\ {{~{ //}~}} you. //| __ |\\\\\n \\\\|/ \\| || {} {// } {} // |/ \\|//\n #[][][] || {} // } {} # [][][]#\n |\\ /| # {} H{{}}} {} [ |\\ /|\n |_||_| @ H"||"} @ [ |_||_|\n [ ][ ] {"||"} [ ][ ]\n | || | {"||"} | || |\n |_||_| {"||"} |_||_|\n____[_][__\\_________________[_][_]__________________/__][_]________\n3\n -=== #### ====\n ""o o {"o o} I\'m going O O~~\n _\\ -/_ { O} to put _\\- /_\n / \\ {~~ //~} these on / \\\n //| __ |\\\\ {{~{ //}~}} you. //| __ |\\\\\n \\\\|/ \\|// {} {// } {} // |/ \\|//\n #[][][]# {} // } {} # [][][]#\n |\\ /| {} H{{}}} {} [ |\\ /|\n |_||_| @ H"||"} @ [ |_||_|\n [ ][ ] {"||"} [ ][ ]\n | || | {"||"} | || |\n |_||_| {"||"} |_||_|\n____[_][__\\_________________[_][_]__________________/__][_]________\n1\n -=== #### ====\n ""o o {"o o} I\'m going O O~~\n _\\ -/_ { =} to put _\\- /_\n / \\ {~~ //~} these on / \\\n //| __ |\\\\ {{~{ //}~}} you. //| __ |\\\\\n \\\\|/ \\|// {} {// } {} // |/ \\| \\\\\n #[][][]# {} // } {} # [][][] ||\n |\\ /| {} H{{}}} {} [ |\\ /| #\n |_||_| @ H"||"} @ [ |_||_|\n [ ][ ] {"||"} [ ][ ]\n | || | {"||"} | || |\n |_||_| {"||"} |_||_|\n____[_][__\\_________________[_][_]__________________/__][_]________\n5\n -=== #### ====\n ""o o {"o o} I\'m going o o~~\n _\\ -/_ { =} to put _\\- /_\n / \\ {~~ //~} these on / \\\n //| __ |\\\\ {{~{ //}~}} you. //| __ |\\\\\n \\\\|/ \\|// {} {// } {} // |/ \\| \\\\\n #[][][]# {} // } {} # [][][] ||\n |\\ /| {} H{{}}} {} [ |\\ /| #\n |_||_| @ H"||"} @ [ |_||_|\n [ ][ ] {"||"} [ ][ ]\n | || | {"||"} | || |\n |_||_| {"||"} |_||_|\n____[_][__\\_________________[_][_]__________________/__][_]________\n6\n -=== #### ====\n ""o o {"o o} o o~~\n _\\ -/_ { =} _\\- /_\n / \\ {~~ //~} / \\\n //| __ |\\\\ {{~{ //}~}} //| __ |\\\\\n \\\\|/ \\|// {} {// } {} // |/ \\| \\\\\n #[][][]# {} // } {} # [][][] ||\n |\\ /| {} H{{}}} {} [ |\\ /| #\n |_||_| @ H"||"} @ [ |_||_|\n [ ][ ] {"||"} [ ][ ]\n | || | {"||"} | || |\n |_||_| {"||"} |_||_|\n____[_][__\\_________________[_][_]__________________/__][_]________\n10\n -=== #### ====\n ""o o Don\'t worry {"o o} o o~~\n _\\ -/_ Chewie... { =} _\\- /_\n / \\ {~~ //~} / \\\n //| __ |\\\\ {{~{ //}~}} //| __ |\\\\\n \\\\|/ \\|// {} {// } {} // |/ \\| \\\\\n #[][][]# {} // } {} # [][][] ||\n |\\ /| {} H{{}}} {} [ |\\ /| #\n |_||_| @ H"||"} @ [ |_||_|\n [ ][ ] {"||"} [ ][ ]\n | || | {"||"} | || |\n |_||_| {"||"} |_||_|\n____[_][__\\_________________[_][_]__________________/__][_]________\n7\n -=== #### ====\n ""o o Don\'t worry {o o"} o o~~\n _\\ -/_ Chewie... {= } _\\- /_\n / \\ {~~ //~} / \\\n //| __ |\\\\ {{~{ //}~}} //| __ |\\\\\n \\\\|/ \\|// {} {// } {} // |/ \\| \\\\\n #[][][]# {} // } {} # [][][] ||\n |\\ /| {} H{{}}} {} [ |\\ /| #\n |_||_| @ H"||"} @ [ |_||_|\n [ ][ ] {"||"} [ ][ ]\n | || | {"||"} | || |\n |_||_| {"||"} |_||_|\n____[_][__\\_________________[_][_]__________________/__][_]________\n16\n -=== #### ====\n ""o o Don\'t worry {o o"} o o~~\n _\\ -/_ Chewie... {= } _\\- /_\n / \\ {~~ //~} / \\\n //| __ |\\\\ {{~{ //}~}} //| __ |\\\\\n \\\\|/ \\|// {} {// } {} // |/ \\| \\\\\n #[][][]# {} // } {} # [][][] ||\n |\\ /| {} H{{}}} {} [ |\\ /| #\n |_||_| @ H"||"} @ [ |_||_|\n [ ][ ] {"||"} [ ][ ]\n | || | {"||"} | || |\n |_||_| {"||"} |_||_|\n____[_][__\\_________________[_][_]__________________/__][_]________\n2\n -=== #### ====\n ""o o {o o"} o o~~\n _\\ -/_ {= } _\\- /_\n / \\ {~~ //~} / \\\n //| __ |\\\\ {{~{ //}~}} //| __ |\\\\\n \\\\|/ \\|// {} {// } {} // |/ \\| \\\\\n #[][][]# {} // } {} # [][][] ||\n |\\ /| {} H{{}}} {} [ |\\ /| #\n |_||_| @ H"||"} @ [ |_||_|\n [ ][ ] {"||"} [ ][ ]\n | || | {"||"} | || |\n |_||_| {"||"} |_||_|\n____[_][__\\_________________[_][_]__________________/__][_]________\n19\n -=== #### ====\n ""o o I think I {o o"} o o~~\n _\\ -/_ know what {= } _\\- /_\n / \\ he has in {~~ //~} / \\\n //| __ |\\\\ mind. {{~{ //}~}} //| __ |\\\\\n \\\\|/ \\|// {} {// } {} // |/ \\| \\\\\n #[][][]# {} // } {} # [][][] ||\n |\\ /| {} H{{}}} {} [ |\\ /| #\n |_||_| @ H"||"} @ [ |_||_|\n [ ][ ] {"||"} [ ][ ]\n | || | {"||"} | || |\n |_||_| {"||"} |_||_|\n____[_][__\\_________________[_][_]__________________/__][_]________\n9\n -=== #### ====\n ""o o I think I {o o"} o o~~\n _\\ -/_ know what {= } _\\- /_\n / \\ he has in {~~ //~} / \\\n //| __ |\\\\ mind. {{~{ //}~}} //| __ |\\\\\n \\\\|/ \\| \\\\ {} {// } {} // |/ \\| \\\\\n #[][][] # {} // } {} # [][][] ||\n |\\ /| {} H{{}}} {} [ |\\ /| #\n |_||_| @ H"||"} @ [ |_||_|\n [ ][ ] {"||"} [ ][ ]\n | || | {"||"} | || |\n |_||_| {"||"} |_||_|\n____[_][__\\_________________[_][_]__________________/__][_]________\n6\n -=== #### ====\n ""o o I think I {o o"} o o~~\n _\\ -/_ know what {= } _\\- /_\n / \\ he has in {~~ //~} / \\\n //| __ |\\\\ mind. {{~{ //}~}} //| __ |\\\\\n \\\\|/ \\| \\\\ {} {// } {} // |/ \\|//\n #[][][] # {} // } {} # [][][]#\n |\\ /| {} H{{}}} {} [ |\\ /|\n |_||_| @ H"||"} @ [ |_||_|\n [ ][ ] {"||"} [ ][ ]\n | || | {"||"} | || |\n |_||_| {"||"} |_||_|\n____[_][__\\_________________[_][_]__________________/__][_]________\n6\n -=== #### ====\n ""o o {o o"} o o~~\n _\\ -/_ {= } _\\- /_\n / \\ {~~ //~} / \\\n //| __ |\\\\ {{~{ //}~}} //| __ |\\\\\n \\\\|/ \\| \\\\ {} {// } {} // |/ \\|//\n #[][][] # {} // } {} # [][][]#\n |\\ /| {} H{{}}} {} [ |\\ /|\n |_||_| @ H"||"} @ [ |_||_|\n [ ][ ] {"||"} [ ][ ]\n | || | {"||"} | || |\n |_||_| {"||"} |_||_|\n____[_][__\\_________________[_][_]__________________/__][_]________\n5\n\n\n\n\n\n\n\n\n\n\n\n\n\n6\n /~\\ | _______\n ( oo| | "" / \\ ooo*\n _\\=/_ | :. |__[]_[]__| o*o*\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ / ()\\ | ## | [] [] | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n |_| | /=\\ /=\\ /=\\ |\n____/_ _[_\\___________________[_]_[_]_[_]_|________________________\n19\n /~\\ | _______\n ( oo| What should R2 and | "" / \\ ooo*\n _\\=/_ I do if we\'re | :. |__[]_[]__| o*o*\n / \\ discovered ___ | |__ _ __| *oo*\n //|/.\\|\\\\ here? / ()\\ | ## | [] [] | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n |_| | /=\\ /=\\ /=\\ |\n____/_ _[_\\___________________[_]_[_]_[_]_|________________________\n9\n /~\\ | _______\n ( oo| What should R2 and | "" / \\ ooo*\n _\\=/_ I do if we\'re | :. |__[]_[]__| o*o*\n / \\ discovered ___ | |__ _ __| *oo*\n //|/.\\|\\\\ here? / ()\\ | ## | [] [] | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n |_| | /=\\ /=\\ /=\\ |\n____/_ _[_\\___________________[_]_[_]_[_]_|________________________\n6\n /~\\ | _______\n ( oo| | "" / \\ ooo*\n _\\=/_ | :. |__[]_[]__| o*o*\n / \\ ___ | |__ _ __| *oo*\n //|/.\\|\\\\ / ()\\ | ## | [] [] | o*oo\n || \\_/ || _|_____|_ | ## \\_______/\n || |\\ /| || | | === | | |______________________\n # \\_ _/ # |_| O |_| /\n | | | || O || |------------------------\n | | | ||__*__|| | (*)\n []|[] |~ \\___/ ~| |\n |_| | /=\\ /=\\ /=\\ |\n____/_ _[_\\___________________[_]_[_]_[_]_|________________________\n1\n\n\n\n\n\n\n\n\n\n\n\n\n\n5\n ===- ==== |\n o o"" o o~~ |\n _\\- /_ _\\- /_ |\n / \\ / \\ |\n //| __ |\\\\ //| __ |\\\\ __ |\n // |/ \\ // \\\\|/ \\|// |o=||\n # [][][]# #[][][]# |__||\n |\\ /| |\\ /| |\n |_||_| |_||_| |\n [ ][ ] [ ][ ] |\n | || | | || | |\n |_||_| |_||_| |\n_______________/__][_]____________________/__][_]________|_________\n20\n ===- ==== |\n o o"" Lock the o o~~ |\n _\\- /_ door. _\\- /_ |\n / \\ / \\ |\n //| __ |\\\\ //| __ |\\\\ __ |\n // |/ \\ // \\\\|/ \\|// |o=||\n # [][][]# #[][][]# |__||\n |\\ /| |\\ /| |\n |_||_| |_||_| |\n [ ][ ] [ ][ ] |\n | || | | || | |\n |_||_| |_||_| |\n_______________/__][_]____________________/__][_]________|_________\n7\n ===- ==== |\n o o"" Lock the o o~~ |\n _\\- /_ door. _\\- /_ |\n / \\ / \\ |\n //| __ |\\\\ //| __ |\\\\ __ |\n // |/ \\ // // |/ \\|// |o=||\n # [][][]# # [][][]# |__||\n |\\ /| |\\ /| |\n |_||_| |_||_| |\n [ ][ ] [ ][ ] |\n | || | | || | |\n |_||_| |_||_| |\n_______________/__][_]____________________/__][_]________|_________\n2\n ===- ==== |\n o o"" o o~~ |\n _\\- /_ _\\- /_ |\n / \\ / \\ |\n //| __ |\\\\ //| __ |\\\\ __ |\n // |/ \\ // // |/ \\|// |o=||\n # [][][]# # [][][]# |__||\n |\\ /| |\\ /| |\n |_||_| |_||_| |\n [ ][ ] [ ][ ] |\n | || | | || | |\n |_||_| |_||_| |\n_______________/__][_]____________________/__][_]________|_________\n2\n ===- ==== |\n o o"" o o~~ |\n _\\- /_ _\\- /_ |\n / \\ / \\ |\n //| __ |\\\\ //| __ |\\\\ __ |\n // |/ \\ // \\\\|/ \\|// |o=||\n # [][][]# #[][][]# |__||\n |\\ /| |\\ /| |\n |_||_| |_||_| |\n [ ][ ] [ ][ ] |\n | || | | || | |\n |_||_| |_||_| |\n_______________/__][_]____________________/__][_]________|_________\n16\n ===- ==== |\n And hope o o"" o o~~ |\n they don\'t _\\- /_ _\\- /_ |\n have / \\ / \\ |\n blasters. //| __ |\\\\ //| __ |\\\\ __ |\n // |/ \\ // \\\\|/ \\|// |o=||\n # [][][]# #[][][]# |__||\n |\\ /| |\\ /| |\n |_||_| |_||_| |\n [ ][ ] [ ][ ] |\n | || | | || | |\n |_||_| |_||_| |\n_______________/__][_]____________________/__][_]________|_________\n3\n ===- ==== |\n And hope o o"" o o~~ |\n they don\'t _\\- /_ _\\- /_ |\n have / \\ / \\ |\n blasters. //| __ |\\\\ //| __ |\\\\ __ |\n \\\\|/ \\ // \\\\|/ \\|// |o=||\n #[][][]# #[][][]# |__||\n |\\ /| |\\ /| |\n |_||_| |_||_| |\n [ ][ ] [ ][ ] |\n | || | | || | |\n |_||_| |_||_| |\n_______________/__][_]____________________/__][_]________|_________\n10\n ===- ==== |\n And hope o o"" ~~o o |\n they don\'t _\\- /_ _\\ -/_ |\n have / \\ / \\ |\n blasters. //| __ |\\\\ //| __ |\\\\ __ |\n \\\\|/ \\ // \\\\|/ \\|// |o=||\n #[][][]# #[][][]# |__||\n |\\ /| |\\ /| |\n |_||_| |_||_| |\n [ ][ ] [ ][ ] |\n | || | | || | |\n |_||_| |_||_| |\n_______________/__][_]_____________________[_][_]________|_________\n5\n ===- ==== |\n o o"" ~~o o |\n _\\- /_ _\\ -/_ |\n / \\ / \\ |\n //| __ |\\\\ //| __ |\\\\ __ |\n \\\\|/ \\ // \\\\|/ \\|// |o=||\n #[][][]# #[][][]# |__||\n |\\ /| |\\ /| |\n |_||_| |_||_| |\n [ ][ ] [ ][ ] |\n | || | | || | |\n |_||_| |_||_| |\n_______________/__][_]_____________________[_][_]________|_________\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n5\n /~\\\n ( oo|\n _\\=/_\n / \\ ___\n //|/.\\|\\\\ / ()\\\n || \\_/ || _|_____|_\n || |\\ /| || | | === | |\n # \\_ _/ # |_| O |_|\n | | | || O ||\n | | | ||__*__||\n []|[] |~ \\___/ ~|\n | | | /=\\ /=\\ /=\\\n_________________________/_]_[_\\___[_]_[_]_[_]_____________________\n15\n /~\\\n That isn\'t very ( oo|\n reassuring. _\\=/_\n / \\ ___\n //|/.\\|\\\\ / ()\\\n || \\_/ || _|_____|_\n || |\\ /| || | | === | |\n # \\_ _/ # |_| O |_|\n | | | || O ||\n | | | ||__*__||\n []|[] |~ \\___/ ~|\n | | | /=\\ /=\\ /=\\\n_________________________/_]_[_\\___[_]_[_]_[_]_____________________\n3\n /~\\\n That isn\'t very ( oo|\n reassuring. _\\=/_\n / \\ # ___\n //|/.\\|\\\\// / ()\\\n || \\_/ \\/ _|_____|_\n || |\\ /| | | === | |\n # \\_ _/ |_| O |_|\n | | | || O ||\n | | | ||__*__||\n []|[] |~ \\___/ ~|\n | | | /=\\ /=\\ /=\\\n_________________________/_]_[_\\___[_]_[_]_[_]_____________________\n8\n /~\\\n That isn\'t very ( oo|\n reassuring. _\\=/_\n / \\ # ___\n //|/.\\|\\\\// /() \\\n || \\_/ \\/ _|_____|_\n || |\\ /| | | === | |\n # \\_ _/ |_| O |_|\n | | | || O ||\n | | | ||__*__||\n []|[] |~ \\___/ ~|\n | | | /=\\ /=\\ /=\\\n_________________________/_]_[_\\___[_]_[_]_[_]_____________________\n11\n /~\\\n That isn\'t very ( oo|\n reassuring. _\\=/_\n / \\ # ___\n //|/.\\|\\\\// / ()\\\n || \\_/ \\/ _|_____|_\n || |\\ /| | | === | |\n # \\_ _/ |_| O |_|\n | | | || O ||\n | | | ||__*__||\n []|[] |~ \\___/ ~|\n | | | /=\\ /=\\ /=\\\n_________________________/_]_[_\\___[_]_[_]_[_]_____________________\n7\n /~\\\n ( oo|\n _\\=/_\n / \\ # ___\n //|/.\\|\\\\// / ()\\\n || \\_/ \\/ _|_____|_\n || |\\ /| | | === | |\n # \\_ _/ |_| O |_|\n | | | || O ||\n | | | ||__*__||\n []|[] |~ \\___/ ~|\n | | | /=\\ /=\\ /=\\\n_________________________/_]_[_\\___[_]_[_]_[_]_____________________\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n4\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | || | {"||"} \' | | || |\n |_||_| {"||"} [_| |_||_|\n_________[_][_]_____________[_][_]_______________[_][_]____________\n2\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | || | {"||"} \' | | || |\n) |_||_| {"||"} [_| |_||_|\n_________[_][_]_____________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n- | || | {"||"} \' | | || |\n_) |_||_| {"||"} [_| |_||_|\nO________[_][_]_____________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n-- | || | {"||"} \' | | || |\n__) |_||_| {"||"} [_| |_||_|\n_O_______[_][_]_____________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n |><> | {o o"} . |><> |\n (/\\__) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n--- | || | {"||"} \' | | || |\n___) |_||_| {"||"} [_| |_||_|\n__O______[_][_]_____________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n |><> | {o o"} . |><> |\n (/\\__) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n---- | || | {"||"} \' | | || |\n____) |_||_| {"||"} [_| |_||_|\nO__O_____[_][_]_____________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n |><> | {o o"} . |><> |\n (/\\__) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n ---- | || | {"||"} \' | | || |\n[____) |_||_| {"||"} [_| |_||_|\n_O__O____[_][_]_____________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n |><> | {o o"} . |><> |\n (/\\__) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n ---- | || | {"||"} \' | | || |\n [____) |_||_| {"||"} [_| |_||_|\n__O__O___[_][_]_____________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n |><> | {o o"} . |><> |\n (/\\__) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n ---- | || | {"||"} \' | | || |\n [____) |_||_| {"||"} [_| |_||_|\n___O__O__[_][_]_____________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n |><> | {o o"} . |><> |\n (/\\__) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n ---- | || | {"||"} \' | | || |\n [____)|_||_| {"||"} [_| |_||_|\n____O__O_[_][_]_____________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n |><> | {o o"} . |><> |\n (/\\__) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n ----| || | {"||"} \' | | || |\n [____)_||_| {"||"} [_| |_||_|\n_____O__O__][_]_____________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n |><> | {o o"} . |><> |\n (/\\__) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n ---- || | {"||"} \' | | || |\n [____)||_| {"||"} [_| |_||_|\n______O__O_][_]_____________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n |><> | {o o"} . |><> |\n (/\\__) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n ----|| | {"||"} \' | | || |\n [____)|_| {"||"} [_| |_||_|\n_______O__O][_]_____________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n |><> | {o o"} . |><> |\n (/\\__) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n ----| | {"||"} \' | | || |\n [____)_| {"||"} [_| |_||_|\n________O__O[_]_____________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n |><> | {o o"} . |><> |\n (/\\__) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n ---- | {"||"} \' | | || |\n [____)| {"||"} [_| |_||_|\n_________O__O_]_____________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n |><> | {o o"} . |><> |\n (/\\__) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n |----| {"||"} \' | | || |\n [____) {"||"} [_| |_||_|\n_________[O__O]_____________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | ---- {"||"} \' | | || |\n |[____) {"||"} [_| |_||_|\n_________[_O__O_____________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | |---- {"||"} \' | | || |\n | [____) {"||"} [_| |_||_|\n_________[_]O__O____________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | ||---- {"||"} \' | | || |\n | |[____) {"||"} [_| |_||_|\n_________[_]_O__O___________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | || ---- {"||"} \' | | || |\n | ||[____) {"||"} [_| |_||_|\n_________[_][_O__O__________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | || |---- {"||"} \' | | || |\n | || [____) {"||"} [_| |_||_|\n_________[_][_]O__O_________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | || | ---- {"||"} \' | | || |\n | || |[____) {"||"} [_| |_||_|\n_________[_][_]_O__O________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | || | ---- {"||"} \' | | || |\n | || | [____) {"||"} [_| |_||_|\n_________[_][_]__O__O_______[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | || | ---- {"||"} \' | | || |\n | || | [____) {"||"} [_| |_||_|\n_________[_][_]___O__O______[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | || | ---- {"||"} \' | | || |\n | || | [____) {"||"} [_| |_||_|\n_________[_][_]____O__O_____[_][_]_______________[_][_]____________\n2\n /__\\ #### /__\\\n | <><| {O O"} . |><> |\n (__/\\) {= } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | || | ---- {"||"} \' | | || |\n | || | [____) {"||"} [_| |_||_|\n_________[_][_]____O__O_____[_][_]_______________[_][_]____________\n14\n /__\\ #### /__\\\n | <><| Grrrrrr! {O O"} . |><> |\n (__/\\) {0 } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | || | ---- {"||"} \' | | || |\n | || | [____) {"||"} [_| |_||_|\n_________[_][_]____O__O_____[_][_]_______________[_][_]____________\n4\n /__\\ #### /__\\\n | <><| Grrrrrr! {o o"} . |><> |\n (__/\\) {0 } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | || | ---- {"||"} \' | | || |\n | || | [____) {"||"} [_| |_||_|\n_________[_][_]____O__O_____[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {- } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | || | ---- {"||"} \' | | || |\n | || | [____) {"||"} [_| |_||_|\n_________[_][_]______O__O___[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {- } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | || | ---- {"||"} \' | | || |\n | || | [____) {"||"} [_| |_||_|\n_________[_][_]_______O__O__[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {- } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | || | ---- {"||"} \' | | || |\n | || | (____] {"||"} [_| |_||_|\n_________[_][_]_______O__O__[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {- } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | || | ---- {"||"} \' | | || |\n | || | (____] {"||"} [_| |_||_|\n_________[_][_]_____O__O____[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n | <><| {"o o} . |><> |\n (__/\\) { -} | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | || | ---- {"||"} \' | | || |\n | || | (____] {"||"} [_| |_||_|\n_________[_][_]___O__O______[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n | <><| {"o o} . |><> |\n (__/\\) --{ -}-- | (/\\__)\n / \\ { // } I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | || | ---- {"||"} \' | | || |\n | || |(____] {"||"} [_| |_||_|\n_________[_][_]_O__O________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n | <><| {"o o} . |><> |\n (__/\\) --{ -}-- | (/\\__)\n / \\ { // } I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | || ---- {"||"} \' | | || |\n | ||(____] {"||"} [_| |_||_|\n_________[_][_O__O__________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n | <><| {"o o} . |><> |\n (__/\\) --{ -}-- | (/\\__)\n / \\ { // } I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n | |---- {"||"} \' | | || |\n | (____] {"||"} [_| |_||_|\n_________[_]O__O____________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n | <><| {"o o} . |><> |\n (__/\\) { -} | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n |----| {"||"} \' | | || |\n (____] {"||"} [_| |_||_|\n_________[O__O]_____________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n |><> | {o o"} . |><> |\n (/\\__) {- } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n ----| | {"||"} \' | | || |\n (____]_| {"||"} [_| |_||_|\n________O__O[_]_____________[_][_]_______________[_][_]____________\n1\n /__\\ #### /__\\\n |><> | {o o"} . |><> |\n (/\\__) {- } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n ----_|| | {"||"} \' | | || |\n (____]||_| {"||"} [_| |_||_|\n______O__O_][_]_____________[_][_]______________/__][_]____________\n1\n /__\\ #### /__\\\n |><> | {o o"} . |><> |\n (/\\__) {- } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n ---- |_|| | {"||"} \' | | || |\n (____]|_||_| {"||"} [_| |_||_|\n____O__O_[_][_]_____________[_][_]______________/__][_]____________\n1\n /__\\ #### /__\\\n |><> | {o o"} . |><> |\n (/\\__) {- } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n ---- |_|| | {"||"} \' | | || |\n (____] |_||_| {"||"} [_| |_||_|\n__O__O___[_][_]_____________[_][_]______________/__][_]____________\n1\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {- } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n---- |_|| | {"||"} \' | | || |\n____] |_||_| {"||"} [_| |_||_|\nO__O_____[_][_]_____________[_][_]______________/__][_]____________\n1\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {- } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n-- |_|| | {"||"} \' | | || |\n__] |_||_| {"||"} [_| |_||_|\n_O_______[_][_]_____________[_][_]______________/__][_]____________\n1\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {- } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n |_|| | {"||"} \' | | || |\n] |_||_| {"||"} [_| |_||_|\n_________[_][_]_____________[_][_]______________/__][_]____________\n4\n /__\\ #### /__\\\n | <><| {o o"} . |><> |\n (__/\\) {- } | (/\\__)\n / \\ {~~ //~} I / \\\n ||/(===o {}{ //}{} I || __ |\\\\\n | / \\ | {}{// {} (I// / \\| ||\n \\/][][\\/ {}/ {} ,]/ [][][] ||\n |\\ /| {}@@{} [] |\\ /| \'\n |_||_| H"||"} [] |_||_|\n [ ][ ] {"||"} /| [ ][ ]\n |_|| | {"||"} \' | | || |\n |_||_| {"||"} [_| |_||_|\n_________[_][_]_____________[_][_]______________/__][_]____________\n5\n\n\n\n\n\n\n\n\n\n\n\n\n\n9\n | /__\\ #### /__\\ |\n | | <><| {o o"} |><> | |\n | (__/\\) {= } . (/\\__) |\n | / \\ {~~ //~} | / \\ |\n | ||/(===o {}{ //}{} I || __ |\\\\ |\n | | / \\ | {}{// {} I// / \\| |||\n | \\/][][\\/ {}/ {} (I/ [][][] |||\n | |\\ /| {}@@{} ,] |\\ /| \' |\n | |_||_| H"||"} [] |_||_| |\n | [ ][ ] {"||"} [] [ ][ ] |\n | | || | {"||"} /| | || | |\n | |_||_| {"||"} \' | |_||_| |\n________________|__[_][_]_____[_][_]__[_|__[_][_]___|______________\n11\n | /__\\ #### /__\\ |\n I can\'t see a | | <><| {o o"} |><> | |\n thing in this | (__/\\) {= } . (/\\__) |\n helmet. | / \\ {~~ //~} | / \\ |\n | ||/(===o {}{ //}{} I || __ |\\\\ |\n | | / \\ | {}{// {} I// / \\| |||\n | \\/][][\\/ {}/ {} (I/ [][][] |||\n | |\\ /| {}@@{} ,] |\\ /| \' |\n | |_||_| H"||"} [] |_||_| |\n | [ ][ ] {"||"} [] [ ][ ] |\n | | || | {"||"} /| | || | |\n | |_||_| {"||"} \' | |_||_| |\n________________|__[_][_]_____[_][_]__[_|__[_][_]___|______________\n6\n | /__\\ #### /__\\ |\n I can\'t see a | | <><| {"o o} |><> | |\n thing in this | (__/\\) { =} . (/\\__) |\n helmet. | / \\ {~~ //~} | / \\ |\n | ||/(===o {}{ //}{} I || __ |\\\\ |\n | | / \\ | {}{// {} I// / \\| |||\n | \\/][][\\/ {}/ {} (I/ [][][] |||\n | |\\ /| {}@@{} ,] |\\ /| \' |\n | |_||_| H"||"} [] |_||_| |\n | [ ][ ] {"||"} [] [ ][ ] |\n | | || | {"||"} /| | || | |\n | |_||_| {"||"} \' | |_||_| |\n________________|__[_][_]_____[_][_]__[_|__[_][_]___|______________\n3\n | /__\\ #### /__\\ |\n I can\'t see a | | <><| {"o o} | <><| |\n thing in this | (__/\\) { =} . (__/\\) |\n helmet. | / \\ {~~ //~} | / \\ |\n | ||/(===o {}{ //}{} I || __ |\\\\ |\n | | / \\ | {}{// {} I// / \\| |||\n | \\/][][\\/ {}/ {} (I/ [][][] |||\n | |\\ /| {}@@{} ,] |\\ /| \' |\n | |_||_| H"||"} [] |_||_| |\n | [ ][ ] {"||"} [] [ ][ ] |\n | | || | {"||"} /| | || | |\n | |_||_| {"||"} \' | |_||_| |\n________________|__[_][_]_____[_][_]__[_|__[_][_]___|______________\n14\n | /__\\ #### /__\\ |\n I can\'t see a | | <><| {"o o} | <><| |\n thing in this | (__/\\) { =} . (__/\\) |\n helmet. | / \\ {~~ //~} | / \\ |\n | ||/(===o {}{ //}{} I || __ |\\\\ |\n | | / \\ | {}{// {} I// / \\| |||\n | \\/][][\\/ {}/ {} (I/ [][][] |||\n | |\\ /| {}@@{} ,] |\\ /| \' |\n | |_||_| H"||"} [] |_||_| |\n | [ ][ ] {"||"} [] [ ][ ] |\n | | || | {"||"} /| | || | |\n | |_||_| {"||"} \' | |_||_| |\n________________|__[_][_]_____[_][_]__[_|__[_][__\\__|______________\n9\n | /__\\ #### /__\\ |\n I can\'t see a | | <><| {"o o} |><> | |\n thing in this | (__/\\) { =} . (/\\__) |\n helmet. | / \\ {~~ //~} | / \\ |\n | ||/(===o {}{ //}{} I || __ |\\\\ |\n | | / \\ | {}{// {} I// / \\| |||\n | \\/][][\\/ {}/ {} (I/ [][][] |||\n | |\\ /| {}@@{} ,] |\\ /| \' |\n | |_||_| H"||"} [] |_||_| |\n | [ ][ ] {"||"} [] [ ][ ] |\n | | || | {"||"} /| | || | |\n | |_||_| {"||"} \' | |_||_| |\n________________|__[_][_]_____[_][_]__[_|__[_][_]___|______________\n6\n | /__\\ #### /__\\ |\n I can\'t see a | | <><| {"o o} |><> | |\n thing in this | (__/\\) { =} . (/\\__) |\n helmet. | / \\ {~~ //~} | / \\ |\n | ||/(===o {}{ //}{} I || __ |\\\\ |\n | | / \\ | {}{// {} I// / \\| |||\n | \\/][][\\/ {}/ {} (I/ [][][] |||\n | |\\ /| {}@@{} ,] |\\ /| \' |\n | |_||_| H"||"} [] |_||_| |\n | [ ][ ] {"||"} [] [ ][ ] |\n | | || | {"||"} /| | || | |\n | |_||_| {"||"} \' | |_||_| |\n________________|__[_][_]_____[_][_]__[_|_/__][_]___|______________\n7\n | /__\\ #### /__\\ |\n I can\'t see a | | <><| {o o"} |><> | |\n thing in this | (__/\\) {= } . (/\\__) |\n helmet. | / \\ {~~ //~} | / \\ |\n | ||/(===o {}{ //}{} I || __ |\\\\ |\n | | / \\ | {}{// {} I// / \\| |||\n | \\/][][\\/ {}/ {} (I/ [][][] |||\n | |\\ /| {}@@{} ,] |\\ /| \' |\n | |_||_| H"||"} [] |_||_| |\n | [ ][ ] {"||"} [] [ ][ ] |\n | | || | {"||"} /| | || | |\n | |_||_| {"||"} \' | |_||_| |\n________________|__[_][_]_____[_][_]__[_|_/__][_]___|______________\n6\n | /__\\ #### /__\\ |\n | | <><| {o o"} |><> | |\n | (__/\\) {= } . (/\\__) |\n | / \\ {~~ //~} | / \\ |\n | ||/(===o {}{ //}{} I || __ |\\\\ |\n | | / \\ | {}{// {} I// / \\| |||\n | \\/][][\\/ {}/ {} (I/ [][][] |||\n | |\\ /| {}@@{} ,] |\\ /| \' |\n | |_||_| H"||"} [] |_||_| |\n | [ ][ ] {"||"} [] [ ][ ] |\n | | || | {"||"} /| | || | |\n | |_||_| {"||"} \' | |_||_| |\n________________|__[_][_]_____[_][_]__[_|_/__][_]___|______________\n1\n | /__\\ #### /__\\ ||\n | | <><| {o o"} |><> | ||\n | (__/\\) {= } . (/\\__) ||\n | / \\ {~~ //~} | / \\ ||\n | ||/(===o {}{ //}{} I || __ |\\\\||\n | | / \\ | {}{// {} I// / \\| |||\n | \\/][][\\/ {}/ {} (I/ [][][] |||\n | |\\ /| {}@@{} ,] |\\ /| \'||\n | |_||_| H"||"} [] |_||_| ||\n | [ ][ ] {"||"} [] [ ][ ] ||\n | | || | {"||"} /| | || | ||\n | |_||_| {"||"} \' | |_||_| ||\n________________|__[_][_]_____[_][_]__[_|_/__][_]__||______________\n1\n | /__\\ #### /__\\ | |\n | | <><| {o o"} |><> | | |\n | (__/\\) {= } . (/\\__) | |\n | / \\ {~~ //~} | / \\| |\n | ||/(===o {}{ //}{} I || __ |\\| |\n | | / \\ | {}{// {} I// / \\| | |\n | \\/][][\\/ {}/ {} (I/ [][][] | |\n | |\\ /| {}@@{} ,] |\\ /| | |\n | |_||_| H"||"} [] |_||_| | |\n | [ ][ ] {"||"} [] [ ][ ] | |\n | | || | {"||"} /| | || | | |\n | |_||_| {"||"} \' | |_||_| | |\n________________|__[_][_]_____[_][_]__[_|_/__][_]_|_|______________\n1\n | /__\\ #### /__\\ | |\n | | <><| {o o"} |><> || |\n | (__/\\) {= } . (/\\__)| |\n | / \\ {~~ //~} | / | |\n | ||/(===o {}{ //}{} I || __ || |\n | | / \\ | {}{// {} I// / \\|| |\n | \\/][][\\/ {}/ {} (I/ [][][]| |\n | |\\ /| {}@@{} ,] |\\ /|| |\n | |_||_| H"||"} [] |_||_|| |\n | [ ][ ] {"||"} [] [ ][ ]| |\n | | || | {"||"} /| | || || |\n | |_||_| {"||"} \' | |_||_|| |\n________________|__[_][_]_____[_][_]__[_|_/__][_]|__|______________\n1\n | /__\\ #### /__\\| |\n | | <><| {o o"} |><> | |\n | (__/\\) {= } . (/\\__| |\n | / \\ {~~ //~} | / | |\n | ||/(===o {}{ //}{} I || __ | |\n | | / \\ | {}{// {} I// / \\| |\n | \\/][][\\/ {}/ {} (I/ [][][| |\n | |\\ /| {}@@{} ,] |\\ /| |\n | |_||_| H"||"} [] |_||_| |\n | [ ][ ] {"||"} [] [ ][ | |\n | | || | {"||"} /| | || | |\n | |_||_| {"||"} \' | |_||_| |\n________________|__[_][_]_____[_][_]__[_|_/__][_|___|______________\n1\n | /__\\ #### /__| |\n | | <><| {o o"} |><>| ||\n | (__/\\) {= } . (/\\_| ||\n | / \\ {~~ //~} | / | ||\n | ||/(===o {}{ //}{} I || __| ||\n | | / \\ | {}{// {} I// / | ||\n | \\/][][\\/ {}/ {} (I/ [][]| |\n | |\\ /| {}@@{} ,] |\\ | ||\n | |_||_| H"||"} [] |_||| ||\n | [ ][ ] {"||"} [] [ ][| ||\n | | || | {"||"} /| | ||| ||\n | |_||_| {"||"} \' | |_||| ||\n________________|__[_][_]_____[_][_]__[_|_/__][|____|______________\n1\n | /__\\ #### /_| _|\n | | <><| {o o"} |><| | |\n | (__/\\) {= } . (/\\| | |\n | / \\ {~~ //~} | / | | |\n | ||/(===o {}{ //}{} I || _| | |\n | | / \\ | {}{// {} I// / | |_|\n | \\/][][\\/ {}/ {} (I/ [][| _|\n | |\\ /| {}@@{} ,] |\\ | | |\n | |_||_| H"||"} [] |_|| | |\n | [ ][ ] {"||"} [] [ ]| | |\n | | || | {"||"} /| | || | |\n | |_||_| {"||"} \' | |_|| |_|\n________________|__[_][_]_____[_][_]__[_|_/__]|_____|______________\n1\n | /__\\ #### /| _ |\n | |><> | {o o"} |>| | ||\n | (/\\__) {= } . (/| | ||\n | / \\ {~~ //~} | / | | ||\n | ||/(===o {}{ //}{} I || | | ||\n | | / \\ | {}{// {} I// /| |_||\n | \\/][][\\/ {}/ {} (I/ []| _ |\n | |\\ /| {}@@{} ,] |\\| | ||\n | |_||_| H"||"} [] |_| | ||\n | [ ][ ] {"||"} [] [ | | ||\n | | || | {"||"} /| | | | ||\n | |_||_| {"||"} \' | |_| |_||\n________________|__[_][_]_____[_][_]__[_|_/__|______|______________\n1\n | /__\\ #### | _ |\n | |><> | {o o"} || | | |\n | (/\\__) {= } . (| | | |\n | / \\ {~~ //~} | / | | | |\n | ||/(===o {}{ //}{} I ||| | | |\n | | / \\ | {}{// {} I// | |_| |\n | \\/][][\\/ {}/ {} (I/ [| _ |\n | |\\ /| {}@@{} ,] || | | |\n | |_||_| H"||"} [] || | | |\n | [ ][ ] {"||"} [] [| | | |\n | | || | {"||"} /| || | | |\n | |_||_| {"||"} \' | || |_| |\n________________|__[_][_]_____[_][_]__[_|_/_|_______|______________\n1\n | /__\\ #### | _ |\n | |><> | {o o"} | | | |\n | (/\\__) {= } . | | | |\n | / \\ {~~ //~} | /| | | |\n | ||/(===o {}{ //}{} I || | | |\n | | / \\ | {}{// {} I//| |_| |\n | \\/][][\\/ {}/ {} (I/ | _ |\n | |\\ /| {}@@{} ,] | | | |\n | |_||_| H"||"} [] | | | |\n | [ ][ ] {"||"} [] | | | |\n | | || | {"||"} /| | | | |\n | |_||_| {"||"} \' | | |_| |\n________________|__[_][_]_____[_][_]__[_|_/|________|______________\n1\n | /__\\ #### | _ |\n | |><> | {o o"} | | | |\n | (/\\__) {= } . | | | |\n | / \\ {~~ //~} | | | | |\n | ||/(===o {}{ //}{} I | | | |\n | | / \\ | {}{// {} I/| |_| |\n | \\/][][\\/ {}/ {} (I/| _ |\n | |\\ /| {}@@{} ,] | | | |\n | |_||_| H"||"} [] | | | |\n | [ ][ ] {"||"} [] | | | |\n | | || | {"||"} /| | | | |\n | |_||_| {"||"} \' | | |_| |\n________________|__[_][_]_____[_][_]__[_|_|_________|______________\n1\n | /__\\ #### | _ |\n | |><> | {o o"} | | | |\n | (/\\__) {= } .| | | |\n | / \\ {~~ //~} || | | |\n | ||/(===o {}{ //}{} I| | | |\n | | / \\ | {}{// {} I| |_| |\n | \\/][][\\/ {}/ {} (I| _ |\n | |\\ /| {}@@{} ,]| | | |\n | |_||_| H"||"} []| | | |\n | [ ][ ] {"||"} []| | | |\n | | || | {"||"} /|| | | |\n | |_||_| {"||"} \' || |_| |\n________________|__[_][_]_____[_][_]__[_||__________|______________\n1\n | /__\\ #### | _ |\n | |><> | {o o"} | | | |\n | (/\\__) {= } | | | |\n | / \\ {~~ //~} | | | |\n | ||/(===o {}{ //}{} | | | |\n | | / \\ | {}{// {} | |_| |\n | \\/][][\\/ {}/ {} (| _ |\n | |\\ /| {}@@{} ,| | | |\n | |_||_| H"||"} [| | | |\n | [ ][ ] {"||"} [| | | |\n | | || | {"||"} /| | | |\n | |_||_| {"||"} \' | |_| |\n________________|__[_][_]_____[_][_]__[_|___________|______________\n1\n | /__\\ #### | _ |\n | |><> | {o o"} | | | |\n | (/\\__) {= } | | | |\n | / \\ {~~ //~} | | | |\n | ||/(===o {}{ //}{} | | | |\n | | / \\ | {}{// {} | |_| |\n | \\/][][\\/ {}/ {} | _ |\n | |\\ /| {}@@{} | | | |\n | |_||_| H"||"} | | | |\n | [ ][ ] {"||"} | | | |\n | | || | {"||"} | | | |\n | |_||_| {"||"} \'| |_| |\n________________|__[_][_]_____[_][_]__[|____________|______________\n1\n | /__\\ #### | _ |\n | |><> | {o o"} | | | |\n | (/\\__) {= } | | | |\n | / \\ {~~ //~}| | | |\n | ||/(===o {}{ //}{}| | | |\n | | / \\ | {}{// {}| |_| |\n | \\/][][\\/ {}/ {} | _ |\n | |\\ /| {}@@{} | | | |\n | |_||_| H"||"} | | | |\n | [ ][ ] {"||"} | | | |\n | | || | {"||"} | | | |\n | |_||_| {"||"} | |_| |\n________________|__[_][_]_____[_][_]__|_____________|______________\n1\n | /__\\ #### | _ |\n | |><> | {"o o} | | | |\n | (/\\__) { =} | | | |\n | / \\ {~~ //~| | | |\n | ||/(===o {}{ //}{| | | |\n | | / \\ | {}{// {| |_| |\n | \\/][][\\/ {}/ {}| _ |\n | |\\ /| {}@@{} | | | |\n | |_||_| H"||"} | | | |\n | [ ][ ] {"||"} | | | |\n | | || | {"||"} | | | |\n | |_||_| {"||"} | |_| |\n________________|__[_][_]_____[_][_]_|______________|______________\n1\n | /__\\ #### | _ |\n | |><> | {"o o}| | | |\n | (/\\__) { =} | | | |\n | / \\ {~~ //| | | |\n | ||/(===o {}{ //}| | | |\n | | / \\ | {}{// | |_| |\n | \\/][][\\/ {}/ {| _ |\n | |\\ /| {}@@{}| | | |\n | |_||_| H"||"}| | | |\n | [ ][ ] {"||"}| | | |\n | | || | {"||"}| | | |\n | |_||_| {"||"}| |_| |\n________________|__[_][_]_____[_][_]|_______________|______________\n1\n | /__\\ ####| _ |\n | |><> | {"o o| | | |\n | (/\\__) { =}| | | |\n | / \\ {~~ /| | | |\n | ||/(===o {}{ //| | | |\n | | / \\ | {}{// | |_| |\n | \\/][][\\/ {}/ | _ |\n | |\\ /| {}@@{| | | |\n | |_||_| H"||"| | | |\n | [ ][ ] {"||"| | | |\n | | || | {"||"| | | |\n | |_||_| {"||"| |_| |\n________________|__[_][_]_____[_][_|________________|______________\n1\n | /__\\ ###| _ |\n | |><> | {o o| | | |\n | (/\\__) {= | | | |\n | / \\ {~~ | | | |\n | ||/(===o {}{ /| | | |\n | | / \\ | {}{// | |_| |\n | \\/][][\\/ {}/ | _ |\n | |\\ /| {}@@| | | |\n | |_||_| H"||| | | |\n | [ ][ ] {"||| | | |\n | | || | {"||| | | |\n | |_||_| {"||| |_| |\n________________|__[_][_]_____[_][|_________________|______________\n1\n | /__\\ ##| _ |\n | |><> | {o | | | |\n | (/\\__) {=| | | |\n | / \\ {~~ | | | |\n | ||/(===o {}{ | | | |\n | | / \\ | {}{//| |_| |\n | \\/][][\\/ {}/ | _ |\n | |\\ /| {}@| | | |\n | |_||_| H"|| | | |\n | [ ][ ] {"|| | | |\n | | || | {"|| | | |\n | |_||_| {"|| |_| |\n________________|__[_][_]_____[_]|__________________|______________\n1\n | /__\\ #| _ |\n | |><> | {o| | | |\n | (/\\__) {| | | |\n | / \\ {~~ | | | |\n | ||/(===o {}{ | | | |\n | | / \\ | {}{/| |_| |\n | \\/][][\\/ {}/| _ |\n | |\\ /| {}| | | |\n | |_||_| H"| | | |\n | [ ][ ] {"| | | |\n | | || | {"| | | |\n | |_||_| {"| |_| |\n________________|__[_][_]_____[_|___________________|______________\n1\n | /__\\ | _ |\n | |><> | {| | | |\n | (/\\__) | | | |\n | / \\ {~~| | | |\n | ||/(===o {}{| | | |\n | | / \\ | {}{| |_| |\n | \\/][][\\/ {}| _ |\n | |\\ /| {| | | |\n | |_||_| H| | | |\n | [ ][ ] {| | | |\n | | || | {| | | |\n | |_||_| {| |_| |\n________________|__[_][_]_____[|____________________|______________\n1\n | /__\\ | _ |\n | |><> | | | | |\n | (/\\__) | | | |\n | / \\ {~| | | |\n | ||/(===o {}| | | |\n | | / \\ | {}| |_| |\n | \\/][][\\/ {| _ |\n | |\\ /| | | | |\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | | | |\n | |_||_| | |_| |\n________________|__[_][_]_____|_____________________|______________\n1\n | /__\\ | _ |\n | | <><| | | | |\n | (__/\\) | | | |\n | / \\ {| | | |\n | ||/(===o {| | | |\n | | / \\ | {| |_| |\n | \\/][][\\/ | _ |\n | |\\ /| | | | |\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | | | |\n | |_||_| | |_| |\n________________|__[_][_]____|______________________|______________\n1\n | /__\\ | _ |\n | | <><| | | | |\n | (__/\\) | | | |\n | / \\ | | | |\n | ||/(===o | | | |\n | | / \\ | | |_| |\n | \\/][][\\/ | _ |\n | |\\ /| | | | |\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | | | |\n | |_||_| | |_| |\n________________|__[_][_]___|_______________________|______________\n1\n | /__\\ | _ |\n | | <><| | | | |\n | (__/\\) | | | |\n | / \\ | | | |\n | ||/(===o | | | |\n | | / \\ | | |_| |\n | \\/][][\\/ | _ |\n | |\\ /| | | | |\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | | | |\n | |_||_| | |_| |\n________________|__[_][_]__|________________________|______________\n1\n | /__\\ | _ |\n | | <><| | | | |\n | (__/\\) | | | |\n | / \\| | | |\n | ||/(===o| | | |\n | | / \\ || |_| |\n | \\/][][\\/| _ |\n | |\\ /| | | | |\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | | | |\n | |_||_| | |_| |\n________________|__[_][_]_|_________________________|______________\n1\n | /__\\ | _ |\n | | <><|| | | |\n | (__/\\)| | | |\n | / | | | |\n | ||/(===| | | |\n | | / \\ | |_| |\n | \\/][][\\| _ |\n | |\\ /|| | | |\n | |_||_|| | | |\n | [ ][ ]| | | |\n | | || || | | |\n | |_||_|| |_| |\n________________|__[_][_]|__________________________|______________\n1\n | /__\\| _ |\n | | <><| | | |\n | (__/\\| | | |\n | / | | | |\n | ||/(==| | | |\n | | / \\| |_| |\n | \\/][][| _ |\n | |\\ /| | | |\n | |_||_| | | |\n | [ ][ | | | |\n | | || | | | |\n | |_||_| |_| |\n________________|__[_][_|___________________________|______________\n1\n | /__| _ |\n | | <>| | | |\n | (__/| | | |\n | / | | | |\n | ||/(=| | | |\n | | / | |_| |\n | \\/][]| _ |\n | |\\ | | | |\n | |_||| | | |\n | [ ][| | | |\n | | ||| | | |\n | |_||| |_| |\n________________|__[_][|____________________________|______________\n1\n | /_| _ |\n | | <| | | |\n | (__| | | |\n | / | | | |\n | ||/(| | | |\n | | / | |_| |\n | \\/][| _ |\n | |\\ | | | |\n | |_|| | | |\n | [ ]| | | |\n | | || | | |\n | |_|| |_| |\n________________|__[_]|_____________________________|______________\n1\n | /| _ |\n | | | | | |\n | (_| | | |\n | / | | | |\n | ||/| | | |\n | | /| |_| |\n | \\/]| _ |\n | |\\| | | |\n | |_| | | |\n | [ | | | |\n | | | | | |\n | |_| |_| |\n________________|__[_|______________________________|______________\n1\n | | _ |\n | || | | |\n | (| | | |\n | / | | | |\n | ||| | | |\n | | | |_| |\n | \\/| _ |\n | || | | |\n | || | | |\n | [| | | |\n | || | | |\n | || |_| |\n________________|__[|_______________________________|______________\n1\n | | _ |\n | | | | |\n | | | | |\n | /| | | |\n | || | | |\n | || |_| |\n | \\| _ |\n | | | | |\n | | | | |\n | | | | |\n | | | | |\n | | |_| |\n________________|__|________________________________|______________\n1\n | | _ |\n | | | | |\n | | | | |\n | | | | |\n | | | | |\n | | |_| |\n | | _ |\n | | | | |\n | | | | |\n | | | | |\n | | | | |\n | | |_| |\n________________|_|_________________________________|______________\n1\n || _ |\n || | | |\n || | | |\n || | | |\n || | | |\n || |_| |\n || _ |\n || | | |\n || | | |\n || | | |\n || | | |\n || |_| |\n________________||__________________________________|______________\n1\n | _ |\n | | | |\n | | | |\n | | | |\n | | | |\n | |_| |\n | _ |\n | | | |\n | | | |\n | | | |\n | | | |\n | |_| |\n________________|___________________________________|______________\n2\n | _ |\n | | | |\n | | | |\n | | | |\n | | | |\n | |_| |\n | _ |\n | | | |\n | | | |\n | | | |\n | | | |\n | |_| |\n________________|___________________________________|______________\n7\n\n\n\n\n\n\n\n\n\n\n\n\n\n2\n | _ |\n | | | |\n | | | |\n | | | |\n | | | |\n | |_| |\n | _ |\n | | | |\n | | | |\n | | | |\n | | | |\n | |_| |\n________________|___________________________________|______________\n1\n || _ |\n || | | |\n || | | |\n || | | |\n || | | |\n || |_| |\n || _ |\n || | | |\n || | | |\n || | | |\n || | | |\n || |_| |\n________________||__________________________________|______________\n1\n | | _ |\n | | | | |\n | | | | |\n | | | | |\n | | | | |\n | | |_| |\n | | _ |\n | | | | |\n | | | | |\n | | | | |\n | | | | |\n | | |_| |\n________________|_|_________________________________|______________\n1\n | | _ |\n | | | | |\n | | | | |\n | /| | | |\n | || | | |\n | || |_| |\n | \\| _ |\n | | | | |\n | | | | |\n | | | | |\n | | | | |\n | | |_| |\n________________|__|________________________________|______________\n1\n | | _ |\n | || | | |\n | (| | | |\n | / | | | |\n | ||| | | |\n | ||| |_| |\n | \\[| _ |\n | || | | |\n | || | | |\n | [| | | |\n | || | | |\n | || |_| |\n________________|__[|_______________________________|______________\n1\n | /| _ |\n | | | | | |\n | (_| | | |\n | / -| | | |\n | ||O| | | |\n | ||-| |_| |\n | \\[(| _ |\n | |\\| | | |\n | | | | | |\n | [ | | | |\n | | | | | |\n | | | |_| |\n________________|__[_|______________________________|______________\n1\n | /_| _ |\n | | | | | |\n | (__| | | |\n | / --| | | |\n | ||O!| | | |\n | ||--| |_| |\n | \\[(_| _ |\n | |\\ | | | |\n | | || | | |\n | [ ]| | | |\n | | || | | |\n | | || |_| |\n________________|__[_]|_____________________________|______________\n1\n | /__| _ |\n | | | | | |\n | (___| | | |\n | / ---| | | |\n | ||O!L| | | |\n | ||---| |_| |\n | \\[(_(| _ |\n | |\\ | | | |\n | | ||| | | |\n | [ ][| | | |\n | | ||| | | |\n | | ||| |_| |\n________________|__[_][|____________________________|______________\n1\n | /__\\| _ |\n | | | | | |\n | (____| | | |\n | / ----| | | |\n | ||O!L|| | | |\n | ||----| |_| |\n | \\[(_()| _ |\n | |\\ /| | | |\n | | || | | | |\n | [ ][ | | | |\n | | || | | | |\n | | || | |_| |\n________________|__[_][_|___________________________|______________\n1\n | /__\\ | _ |\n | | || | | |\n | (____)| | | |\n | / ---- | | | |\n | ||O!L||| | | |\n | ||----|| |_| |\n | \\[(_()]| _ |\n | |\\ /|| | | |\n | | || || | | |\n | [ ][ ]| | | |\n | | || || | | |\n | | || || |_| |\n________________|__[_][__|__________________________|______________\n1\n | /__\\ | _ |\n | | | | | | |\n | (____) | | | |\n | / ---- \\| | | |\n | ||O!L|||| | | |\n | ||----|\\| |_| |\n | \\[(_()] | _ |\n | |\\ /| | | | |\n | | || | | | | |\n | [ ][ ] | | | |\n | | || | | | | |\n | | || | | |_| |\n________________|__[_][__\\|_________________________|______________\n1\n | /__\\ | _ |\n | | | | | | |\n | (____) | | | |\n | / ---- \\ | | | |\n | ||O!L||| | | | |\n | ||----|\\\\| |_| |\n | \\[(_()] \\| _ |\n | |\\ /| | | | |\n | | || | | | | |\n | [ ][ ] | | | |\n | | || | | | | |\n | | || | | |_| |\n________________|__[_][__\\_|________________________|______________\n1\n | /__\\ | _ |\n | | | | | | |\n | (____) .| | | |\n | / ---- \\ || | | |\n | ||O!L||| I| | | |\n | ||----|\\\\I| |_| |\n | \\[(_()] \\I| _ |\n | |\\ /| [| | | |\n | | || | [| | | |\n | [ ][ ] [| | | |\n | | || | || | | |\n | | || | || |_| |\n________________|__[_][__\\_||_______________________|______________\n1\n | /__\\ | _ |\n | | | | | | |\n | (____) . | | | |\n | / ---- \\ | | | | |\n | ||O!L||| I | | | |\n | ||----|\\\\I | |_| |\n | \\[(_()] \\I)| _ |\n | |\\ /| [,| | | |\n | | || | []| | | |\n | [ ][ ] []| | | |\n | | || | |\\| | | |\n | | || | | | |_| |\n________________|__[_][__\\_|_|______________________|______________\n1\n | /__\\ | _ |\n | | | | | | |\n | (____) . | | | |\n | / ---- \\ | | | | |\n | ||O!L||| I | | | |\n | ||----|\\\\I | |_| |\n | \\[(_()] \\I) | _ |\n | |\\ /| [, | | | |\n | | || | [] | | | |\n | [ ][ ] [] | | | |\n | | || | |\\ | | | |\n | | || | | \'| |_| |\n________________|__[_][__\\_|_]|_____________________|______________\n1\n | /__\\ | _ |\n | | | | | | |\n | (____) . | | | |\n | / ---- \\ | {| | | |\n | ||O!L||| I {| | | |\n | ||----|\\\\I {| |_| |\n | \\[(_()] \\I) | _ |\n | |\\ /| [, | | | |\n | | || | [] | | | |\n | [ ][ ] [] | | | |\n | | || | |\\ | | | |\n | | || | | \' | |_| |\n________________|__[_][__\\_|_]_|____________________|______________\n1\n | /__\\ | _ |\n | | | | | | |\n | (____) . | | | |\n | / ---- \\ | {~| | | |\n | ||O!L||| I {}| | | |\n | ||----|\\\\I {}| |_| |\n | \\[(_()] \\I) {| _ |\n | |\\ /| [, | | | |\n | | || | [] | | | |\n | [ ][ ] [] | | | |\n | | || | |\\ | | | |\n | | || | | \' | |_| |\n________________|__[_][__\\_|_]__|___________________|______________\n1\n | /__\\ | _ |\n | | | {| | | |\n | (____) . | | | |\n | / ---- \\ | {~\\| | | |\n | ||O!L||| I {}{| | | |\n | ||----|\\\\I {}{| |_| |\n | \\[(_()] \\I) {}| _ |\n | |\\ /| [, {| | | |\n | | || | [] {| | | |\n | [ ][ ] [] {| | | |\n | | || | |\\ {| | | |\n | | || | | \' {| |_| |\n________________|__[_][__\\_|_]__[|__________________|______________\n1\n | /__\\ #| _ |\n | | | {"| | | |\n | (____) . {| | | |\n | / ---- \\ | {~\\\\| | | |\n | ||O!L||| I {}{\\| | | |\n | ||----|\\\\I {}{~| |_| |\n | \\[(_()] \\I) {}~| _ |\n | |\\ /| [, {~| | | |\n | | || | [] {"| | | |\n | [ ][ ] [] {"| | | |\n | | || | |\\ {"| | | |\n | | || | | \' {"| |_| |\n________________|__[_][__\\_|_]__[_|_________________|______________\n1\n | /__\\ ##| _ |\n | | | {""| | | |\n | (____) . {"| | | |\n | / ---- \\ | {~\\\\~| | | |\n | ||O!L||| I {}{\\\\| | | |\n | ||----|\\\\I {}{~\\| |_| |\n | \\[(_()] \\I) {}~~| _ |\n | |\\ /| [, {~~| | | |\n | | || | [] {"|| | | |\n | [ ][ ] [] {"|| | | |\n | | || | |\\ {"|| | | |\n | | || | | \' {"|| |_| |\n________________|__[_][__\\_|_]__[_]|________________|______________\n1\n | /__\\ ###| _ |\n | | | {"""| | | |\n | (____) . {""| | | |\n | / ---- \\ | {~\\\\~~| | | |\n | ||O!L||| I {}{\\\\~| | | |\n | ||----|\\\\I {}{~\\\\| |_| |\n | \\[(_()] \\I) {}~~\\| _ |\n | |\\ /| [, {~~~| | | |\n | | || | [] {"||| | | |\n | [ ][ ] [] {"||| | | |\n | | || | |\\ {"||| | | |\n | | || | | \' {"||| |_| |\n________________|__[_][__\\_|_]__[_][|_______________|______________\n1\n | /__\\ ####| _ |\n | | | {""""| | | |\n | (____) . {""}| | | |\n | / ---- \\ | {~\\\\~~~| | | |\n | ||O!L||| I {}{\\\\~~| | | |\n | ||----|\\\\I {}{~\\\\~| |_| |\n | \\[(_()] \\I) {}~~\\\\| _ |\n | |\\ /| [, {~~~\\| | | |\n | | || | [] {"||"| | | |\n | [ ][ ] [] {"||"| | | |\n | | || | |\\ {"||"| | | |\n | | || | | \' {"||"| |_| |\n________________|__[_][__\\_|_]__[_][_|______________|______________\n1\n | /__\\ #### | _ |\n | | | {""""}| | | |\n | (____) . {""} | | | |\n | / ---- \\ | {~\\\\~~~~| | | |\n | ||O!L||| I {}{\\\\~~~| | | |\n | ||----|\\\\I {}{~\\\\~~| |_| |\n | \\[(_()] \\I) {}~~\\\\{| _ |\n | |\\ /| [, {~~~\\}| | | |\n | | || | [] {"||"}| | | |\n | [ ][ ] [] {"||"}| | | |\n | | || | |\\ {"||"}| | | |\n | | || | | \' {"||"}| |_| |\n________________|__[_][__\\_|_]__[_][_]|_____________|______________\n1\n | /__\\ #### | _ |\n | | | {""""} | | | |\n | (____) . {""} | | | |\n | / ---- \\ | {~\\\\~~~~~| | | |\n | ||O!L||| I {}{\\\\~~~{| | | |\n | ||----|\\\\I {}{~\\\\~~{| |_| |\n | \\[(_()] \\I) {}~~\\\\{}| _ |\n | |\\ /| [, {~~~\\} | | | |\n | | || | [] {"||"} | | | |\n | [ ][ ] [] {"||"} | | | |\n | | || | |\\ {"||"} | | | |\n | | || | | \' {"||"} | |_| |\n________________|__[_][__\\_|_]__[_][_]_|____________|______________\n1\n | /__\\ #### | _ |\n | | <| {""""} | | | |\n | (___/) . {""} | | | |\n | / ---- \\ | {~\\\\~~~~~}| | | |\n | ||O!L||| I {}{\\\\~~~{}| | | |\n | ||----|\\\\I {}{~\\\\~~{}| |_| |\n | \\[(_()] \\I) {}~~\\\\{} | _ |\n | |\\ /| [, {~~~\\} | | | |\n | | || | [] {"||"} | | | |\n | [ ][ ] [] {"||"} | | | |\n | | || | |\\ {"||"} | | | |\n | | || | | \' {"||"} | |_| |\n________________|__[_][__\\_|_]__[_][_]__|___________|______________\n1\n | /__\\ #### | _ |\n | | <| {""""} | | | |\n | (___/) . {""} | | | |\n | / ---- \\ | {~\\\\~~~~~} | | | |\n | ||O!L||| I {}{\\\\~~~{} | | | |\n | ||----|\\\\I {}{~\\\\~~{} | |_| |\n | \\[(_()] \\I) {}~~\\\\{} | _ |\n | |\\ /| [, {~~~\\} | | | |\n | | || | [] {"||"} | | | |\n | [ ][ ] [] {"||"} | | | |\n | | || | |\\ {"||"} | | | |\n | | || | | \' {"||"} | |_| |\n________________|__[_][__\\_|_]__[_][_]___|__________|______________\n1\n | /__\\ #### | _ |\n | | <| {""""} | | | |\n | (___/) . {""} | | | |\n | / ---- \\ | {~\\\\~~~~~} | | | |\n | ||O!L||| I {}{\\\\~~~{} | | | |\n | ||----|\\\\I {}{~\\\\~~{} | |_| |\n | \\[(_()] \\I) {}~~\\\\{} | _ |\n | |\\ /| [, {~~~\\} | | | |\n | | || | [] {"||"} | | | |\n | [ ][ ] [] {"||"} | | | |\n | | || | |\\ {"||"} | | | |\n | | || | | \' {"||"} | |_| |\n________________|__[_][__\\_|_]__[_][_]____|_________|______________\n1\n | /__\\ #### | _ |\n | | <| {""""} | | | |\n | (___/) . {""} | | | |\n | / ---- \\ | {~\\\\~~~~~} | | | |\n | ||O!L||| I {}{\\\\~~~{} /| | | |\n | ||----|\\\\I {}{~\\\\~~{} \\| |_| |\n | \\[(_()] \\I) {}~~\\\\{} | _ |\n | |\\ /| [, {~~~\\} | | | |\n | | || | [] {"||"} | | | |\n | [ ][ ] [] {"||"} | | | |\n | | || | |\\ {"||"} | | | |\n | | || | | \' {"||"} | |_| |\n________________|__[_][__\\_|_]__[_][_]_____|________|______________\n1\n | /__\\ #### | _ |\n | | | {""""} | | | |\n | (____) . {""} | | | |\n | / ---- \\ | {~\\\\~~~~~} /| | | |\n | ||O!L||| I {}{\\\\~~~{} / | | | |\n | ||----|\\\\I {}{~\\\\~~{} \\\\| |_| |\n | \\[(_()] \\I) {}~~\\\\{} \\| _ |\n | |\\ /| [, {~~~\\} | | | |\n | | || | [] {"||"} | | | |\n | [ ][ ] [] {"||"} | | | |\n | | || | |\\ {"||"} | | | |\n | | || | | \' {"||"} | |_| |\n________________|__[_][__\\_|_]__[_][_]______|_______|______________\n1\n | /__\\ #### | _ |\n | | | {""""} || | | |\n | (____) . {""} (| | | |\n | / ---- \\ | {~\\\\~~~~~} / | | | |\n | ||O!L||| I {}{\\\\~~~{} / || | | |\n | ||----|\\\\I {}{~\\\\~~{} \\\\|| |_| |\n | \\[(_()] \\I) {}~~\\\\{} \\[| _ |\n | |\\ /| [, {~~~\\} || | | |\n | | || | [] {"||"} || | | |\n | [ ][ ] [] {"||"} [| | | |\n | | || | |\\ {"||"} || | | |\n | | || | | \' {"||"} || |_| |\n________________|__[_][__\\_|_]__[_][_]______[|______|______________\n1\n | /__\\ #### /| _ |\n | | | {""""} | | | ||\n | (____) . {""} (_| | ||\n | / ---- \\ | {~\\\\~~~~~} / -| | ||\n | ||O!L||| I {}{\\\\~~~{} / |O| | ||\n | ||----|\\\\I {}{~\\\\~~{} \\\\|-| |_||\n | \\[(_()] \\I) {}~~\\\\{} \\[(| _ |\n | |\\ /| [, {~~~\\} |\\| | ||\n | | || | [] {"||"} | | | ||\n | [ ][ ] [] {"||"} [ | | ||\n | | || | |\\ {"||"} | | | ||\n | | || | | \' {"||"} | | |_||\n________________|__[_][__\\_|_]__[_][_]______[_|_____|______________\n1\n | /__\\ #### /_| _|\n | | | {""""} | | | |\n | (____) . {""} (__| | |\n | / ---- \\ | {~\\\\~~~~~} / --| | |\n | ||O!L||| I {}{\\\\~~~{} / |O!| | |\n | ||----|\\\\I {}{~\\\\~~{} \\\\|--| |_|\n | \\[(_()] \\I) {}~~\\\\{} \\[(_| _|\n | |\\ /| [, {~~~\\} |\\ | | |\n | | || | [] {"||"} | || | |\n | [ ][ ] [] {"||"} [ ]| | |\n | | || | |\\ {"||"} | || | |\n | | || | | \' {"||"} | || |_|\n________________|__[_][__\\_|_]__[_][_]______[_]|____|______________\n1\n | /__\\ #### /__| |\n | | | {""""} | | ||\n | (____) . {""} (___| ||\n | / ---- \\ | {~\\\\~~~~~} / ---| ||\n | ||O!L||| I {}{\\\\~~~{} / |O!L| ||\n | ||----|\\\\I {}{~\\\\~~{} \\\\|---| ||\n | \\[(_()] \\I) {}~~\\\\{} \\[(_(| |\n | |\\ /| [, {~~~\\} |\\ | ||\n | | || | [] {"||"} | ||| ||\n | [ ][ ] [] {"||"} [ ][| ||\n | | || | |\\ {"||"} | ||| ||\n | | || | | \' {"||"} | ||| ||\n________________|__[_][__\\_|_]__[_][_]______[_][|___|______________\n1\n | /__\\ #### /__\\| |\n | | | {""""} | | |\n | (____) . {""} (____| |\n | / ---- \\ | {~\\\\~~~~~} / ----| |\n | ||O!L||| I {}{\\\\~~~{} / |O!L|| |\n | ||----|\\\\I {}{~\\\\~~{} \\\\|----| |\n | \\[(_()] \\I) {}~~\\\\{} \\[(_()| |\n | |\\ /| [, {~~~\\} |\\ /| |\n | | || | [] {"||"} | || | |\n | [ ][ ] [] {"||"} [ ][ | |\n | | || | |\\ {"||"} | || | |\n | | || | | \' {"||"} | || | |\n________________|__[_][__\\_|_]__[_][_]______[_][_|__|______________\n1\n | /__\\ #### /__\\ | |\n | | | {""""} | || |\n | (____) . {""} (____)| |\n | / ---- \\ | {~\\\\~~~~~} / ---- | |\n | ||O!L||| I {}{\\\\~~~{} / |O!L||| |\n | ||----|\\\\I {}{~\\\\~~{} \\\\|----|| |\n | \\[(_()] \\I) {}~~\\\\{} \\[(_()]| |\n | |\\ /| [, {~~~\\} |\\ /|| |\n | | || | [] {"||"} | || || |\n | [ ][ ] [] {"||"} [ ][ ]| |\n | | || | |\\ {"||"} | || || |\n | | || | | \' {"||"} | || || |\n________________|__[_][__\\_|_]__[_][_]______[_][_]|_|______________\n1\n | /__\\ #### /__\\ ||\n | | | {""""} | | ||\n | (____) . {""} (____) ||\n | / ---- \\ | {~\\\\~~~~~} / ---- \\||\n | ||O!L||| I {}{\\\\~~~{} / |O!L||\\||\n | ||----|\\\\I {}{~\\\\~~{} \\\\|----|/||\n | \\[(_()] \\I) {}~~\\\\{} \\[(_()]/||\n | |\\ /| [, {~~~\\} |\\ /| ||\n | | || | [] {"||"} | || | ||\n | [ ][ ] [] {"||"} [ ][ ] ||\n | | || | |\\ {"||"} | || | ||\n | | || | | \' {"||"} | || | ||\n________________|__[_][__\\_|_]__[_][_]______[_][_]_||______________\n1\n | /__\\ #### /__\\ |\n | | | {""""} | | |\n | (____) . {""} (____) |\n | / ---- \\ | {~\\\\~~~~~} / ---- \\ |\n | ||O!L||| I {}{\\\\~~~{} / |O!L||\\\\|\n | ||----|\\\\I {}{~\\\\~~{} \\\\|----|//|\n | \\[(_()] \\I) {}~~\\\\{} \\[(_()]/ |\n | |\\ /| [, {~~~\\} |\\ /| |\n | | || | [] {"||"} | || | |\n | [ ][ ] [] {"||"} [ ][ ] |\n | | || | |\\ {"||"} | || | |\n | | || | | \' {"||"} | || | |\n________________|__[_][__\\_|_]__[_][_]______[_][_]__|______________\n2\n | /__\\ #### /__\\ |\n | | <><| {""""} | | |\n | (__/\\) . {""} (____) |\n | / ---- \\ | {~\\\\~~~~~} / ---- \\ |\n | ||O!L||| I {}{\\\\~~~{} / |O!L||\\\\|\n | ||----|\\\\I {}{~\\\\~~{} \\\\|----|//|\n | \\[(_()] \\I) {}~~\\\\{} \\[(_()]/ |\n | |\\ /| [, {~~~\\} |\\ /| |\n | | || | [] {"||"} | || | |\n | [ ][ ] [] {"||"} [ ][ ] |\n | | || | |\\ {"||"} | || | |\n | | || | | \' {"||"} | || | |\n________________|__[_][__\\_|_]__[_][_]______[_][_]__|______________\n1\n | /__\\ #### /__\\ |\n | | <><| {o o"} | | |\n | (__/\\) . {= } (____) |\n | / ---- \\ | {~\\\\~~~~~} / ---- \\ |\n | ||O!L||| I {}{\\\\~~~{} / |O!L||\\\\|\n | ||----|\\\\I {}{~\\\\~~{} \\\\|----|//|\n | \\[(_()] \\I) {}~~\\\\{} \\[(_()]/ |\n | |\\ /| [, {~~~\\} |\\ /| |\n | | || | [] {"||"} | || | |\n | [ ][ ] [] {"||"} [ ][ ] |\n | | || | |\\ {"||"} | || | |\n | | || | | \' {"||"} | || | |\n________________|__[_][__\\_|_]__[_][_]______[_][_]__|______________\n4\n | /__\\ #### /__\\ |\n | | <><| {o o"} |><> | |\n | (__/\\) . {= } (/\\__) |\n | / ---- \\ | {~\\\\~~~~~} / ---- \\ |\n | ||O!L||| I {}{\\\\~~~{} / |O!L||\\\\|\n | ||----|\\\\I {}{~\\\\~~{} \\\\|----|//|\n | \\[(_()] \\I) {}~~\\\\{} \\[(_()]/ |\n | |\\ /| [, {~~~\\} |\\ /| |\n | | || | [] {"||"} | || | |\n | [ ][ ] [] {"||"} [ ][ ] |\n | | || | |\\ {"||"} | || | |\n | | || | | \' {"||"} | || | |\n________________|__[_][__\\_|_]__[_][_]______[_][_]__|______________\n4\n | /__\\ #### /__\\ |\n | | <><| {o o"} |><> | |\n | (__/\\) . {= } (/\\__) |\n | / ---- \\ | {~\\\\~~~~~} / ---- \\ |\n | ||O!L||| I {}{\\\\~~~{} //|O!L||\\\\|\n | ||----|\\\\I {}{~\\\\~~{} || |----|//|\n | \\[(_()] \\I) {}~~\\\\{} # [(_()]/ |\n | |\\ /| [, {~~~\\} [ |\\ /| |\n | | || | [] {"||"} [ | || | |\n | [ ][ ] [] {"||"} \' [ ][ ] |\n | | || | |\\ {"||"} | || | |\n | | || | | \' {"||"} | || | |\n________________|__[_][__\\_|_]__[_][_]______[_][_]__|______________\n4\n\n\n\n\n\n\n\n\n\n\n\n\n\n11\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) @@@ [....] [|\n [)______________________[___|||__\\__/___[|\n6\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) @ @@ [....] [|\n [)______________________[__|_||__\\__/___[|\n7\n\n\n\n\n\n\n\n\n\n\n\n\n\n3\n | /__\\ #### /__\\ |\n | | <><| {"o o} | <><| |\n | . (__/\\) { =} (__/\\) |\n | | / \\ {~~ //~} / \\ |\n | I | __ | {}{ //}{} ||/(===o |\n | I// / \\ | {}{// {} | / \\|| |\n |(I/ /][][\\| {}/ {} \\[][][] |\n |,] |\\ /|# {}@@{} |\\ /| |\n |[] |_||_| H"||"} |_||_| |\n |[] [ ][ ] {"||"} [ ][ ] |\n |/| | || | {"||"} | || | |\n | | |_||_| {"||"} |_||_| |\n________________|_|__[_][_]_____[_][_]______[_][_]__|______________\n3\n | /__\\ #### /__\\ |\n | | <><| {o o"} | <><| |\n | . (__/\\) {= } (__/\\) |\n | | / \\ {~~ //~} / \\ |\n | I | __ | {}{ //}{} ||/(===o |\n | I// / \\ | {}{// {} | / \\|| |\n |(I/ /][][\\| {}/ {} \\[][][] |\n |,] |\\ /|# {}@@{} |\\ /| |\n |[] |_||_| H"||"} |_||_| |\n |[] [ ][ ] {"||"} [ ][ ] |\n |/| | || | {"||"} | || | |\n | | |_||_| {"||"} |_||_| |\n________________|_|__[_][_]_____[_][_]______[_][_]__|______________\n13\n | /__\\ #### /__\\ |\n | | <><| {"o o} | <><| |\n | . (__/\\) { =} (__/\\) |\n | | / \\ {~~ //~} / \\ |\n | I | __ | {}{ //}{} ||/(===o |\n | I// / \\ | {}{// {} | / \\|| |\n |(I/ /][][\\| {}/ {} \\[][][] |\n |,] |\\ /|# {}@@{} |\\ /| |\n |[] |_||_| H"||"} |_||_| |\n |[] [ ][ ] {"||"} [ ][ ] |\n |/| | || | {"||"} | || | |\n | | |_||_| {"||"} |_||_| |\n________________|_|__[_][_]_____[_][_]______[_][_]__|______________\n1\n\n\n\n\n\n\n\n\n\n\n\n\n\n3\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) @ @@ [....] [|\n [)______________________[__|_||__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [)o @ @@ [....] [|\n [)|_____________________[__|_||__\\__/___[|\n2\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o @ @@ [....] [|\n [)_|____________________[__|_||__\\__/___[|\n2\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [)# o @ @@ [....] [|\n [)|_|___________________[__|_||__\\__/___[|\n2\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) # o @ @@ [....] [|\n [)_|_|__________________[__|_||__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [)o # o @ @@ [....] [|\n [)|_|_|_________________[__|_||__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [)o # o @ @@ [....] [|\n [)|_|_|_________________[_|__||__\\__/___[|\n2\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ @@ [....] [|\n [)_|_|_|________________[_|__||__\\__/___[|\n2\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ @@ [....] [|\n [)__|_|_|_______________[_|__||__\\__/___[|\n3\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ @@ [....] [|\n [)___|_|_|______________[_|__||__\\__/___[|\n30\n\n\n Where are you taking\n this... thing?\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ @@ [....] [|\n [)___|_|_|______________[_|__||__\\__/___[|\n3\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ @@ [....] [|\n [)___|_|_|______________[_|__||__\\__/___[|\n32\n\n\n Prisoner transfer from\n cell block 1138.\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ @@ [....] [|\n [)___|_|_|______________[_|__||__\\__/___[|\n3\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ @@ [....] [|\n [)___|_|_|______________[_|__||__\\__/___[|\n12\n\n\n I wasn\'t notified.\n\n I\'ll have to clear it.\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ @@ [....] [|\n [)___|_|_|______________[_|__||__\\__/___[|\n4\n\n\n I wasn\'t notified.\n\n I\'ll have to clear it.\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ @ @ [....] [|\n [)___|_|_|______________[_|_|_|__\\__/___[|\n2\n\n\n I wasn\'t notified.\n\n I\'ll have to clear it.\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @@ @ [....] [|\n [)___|_|_|______________[_||__|__\\__/___[|\n2\n\n\n I wasn\'t notified.\n\n I\'ll have to clear it.\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ @ [....] [|\n [)___|_|_|______________[_|___|__\\__/___[|\n2\n\n\n I wasn\'t notified.\n\n I\'ll have to clear it.\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @@ @ [....] [|\n [)___|_|_|______________[||___|__\\__/___[|\n2\n\n\n I wasn\'t notified.\n\n I\'ll have to clear it.\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ @ @ [....] [|\n [)___|_|_|______________[_|___|__\\__/___[|\n2\n\n\n I wasn\'t notified.\n\n I\'ll have to clear it.\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ @ @ [....] [|\n [)___|_|_|_____________|[_|___|__\\__/___[|\n2\n\n\n I wasn\'t notified.\n\n I\'ll have to clear it.\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ @ @ [....] [|\n [)___|_|_|____________|_[_|___|__\\__/___[|\n2\n\n\n I wasn\'t notified.\n\n I\'ll have to clear it.\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ @ @ [....] [|\n [)___|_|_|___________|__[_|___|__\\__/___[|\n2\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ @ @ [....] [|\n [)___|_|_|__________|___[_|___|__\\__/___[|\n2\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ @ @ [....] [|\n [)___|_|_|_________|____[_|___|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ @ @ [....] [|\n [)___|_|_|________|_____[_|___|__\\__/___[|\n1\n\n\n Look out!\n\n He\'s loose!\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ @ @ [....] [|\n [)___|_|_|________|_____[_|___|__\\__/___[|\n1\n\n\n Look out!\n\n He\'s loose!\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ @ @ [....] [|\n [)___|_|_|_______|______[_|___|__\\__/___[|\n1\n\n\n Look out!\n\n He\'s loose!\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o #o @ @ @ [....] [|\n [)___|__||_______|______[_|___|__\\__/___[|\n1\n\n\n Look out!\n\n He\'s loose!\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o #o @ @ @ [....] [|\n [)___|__||______|_______[_|___|__\\__/___[|\n1\n\n\n Look out!\n\n He\'s loose!\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # @ @ @ [....] [|\n [)___|___|______|_______[_|___|__\\__/___[|\n1\n\n\n Look out!\n\n He\'s loose!\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # @ @ @ [....] [|\n [)___|___|_____|________[_|___|__\\__/___[|\n1\n\n\n Look out!\n\n He\'s loose!\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o o# @ @ @ [....] [|\n [)___|___||____|________[_|___|__\\__/___[|\n1\n\n\n Look out!\n\n He\'s loose!\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o o# @ @ @ [....] [|\n [)___|___||___|_________[_|___|__\\__/___[|\n1\n\n\n Look out!\n\n He\'s loose!\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o o # @ @ @ [....] [|\n [)___|___|_|__|_________[_|___|__\\__/___[|\n1\n\n\n Look out!\n\n He\'s loose!\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o o # @ @ @ [....] [|\n [)___|___|_|_|__________[_|___|__\\__/___[|\n1\n\n\n Look out!\n\n He\'s loose!\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o o # @ @ @ [....] [|\n [)____|__|_|_|__________[_|___|__\\__/___[|\n3\n\n\n Look out!\n\n He\'s loose!\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o o #@ @ @ [....] [|\n [)____|__|_||___________[_|___|__\\__/___[|\n1\n\n\n Look out!\n\n He\'s loose!\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o o #@ @ @ [....] [|\n [)____|__|_|/___________[_|___|__\\__/___[|\n1\n\n\n Look out!\n\n He\'s loose!\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o o # @ @ @ [....] [|\n [)____|__|_|/___________[_|___|__\\__/___[|\n2\n\n\n Look out!\n\n He\'s loose!\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o o # @ @ [....] [|\n [)____|__|_|/-@_________[_|___|__\\__/___[|\n5\n\n\n Look out!\n\n He\'s loose!\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o o # @ @ [....] [|\n [)____|__|_|--@_________[_|___|__\\__/___[|\n1\n\n\n Look out!\n\n He\'s loose!\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o o # - @ @ [....] [|\n [)____|__|_|--@_________[_|___|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o o # - @ @ [....] [|\n [)____|__|_|--@_________[_|___|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o o # - @ @ [....] [|\n [)____|__|_|--@_________[_|___|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o o # - @ @ [....] [|\n [)_____|_|_|--@_________[_|___|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o o # - @ @ [....] [|\n [)_____|_|_|--@_________[_|___|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) oo # - @ @ [....] [|\n [)______||_|--@_________[_|___|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) -oo # - @ @ [....] [|\n [)______||_|--@_________[_|___|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) - o # - @ @ [....] [|\n [)_______|_|--@_________[_|___|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) - o # - @ @ [....] [|\n [)_______|_|--@_________[_|___|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) - oo# - @ @ [....] [|\n [)_______|||--@_________[_|___|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) - oo# -@ @ [....] [|\n [)_______|||--@_________[_|___|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [)- o # * @ [....] [|\n [)_______|_|--@_________[_|___|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [* o # * @ [....] [|\n [)_______|_|--@_________[_|___|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [). / \\ [|\n [), o #o @ @ [....] [|\n [)_______|_||-@_________[_|___|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) . / \\ [|\n [) o #o @ @ [....] [|\n [)_,_____|_||-@_________[_/___|__\\__/___[|\n2\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ [....] [|\n [)_______|_|-|@_________[_/-@_|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o-# o @ [....] [|\n [)_______|_|--|_________[_/-@|___\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ [....] [|\n [)_______|_|--|_________[_/-@|___\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o #- o @ [....] [|\n [)_______|_|--@|________[_/-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # - o @ [....] [|\n [)_______|_|--@|________[_/-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # - o @ [....] [|\n [)_______|_|--@_|_______[_/|@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # -o @ [....] [|\n [)_______|_|--@_|_______[_/|@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o- @ [....] [|\n [)_______|_|--@_|_______[_|-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o - @ [....] [|\n [)_______|_|--@_|_______[_|-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o - .@ [....] [|\n [)_______|_|--@_|_______[|/-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o - @ [....] [|\n [)_______|_|--@_|_______[|/-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o - .@ [....] [|\n [)_______|_|--@_|_______[|/-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o - @ [....] [|\n [)_______|_|--@_|_______[|/-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o -.@ [....] [|\n [)_______|_|--@_|_______[|/-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o -@ [....] [|\n [)_______|_|--@_|_______[|/-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o .* [....] [|\n [)_______|_|--@_|_______[|/-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o * [....] [|\n [)_______|_|--@_|_______[|/-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o .@ [....] [|\n [)_______|_|--@_|_______[|/-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o @ [....] [|\n [)_______|_|--@_|_______[//-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o . @ [....] [|\n [)_______|_|--@_|_______[//-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o [....] [|\n [)_______|_|--@_|_______[/@-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o . [....] [|\n [)_______|_|--@_|_______[/@-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o [....] [|\n [)_______|_|--@_|_______[/@-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o . [....] [|\n [)_______|__|-@__|______[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o [....] [|\n [)________|_|-@__|______[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o . [....] [|\n [)________|_-|@___|_____[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o [....] [|\n [)_________|-|@___|_____[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o . [....] [|\n [)_________|--|____|____[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o [....] [|\n [)__________|-|____|____[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o . [....] [|\n [)__________|-@|____|___[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o [....] [|\n [)__________-|@|____|___[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o . [....] [|\n [)__________-|@_|____|__[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o [....] [|\n [)__________--|_|____|__[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o . [....] [|\n [)__________--|__|____|_[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o [....] [|\n [)__________--@|_|____|_[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o. [....] [|\n [)__________--@|__|____|[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o [....] [|\n [)__________--@_|_|____|[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o [....] [|\n [)__________--@_|__|____[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o [....] [|\n [)__________--@__|_|____[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # .o [....] [|\n [)__________--@__|__|___[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o [....] [|\n [)__________--@___|_|___[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # . o [....] [|\n [)__________--@___|__|__[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # o [....] [|\n [)__________--@____|_|__[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # . o [....] [|\n [)__________--@____|_|__[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o# o [....] [|\n [)__________--@_____||__[/@-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o# . o [....] [|\n [)__________--@_____||__[/@/@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) # o [....] [|\n [)__________--@______|__[/@/@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) # . o [....] [|\n [)__________--@______|__[/|-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) #o o [....] [|\n [)__________--@______||_[/|-@____\\__/___[|\n1\n\n\n We\'ve got to find out what cell\n this princess of yours is in!\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) #o . o [....] [|\n [)__________--@______||_[/|-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) # o o [....] [|\n [)__________--@______|_|[/|-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) # o. o [....] [|\n [)__________--@______|_|[/|-@____\\__/___[|\n2\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) # o o [....] [|\n [)__________--@______|__[/|-@____\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) # oo [....] [|\n [)__________--@______|__[/|-@____\\__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) # .oo [....] [|\n [)__________--@______|__[/|-@____\\__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) # oo [....] [|\n [)__________--@______|__[/|-@____\\__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) # . o [....] [|\n [)__________--@______|__[/|-@____\\__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) # o [....] [|\n [)__________--@______|__[/|-@____\\__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) # . oo [....] [|\n [)__________--@______|__[/|-@____\\__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) # oo [....] [|\n [)__________--@______|__[/|-@____\\__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) # . o o [....] [|\n [)__________--@______|__[/|-@____\\__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) # o o [....] [|\n [)__________--@_______|_[/|-@____\\__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) # . o o [....] [|\n [)__________--@_______|_[/|-@|___\\__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) # o o [....] [|\n [)__________--@________|[/|-@|___\\__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) #. o o [....] [|\n [)__________--@________|[/|-@_|__\\__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) # o o [....] [|\n [)__________--@_________[/|-@_|__\\__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) # o o[....] [|\n [)__________--@_________[/|-@__|_\\__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) #o o[....] [|\n [)__________--@_________[/|-@__|_\\__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) .#o o....] [|\n [)__________--@_________[/|-@___|\\__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o o....] [|\n [)__________--@_________[/|-@___|\\__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) . o [o...] [|\n [)__________--@_________[/|-@____|__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o# [o...] [|\n [)__________--@_________[/|-@____|__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) . o# [.o..] [|\n [)__________--@_________[/|-@____\\|_/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # [.o..] [|\n [)__________--@_________[/|-@____\\|_/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / o\\ [|\n [) . o # [..|.] [|\n [)__________--@_________[/|-@____\\__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / o\\ [|\n [) o # [..|.] [|\n [)__________--@_________[/|-@|___\\__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) . o # [....] [|\n [)__________--@_________[/|-@|___\\__/___[|\n1\n\n\n Here it is, twenty one eighty seven.\n You go get her.\n\n I\'ll hold them off here!\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # [....] [|\n [)__________--@_________[/|-@_|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) . o # [....] [|\n [)__________--@_________[/|-@_|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # [....] [|\n [)__________--@_________[/|-@_|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) . o # [....] [|\n [)__________--@_________[/|-@_|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) o # [....] [|\n [)__________--@_________[/|-@_|__\\__/___[|\n1\n\n\n\n\n\n\n\n ________________________________________\n | ^ ^ ^ ^ |\n | __ |\n [) / \\ [|\n [) . o # [....] [|\n [)__________--@_________[/|-@_|__\\__/___[|\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n2\n -=== ####\n ""o o {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ * / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== ####\n ""o o {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n ===- ####\n o o" {o o"}\n _\\- /_ {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ * / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n ===- Everything is under ####\n o o"" control. Situation {o o"}\n _\\- /_ normal. {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Everything is under ####\n ""o o control. Situation {o o"}\n _\\ -/_ normal. {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ * / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Everything is under ####\n ""o o control. Situation {o o"}\n _\\ -/_ normal. {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Everything is under ####\n ""o o control. Situation {o o"}\n _\\ -/_ normal. {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ * / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Everything is under ####\n ""o o control. Situation {o o"}\n _\\ -/_ normal. {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n1\n -=== Everything is under ####\n ""o o control. Situation {o o"}\n _\\ -/_ normal. {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ * / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n1\n -=== Everything is under ####\n ""o o control. Situation {"o o}\n _\\ -/_ normal. { =} .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ * / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Everything is under ####\n ""o o control. Situation {"o o}\n _\\ -/_ normal. { =} .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Everything is under ####\n ""o o control. Situation {"o o}\n _\\ -/_ normal. { =} .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ * / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Everything is under ####\n ""o o control. Situation {"o o}\n _\\ -/_ normal. { =} .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Everything is under ####\n ""o o control. Situation {"o o}\n _\\ -/_ normal. { =} .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ * / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Everything is under ####\n ""o o control. Situation {o o"}\n _\\ -/_ normal. {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Everything is under ####\n ""o o control. Situation {o o"}\n _\\ -/_ normal. {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ * / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Everything is under ####\n ""o o control. Situation {o o"}\n _\\ -/_ normal. {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Everything is under ####\n ""o o control. Situation {o o"}\n _\\ -/_ normal. {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ * / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Everything is under ####\n ""o o control. Situation {o o"}\n _\\ -/_ normal. {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n4\n ===- ####\n o o"" {o o"}\n _\\- /_ {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ * / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n1\n ===- ####\n o o"" What\'s your operating {o o"}\n _\\- /_ number? {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n1\n ===- Who is this? ####\n o o"" What\'s your operating {o o"}\n _\\- /_ number? {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Who is this? ####\n ""o o What\'s your operating {o o"}\n _\\ -/_ number? {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ * / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Who is this? ####\n ""o o What\'s your operating {o o"}\n _\\ -/_ number? {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Who is this? ####\n ""o o What\'s your operating {o o"}\n _\\ -/_ number? {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ * / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Who is this? ####\n ""o o What\'s your operating {o o"}\n _\\ -/_ number? {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n1\n -=== Who is this? ####\n ""o o What\'s your operating {o o"}\n _\\ -/_ number? {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ * / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n1\n -=== Who is this? ####\n ""o o What\'s your operating {"o o}\n _\\ -/_ number? { =} .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ * / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Who is this? ####\n ""o o What\'s your operating {"o o}\n _\\ -/_ number? { =} .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Who is this? ####\n ""o o What\'s your operating {"o o}\n _\\ -/_ number? { =} .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ * / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Who is this? ####\n ""o o What\'s your operating {"o o}\n _\\ -/_ number? { =} .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Who is this? ####\n ""o o What\'s your operating {"o o}\n _\\ -/_ number? { =} .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ * / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Who is this? ####\n ""o o What\'s your operating {o o"}\n _\\ -/_ number? {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Who is this? ####\n ""o o What\'s your operating {o o"}\n _\\ -/_ number? {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ * / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Who is this? ####\n ""o o What\'s your operating {o o"}\n _\\ -/_ number? {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Who is this? ####\n ""o o What\'s your operating {o o"}\n _\\ -/_ number? {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ * / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== Who is this? ####\n ""o o What\'s your operating {o o"}\n _\\ -/_ number? {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n2\n -=== ####\n ""o o {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ * / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ // | __ | \\\\ / | {} {// } {}I\n | \\ || [(_()] #) / | {} // } {}I\n \\ \\__#]_|\\__/|_____/ / {} H{{}}} ,I}\n | | [I | || | | | @ H"||"} []\n | | I [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ \\\\| __ | \\\\ * / | {} {// } {}I\n | \\ [(_()] #) / | {} // } {}I\n \\ \\_____|\\__/|_____/ / {} H{{}}} ,I}\n | | | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ \\\\| __ |-\\\\ * / | {} {// } {}I\n | \\ [(_()] #) / | {} // } {}I\n \\ \\_____|\\__/|_____/ / {} H{{}}} ,I}\n | | | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ ______ {{~{ //}~~ I\n | \\ \\\\| __ | \\\\- * / | {} {// } {}I\n | \\ [(_()] #) / | {} // } {}I\n \\ \\_____|\\__/|_____/ / {} H{{}}} ,I}\n | | | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n _______//|O!L||\\\\ __*___ {{~{ //}~~ I\n | \\ \\\\| __ | \\\\ ***/ | {} {// } {}I\n | \\ [(_()] #) */ | {} // } {}I\n \\ \\_____|\\__/|_____/ / {} H{{}}} ,I}\n | | | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ {= } .\n / __ \\ * {~~ //~} |\n _______//|O!L||\\\\ _***__ {{~{ //}~~ I\n | \\ \\\\| __ | \\\\ **** | {} {// } {}I\n | \\ [(_()] #)*** | {} // } {}I\n \\ \\_____|\\__/|_____/ / {} H{{}}} ,I}\n | | | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ {= } .\n / __ \\ , **" {~~ //~} |\n _______//|O!L||\\\\ _****_. {{~{ //}~~ I\n | \\ \\\\| __ | \\\\ *****| {} {// } {}I\n | \\ [(_()] #)****.| {} // } {}I\n \\ \\_____|\\__/|_____*` / {} H{{}}} ,I}\n | | | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ , " {= } .\n / __ \\ .***. {~~ //~} |\n _______//|O!L||\\\\ ****** {{~{ //}~~ I\n | \\ \\\\| __ | \\\\******| {} {// } {}I\n | \\ [(_()] #)*****| {} // } {}I\n \\ \\_____|\\__/|____*** /. {} H{{}}} ,I}\n | | | || | | |, @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ " {= } .\n / __ \\. * . {~~ //~} |\n _______//|O!L||\\\\__****_ {{~{ //}~~ I\n | \\ \\\\| __ | \\\\ **** | {} {// } {}I\n | \\ [(_()] #) ** | {} // } {}I\n \\ \\_____|\\__/|____ * / {} H{{}}} ,I}\n | | | || | | | @ H"||"} []\n | | [ ][ ] | | . {"||"} []\n | | | || | | |, {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/________________________[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ " {= } .\n / __ \\ . {~~ //~} |\n _______//|O!L||\\\\___**__ {{~{ //}~~ I\n | \\ \\\\| __ | \\\\ %**/ | {} {// } {}I\n | \\ [(_()] #) / | {} // } {}I\n \\ \\_____|\\__/|____ / / {} H{{}}} ,I}\n | | | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | . {"||"} | |\n_______\\_|____[_][__\\___|_/__,_____________________[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ {= } .\n / __ \\ " {~~ //~} |\n ______ //|O!L||\\\\_______ {{~{ //}~~ I\n | \\ || | __ | \\\\ %$*/ | {} {// } {}I\n | \\ #] [(_()] #) / | {} // } {}I\n \\ \\__[I_|\\__/|____ / / {} H{{}}} ,I}\n | | I | || | | | . @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/__,_____._______________[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n ______ //|O!L||\\\\_______ {{~{ //}~~ I\n | \\ || | __ | \\\\ %$*/ | {} {// } {}I\n | \\ #] [(_()] #) / | {} // } {}I\n \\ \\__[I_|\\__/|____ / / {} H{{}}} ,I}\n | | I | || | | | . @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | . {"||"} | |\n_______\\_|____[_][__\\___|_/__,_____________________[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n ______ //|O!L||\\\\_______ {{~{ //}~~ I\n | \\ || | __ | \\\\ %$*/ | {} {// } {}I\n | \\ #] [(_()] #) / | {} // } {}I\n \\ \\__[I_|\\__/|____ / / " {} H{{}}} ,I}\n | | I | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | . {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/__,________.____________[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n ______ //|O!L||\\\\_______ {{~{ //}~~ I\n | \\ || | __ | \\\\ %$*/ | {} {// } {}I\n | \\ #] [(_()] #) / | {} // } {}I\n \\ \\__[I_|\\__/|____ / / {} H{{}}} ,I}\n | | I | || | | | @ H"||"} []\n | | [ ][ ] | | " {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/__,_________.___________[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n ______ //|O!L||\\\\_______ {{~{ //}~~ I\n | \\ || | __ | \\\\ %$*/ | {} {// } {}I\n | \\ #] [(_()] #) / | {} // } {}I\n \\ \\__[I_|\\__/|____ / / {} H{{}}} ,I}\n | | I | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | " {"||"} | |\n_______\\_|____[_][__\\___|_/__,__________.__________[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n ______ //|O!L||\\\\_______ {{~{ //}~~ I\n | \\ || | __ | \\\\ %$*/ | {} {// } {}I\n | \\ #] [(_()] #) / | {} // } {}I\n \\ \\__[I_|\\__/|____ / / {} H{{}}} ,I}\n | | I | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/__,__________"._________[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n ______ //|O!L||\\\\_______ {{~{ //}~~ I\n | \\ || | __ | \\\\ %$*/ | {} {// } {}I\n | \\ #] [(_()] #) / | {} // } {}I\n \\ \\__[I_|\\__/|____ / / {} H{{}}} ,I}\n | | I | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | " {"||"} | |\n_______\\_|____[_][__\\___|_/__,____________.________[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n ______ //|O!L||\\\\_______ {{~{ //}~~ I\n | \\ || | __ | \\\\ %$*/ | {} {// } {}I\n | \\ #] [(_()] #) / | {} // } {}I\n \\ \\__[I_|\\__/|____ / / {} H{{}}} ,I}\n | | I | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | " {"||"} | |\n_______\\_|____[_][__\\___|_/__,____________.________[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n ______ //|O!L||\\\\_______ {{~{ //}~~ I\n | \\ || | __ | \\\\ %$*/ | {} {// } {}I\n | \\ #] [(_()] #) / | {} // } {}I\n \\ \\__[I_|\\__/|____ / / {} H{{}}} ,I}\n | | I | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/__,____________.__"_____[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n ______ //|O!L||\\\\_______ {{~{ //}~~ I\n | \\ || | __ | \\\\ %$*/ | {} {// } {}I\n | \\ #] [(_()] #) / | {} // } {}I\n \\ \\__[I_|\\__/|____ / / {} H{{}}} ,I}\n | | I | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/__,____________.___,____[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n ______ //|O!L||\\\\_______ {{~{ //}~~ I\n | \\ || | __ | \\\\ %$*/ | {} {// } {}I\n | \\ #] [(_()] #) / | {} // } {}I\n \\ \\__[I_|\\__/|____ / / {} H{{}}} ,I}\n | | I | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/__,____________.____,___[_][_]_|_|______\n1\n -=== ####\n ""o o Bah! {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n ______ //|O!L||\\\\_______ {{~{ //}~~ I\n | \\ || | __ | \\\\ %$*/ | {} {// } {}I\n | \\ #] [(_()] #) / | {} // } {}I\n \\ \\__[I_|\\__/|____ / / {} H{{}}} ,I}\n | | I | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/__,____________._____,__[_][_]_|_|______\n3\n -=== ####\n ""o o {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n ______ //|O!L||\\\\_______ {{~{ //}~~ I\n | \\ || | __ | \\\\ %$*/ | {} {// } {}I\n | \\ #] [(_()] #) / | {} // } {}I\n \\ \\__[I_|\\__/|____ / / {} H{{}}} ,I}\n | | I | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/__,____________._____,__[_][_]_|_|______\n19\n -=== ####\n ""o o Boring conversation {o o"}\n _\\ -/_ anyway! {= } .\n / __ \\ {~~ //~} |\n ______ //|O!L||\\\\_______ {{~{ //}~~ I\n | \\ || | __ | \\\\ %$*/ | {} {// } {}I\n | \\ #] [(_()] #) / | {} // } {}I\n \\ \\__[I_|\\__/|____ / / {} H{{}}} ,I}\n | | I | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/__,____________._____,__[_][_]_|_|______\n8\n -=== ####\n ""o o Boring conversation {"o o}\n _\\ -/_ anyway! { =} .\n / __ \\ {~~ //~} |\n ______ //|O!L||\\\\_______ {{~{ //}~~ I\n | \\ || | __ | \\\\ %$*/ | {} {// } {}I\n | \\ #] [(_()] #) / | {} // } {}I\n \\ \\__[I_|\\__/|____ / / {} H{{}}} ,I}\n | | I | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/__,____________._____,__[_][_]_|_|______\n1\n -=== ####\n ""o o Boring conversation {o o"}\n _\\ -/_ anyway! {= } .\n / __ \\ {~~ //~} |\n ______ //|O!L||\\\\_______ {{~{ //}~~ I\n | \\ || | __ | \\\\ %$*/ | {} {// } {}I\n | \\ #] [(_()] #) / | {} // } {}I\n \\ \\__[I_|\\__/|____ / / {} H{{}}} ,I}\n | | I | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/__,____________._____,__[_][_]_|_|______\n2\n -=== ####\n ""o o {o o"}\n _\\ -/_ {= } .\n / __ \\ {~~ //~} |\n ______ //|O!L||\\\\_______ {{~{ //}~~ I\n | \\ || | __ | \\\\ %$*/ | {} {// } {}I\n | \\ #] [(_()] #) / | {} // } {}I\n \\ \\__[I_|\\__/|____ / / {} H{{}}} ,I}\n | | I | || | | | @ H"||"} []\n | | [ ][ ] | | {"||"} []\n | | | || | | | {"||"} /|\n | | |_||_| | | {"||"} | |\n_______\\_|____[_][__\\___|_/__,____________._____,__[_][_]_|_|______\n1\n\n\n\n\n\n\n\n\n\n\n\n\n* *\n1\n\n\n\n\n\n\n\n\n\n\n\n\n\n5\n / /__\\ \\\n / | <><| \\\n / (__/\\) \\\n | / \\ |\n | ||/(===o |\n | | / \\ | |\n | \\/][][\\/ |\n | |\\ /| |\n | |_||_| |\n | [ ][ ] |\n \\ | || | /\n \\ | || | /\n \\________________________[_][_]_______________________/\n11\n / /__\\ \\\n / Luke! We\'re | <><| \\\n / going to have (__/\\) \\\n | company! / \\ |\n | ||/(===o |\n | | / \\ | |\n | \\/][][\\/ |\n | |\\ /| |\n | |_||_| |\n | [ ][ ] |\n \\ | || | /\n \\ | || | /\n \\________________________[_][_]_______________________/\n18\n / /__\\ \\\n / Luke! We\'re |><> | \\\n / going to have (/\\__) \\\n | company! / \\ |\n | ||/(===o |\n | | / \\ | |\n | \\/][][\\/ |\n | |\\ /| |\n | |_||_| |\n | [ ][ ] |\n \\ | || | /\n \\ | || | /\n \\________________________[_][_]_______________________/\n5\n / /__\\ \\\n / |><> | \\\n / (/\\__) \\\n | / \\ |\n | ||/(===o |\n | | / \\ | |\n | \\/][][\\/ |\n | |\\ /| |\n | |_||_| |\n | [ ][ ] |\n \\ | || | /\n \\ | || | /\n \\________________________[_][_]_______________________/\n2\n\n\n\n\n\n\n\n\n\n\n\n\n\n4\n / \\ ===,\n | | @- -@)\n | | \\- /\n | | /~~ ~~\\\n | | / ( ) \\\n | | /_/\\ /\\_|\n | | \\\\ \\ // ||\n | | @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n______|_____________|___________________________(_)_(_)____________\n1\n / \\ ===,\n | | @- -@)\n | | \\- /\n | | /~~ ~~\\\n | | / ( ) \\\n | | /_/\\ /\\_|\n | | \\\\ \\ // ||\n | | @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n | | ~~~~~~~\n______|\\___________/|___________________________(_)_(_)____________\n1\n / \\ ===,\n | | @- -@)\n | | \\- /\n | | /~~ ~~\\\n | | / ( ) \\\n | | /_/\\ /\\_|\n | | \\\\ \\ // ||\n | | @ | | | @\n | | | | |\n | | | | |\n | | / | \\\n |\\___________/| ~~~~~~~\n______|____[_][__\\__|___________________________(_)_(_)____________\n1\n / \\ ===,\n | | @o o@)\n | | \\- /\n | | /~~ ~~\\\n | | / ( ) \\\n | | /_/\\ /\\_|\n | | \\\\ \\ // ||\n | | @ | | | @\n | | | | |\n | | | | |\n |\\___________/| / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________(_)_(_)____________\n1\n / \\ ===,\n | | @o o@)\n | | \\- /\n | | /~~ ~~\\\n | | / ( ) \\\n | | /_/\\ /\\_|\n | | \\\\ \\ // ||\n | | @ | | | @\n | | | | |\n |\\___________/| | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________(_)_(_)____________\n1\n / \\ ===,\n | | @o o@)\n | | \\- /\n | | /~~ ~~\\\n | | / ( ) \\\n | | /_/\\ /\\_|\n | | \\\\ \\ // ||\n | | @ | | | @\n |\\___________/| | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________(_)_(_)____________\n1\n / \\ ===,\n | | @o o@)\n | | \\- /\n | | /~~ ~~\\\n | | / ( ) \\\n | | /_/\\ /\\_|\n | | \\\\ \\ // ||\n |\\___________/| @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________(_)_(_)____________\n1\n / \\ ===,\n | | @o o@)\n | | \\- /\n | | /~~ ~~\\\n | | / ( ) \\\n | | /_/\\ /\\_|\n |\\___________/| \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n1\n / \\ ===,\n | | @o o@)\n | | \\- /\n | | /~~ ~~\\\n | | / ( ) \\\n |\\___________/| /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n1\n / \\ ===,\n | | @o o@)\n | | \\- /\n | | /~~ ~~\\\n |\\___________/| / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n1\n / \\ ===,\n | | @o o@)\n | | \\- /\n |\\___________/| /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n1\n / \\ ===,\n | | @o o@)\n |\\___________/| \\- /\n | / \\ | /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n1\n / \\ ===,\n |\\___________/| @o o@)\n | (__/\\) | \\- /\n | / \\ | /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n1\n /___________\\ ===,\n | | <><| | @o o@)\n | (__/\\) | \\- /\n | / \\ | /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n7\n / / \\ \\ ===,\n | | <><| | @o o@)\n | (__/\\) | \\- /\n | / \\ | /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n11\n / / \\ \\ ===,\n | | <><| | Aren\'t you a little @o o@)\n | (__/\\) | short for a \\- /\n | / \\ | Stormtrooper? /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n15\n / / \\ \\ ===,\n | | <><| | Aren\'t you a little @o o@)\n | (__/\\) | short for a \\- /\n | / \\ | Stormtrooper? /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @| | |@\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n3\n / / \\ \\ ===,\n | | <><| | Aren\'t you a little @o o@)\n | (__/\\) | short for a \\- /\n | / \\ | Stormtrooper? /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n4\n / / \\ \\ ===,\n | | <><| | @o o@)\n | (__/\\) | \\- /\n | / \\ | /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n17\n / / \\ \\ ===,\n | | <><| | Oh, the uniform. @o o@)\n | (__/\\) | \\- /\n | / \\ | I\'m Luke Skywalker. /~~ ~~\\\n | ||/(===o | I\'m here to / ( ) \\\n | | / \\ | | rescue you! /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n15\n / / \\ \\ ===,\n | | <><| | Oh, the uniform. @o o@)\n | (__/\\) | \\- /\n | / \\ | I\'m Luke Skywalker. /~~ ~~\\\n | ||/(===o | I\'m here to / ( ) \\\n | | / \\ | | rescue you! /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n2\n / / \\ \\ ===,\n | | <><| | @o o@)\n | (__/\\) | \\- /\n | / \\ | /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n1\n / / \\ \\ ===,\n | | <><| | @o o@)\n | (__/\\) | \\- /\n | / \\ | /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n24\n / / \\ \\ ===,\n | | <><| | You\'re who? @o o@)\n | (__/\\) | \\- /\n | / \\ | /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n2\n / / \\ \\ ===,\n | | <><| | @o o@)\n | (__/\\) | \\- /\n | / \\ | /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n16\n / / \\ \\ ===,\n | | <><| | I\'m with Ben Kenobi! @o o@)\n | (__/\\) | \\- /\n | / \\ | /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n5\n / / \\ \\ ===,\n | |><> | | I\'m with Ben Kenobi! @o o@)\n | (/\\__) | \\- /\n | / \\ | /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n3\n / / \\ \\ ===,\n | |><> | | I\'m with Ben Kenobi! @O O@)\n | (/\\__) | \\- /\n | / \\ | /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n3\n / / \\ \\ ===,\n | |><> | | @O O@)\n | (/\\__) | \\O /\n | / \\ | /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n4\n / / \\ \\ ===,\n | |><> | | Ben Kenobi! @o o@)\n | (/\\__) | \\- /\n | / \\ | Where is he? /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | \\\\ \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n23\n / / \\ \\ ===,\n | | <><| | Ben Kenobi! @o o@)\n | (__/\\) | \\- /\n | / \\ | Where is he? /~~ ~~\\\n | ||/(===o | @\\ / ( ) \\\n | | / \\ | | \\\\_/\\ /\\_|\n | \\/][][\\/ | \\ // ||\n | |\\ /| | | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n3\n / / \\ \\ ===,\n | | <><| | @o o@)\n | (__/\\) | \\- /\n | / \\ | /~~ ~~\\\n | ||/(===o | @\\ / ( ) \\\n | | / \\ | | \\\\_/\\ /\\_|\n | \\/][][\\/ | \\ // ||\n | |\\ /| | | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n9\n / / \\ \\ ===,\n | | <><| | Come on! @o o@)\n | (__/\\) | \\- /\n | / \\ | /~~ ~~\\\n | ||/(===o | @\\ / ( ) \\\n | | / \\ | | \\\\_/\\ /\\_|\n | \\/][][\\/ | \\ // ||\n | |\\ /| | | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n4\n / / \\ \\ ===,\n | |><> | | Come on! @o o@)\n | (/\\__) | \\- /\n | / \\ | /~~ ~~\\\n | ||/(===o | @\\ / ( ) \\\n | | / \\ | | \\\\_/\\ /\\_|\n | \\/][][\\/ | \\ // ||\n | |\\ /| | | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][__\\__|___________________________/__)(_)____________\n2\n / / \\ \\ ===,\n | |><> | | Come on! @o o@)\n | (/\\__) | \\- /\n | / \\ | /~~ ~~\\\n | ||/(===o | @\\ / ( ) \\\n | | / \\ | | \\\\_/\\ /\\_|\n | \\/][][\\/ | \\ // ||\n | |\\ /| | | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][_]___|___________________________/__)(_)____________\n4\n / / \\ \\ ===,\n | |><> | | Come on! @o o@)\n | (/\\__) | \\- /\n | / \\ | /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | || \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|____[_][_]___|___________________________/__)(_)____________\n8\n / / \\ \\ ===,\n | |><> | | Come on! @o o@)\n | (/\\__) | \\- /\n | / \\ | /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | || \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|___/__][_]___|___________________________/__)(_)____________\n6\n / / \\ \\ ===,\n | |><> | | @o o@)\n | (/\\__) | \\- /\n | / \\ | /~~ ~~\\\n | ||/(===o | / ( ) \\\n | | / \\ | | /_/\\ /\\_|\n | \\/][][\\/ | || \\ // ||\n | |\\ /| | @ | | | @\n | |_||_| | | | |\n | [ ][ ] | | | |\n | | || | | / | \\\n | | || | | ~~~~~~~\n______|___/__][_]___|___________________________/__)(_)____________\n3\n\n\n\n\n\n\n\n\n\n\n\n\n\n4\n """"\n 0 0\')\n _\\- /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n4\n """"\n (\'0 0\n __\\ -/_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n___________________________/__]__[__]______________________________\n1\n """"\n (\'0 0\n __\\ -/_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n2\n """"\n (\'0 0 Never gonna to\n __\\ o/_ give you up...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n1\n """"\n (\'0 0 Never gonna to\n __\\ 0/_ give you up...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n1\n """"\n (\'0 0 Never gonna to\n __\\ o/_ give you up...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n2\n """"\n (\'0 0 Never gonna to\n __\\ -/_ give you up...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n2\n """"\n (\'0 0 Never gonna to\n __\\ o/_ give you up...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n5\n """"\n (\'0 0 Never gonna to\n __\\ -/_ / give you up...\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n3\n """"\n (\'0 0 Never gonna to\n __\\ o/_ / give you up...\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n1\n """"\n (\'0 0 Never gonna to\n __\\ -/_ / give you up...\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n4\n """"\n 0 0\') Never gonna to\n __\\o /_ / give you up...\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n2\n """"\n 0 0\') Never gonna to\n __\\o /_ give you up...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n2\n """"\n 0 0\') Never gonna to\n __\\- /_ give you up...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n1\n """"\n 0 0\')\n __\\- /_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n7\n """"\n Never gonna to 0 0\')\n let you down... __\\o /_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n1\n """"\n Never gonna to 0 0\')\n let you down... _\\o /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | //\n /\' | || |/\'\n / || \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n_________________________/__]___[__]_______________________________\n7\n """"\n Never gonna to 0 0\')\n let you down... _\\- /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | //\n /\' | || |/\'\n / || \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n_________________________/__]___[__]_______________________________\n3\n """"\n Never gonna to 0 0\')\n let you down... \\ _\\o /__\n \\\\ / \\ / \\\n \\\\//| || |\\\\\n \\/ | || | \\\\\n | || | //\n | || |/\'\n / || \\\n / | \\ \\\n /___/---\\__\\\n /_/ |_|\n________________________/__]____[_]________________________________\n1\n """"\n Never gonna to 0 0\')\n let you down... \\ _\\- /__\n \\\\ / \\ / \\\n \\\\//| || |\\\\\n \\/ | || | \\\\\n | || | //\n | || |/\'\n / || \\\n / | \\ \\\n /___/---\\__\\\n /_/ |_|\n________________________/__]____[_]________________________________\n1\n """"\n Never gonna to 0 0\')\n let you down... _\\- /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n /_/ |_|\n________________________/__]____[_]________________________________\n5\n """"\n Never gonna to 0 0\')\n let you down... _\\o /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n /_/ |_|\n________________________/__]____[_]________________________________\n1\n """"\n Never gonna to 0 0\')\n let you down... _\\o /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n /_/ |_|\n_________________________/__]____[_]_______________________________\n1\n """"\n Never gonna to 0 0\')\n let you down... _\\- /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n1\n """"\n Never gonna to (\'0 0\n let you down... __\\ -/_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n___________________________/__]__[__]______________________________\n3\n """"\n Never gonna to (\'0 0\n let you down... __\\ o/_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n___________________________/__]__[__]______________________________\n1\n """"\n Never gonna to (\'0 0\n let you down... __\\ o/_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n2\n """"\n Never gonna to (\'0 0\n let you down... __\\ -/_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n1\n """"\n (\'0 0\n __\\ o/_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n1\n """"\n (\'0 0\n __\\ o/_ ,|\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n1\n """"\n (\'0 0 Never gonna to\n __\\ o/_ ,| run around and\n / \\ / \\ // desert you!\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n1\n """"\n (\'0 0 Never gonna to\n __\\ -/_ ,| run around and\n / \\ / \\ // desert you!\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n3\n """"\n (\'0 0 Never gonna to\n __\\ o/_ ,| run around and\n / \\ / \\ // desert you!\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n6\n """"\n (\'0 0 Never gonna to\n __\\ -/_ ,| run around and\n / \\ / \\ // desert you!\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n8\n """"\n (\'0 0 Never gonna to\n __\\ o/_ ,| run around and\n / \\ / \\ // desert you!\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n1\n """"\n 0 0\') Never gonna to\n __\\o /_ \\ run around and\n / \\ / \\ // desert you!\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n1\n """"\n 0 0\') Never gonna to\n __\\- /_ \\ run around and\n / \\ / \\ // desert you!\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n4\n """"\n 0 0\') Never gonna to\n __\\o /_ \\ run around and\n / \\ / \\ // desert you!\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n4\n """"\n 0 0\') Never gonna to\n __\\o /_ run around and\n / \\ / \\ desert you!\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n4\n """"\n 0 0\') Never gonna to\n _\\o /__ run around and\n / \\ / \\ desert you!\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n4\n """"\n (\'0 0 Never gonna to\n __\\ o/_ run around and\n / \\ / \\ desert you!\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n___________________________/__]__[__]______________________________\n4\n """"\n (\'0 0 Never gonna to\n __\\ -/_ run around and\n / \\ / \\ desert you!\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n2\n """"\n (\'0 0 Never gonna to\n __\\ -/_ run around and\n / \\ / \\ desert you!\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n3\n """"\n (\'0 0 Never gonna to\n __\\ o/_ run around and\n / \\ / \\ desert you!\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n3\n """"\n (\'0 0 Never gonna to\n __\\ -/_ ,| run around and\n / \\ / \\ // desert you!\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n3\n """"\n (\'0 0 Never gonna to\n __\\ o/_ ,| run around and\n / \\ / \\ // desert you!\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n1\n """"\n (\'0 0\n __\\ o/_ ,|\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n2\n """"\n (\'0 0\n __\\ -/_ ,|\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n2\n """"\n 0 0\')\n __\\- /_ \\\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n2\n """"\n Never gonna to 0 0\')\n make you cry... __\\- /_ \\\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n10\n """"\n Never gonna to 0 0\')\n make you cry... __\\o /_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n7\n """"\n Never gonna to 0 0\')\n make you cry... __\\- /_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n1\n """"\n Never gonna to 0 0\')\n make you cry... __\\o /_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n1\n """"\n Never gonna to 0 0\')\n make you cry... _\\- /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | //\n /\' | || |/\'\n / || \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n_________________________/__]___[__]_______________________________\n5\n """"\n Never gonna to 0 0\')\n make you cry... _\\o /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | //\n /\' | || |/\'\n / || \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n_________________________/__]___[__]_______________________________\n4\n """"\n Never gonna to 0 0\')\n make you cry... \\ _\\- /__\n \\\\ / \\ / \\\n \\\\//| || |\\\\\n \\/ | || | \\\\\n | || | //\n | || |/\'\n / || \\\n / | \\ \\\n /___/---\\__\\\n /_/ |_|\n________________________/__]____[_]________________________________\n2\n """"\n Never gonna to 0 0\')\n make you cry... _\\- /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n /_/ |_|\n________________________/__]____[_]________________________________\n1\n """"\n Never gonna to 0 0\')\n make you cry... _\\o /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n /_/ |_|\n________________________/__]____[_]________________________________\n1\n """"\n Never gonna to 0 0\')\n make you cry... _\\- /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n /_/ |_|\n_________________________/__]____[_]_______________________________\n1\n """"\n 0 0\')\n _\\- /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n8\n """"\n (\'0 0 Never gonna to\n __\\ o/_ say goodbye...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n___________________________/__]__[__]______________________________\n1\n """"\n (\'0 0 Never gonna to\n __\\ -/_ say goodbye...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n___________________________/__]__[__]______________________________\n1\n """"\n (\'0 0 Never gonna to\n __\\ o/_ say goodbye...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n1\n """"\n (\'0 0 Never gonna to\n __\\ -/_ say goodbye...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n5\n """"\n (\'0 0 Never gonna to\n __\\ o/_ / say goodbye...\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n9\n """"\n (\'0 0 Never gonna to\n __\\ -/_ / say goodbye...\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n1\n """"\n (\'0 0 Never gonna to\n __\\ o/_ / say goodbye...\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n3\n """"\n (\'0 0 Never gonna to\n __\\ -/_ / say goodbye...\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n2\n """"\n 0 0\') Never gonna to\n __\\o /_ / say goodbye...\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n1\n """"\n 0 0\') Never gonna to\n __\\- /_ / say goodbye...\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n1\n """"\n 0 0\') Never gonna to\n __\\o /_ say goodbye...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n2\n """"\n 0 0\')\n _\\- /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n2\n """"\n Never gonna tell (\'0 0\n a lie and __\\ -/_\n hurt you! / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n___________________________/__]__[__]______________________________\n2\n """"\n Never gonna tell (\'0 0\n a lie and __\\ o/_\n hurt you! / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n___________________________/__]__[__]______________________________\n2\n """"\n Never gonna tell (\'0 0\n a lie and __\\ o/_\n hurt you! / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n4\n """"\n Never gonna tell (\'0 0\n a lie and __\\ -/_\n hurt you! / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n2\n """"\n Never gonna tell (\'0 0\n a lie and __\\ o/_\n hurt you! / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n5\n """"\n Never gonna tell (\'0 0\n a lie and __\\ o/_\n hurt you! / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n8\n """"\n Never gonna tell (\'0 0\n a lie and __\\ -/_ ,|\n hurt you! / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n1\n """"\n Never gonna tell 0 0\')\n a lie and __\\- /_ ,|\n hurt you! / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n1\n """"\n Never gonna tell 0 0\')\n a lie and __\\- /_ \\\n hurt you! / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n2\n """"\n Never gonna tell 0 0\')\n a lie and __\\o /_ \\\n hurt you! / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n8\n """"\n Never gonna tell 0 0\')\n a lie and __\\- /_ \\\n hurt you! / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n11\n """"\n Never gonna tell 0 0\')\n a lie and __\\o /_ \\\n hurt you! / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n1\n """"\n Never gonna tell 0 0\')\n a lie and __\\o /_\n hurt you! / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n1\n """"\n Never gonna tell 0 0\')\n a lie and __\\o /_\n hurt you! / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__]_____________________________\n1\n """"\n Never gonna tell 0 0\')\n a lie and _\\o /__\n hurt you! / \\ / \\\n //| | | |\\\\\n // | | | | \\\\\n // | | | | \\\\\n /\' | | | | \'\\\n / | | \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n3\n """"\n Never gonna tell 0 0\')\n a lie and _\\o /__\n hurt you! / \\ / \\\n //| | | |\\\\\n // | | | | \\\\\n // | | | | \\\\\n /\' | | | | \'\\\n / | | \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n1\n """"\n Never gonna tell (\'0 0\n a lie and __\\ o/_\n hurt you! / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n___________________________/__]__[__]______________________________\n3\n """"\n (\'0 0\n __\\ -/_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n___________________________/__]__[__]______________________________\n1\n """"\n (\'0 0\n __\\ -/_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n2\n """"\n (\'0 0 Never gonna to\n __\\ o/_ give you up...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n1\n """"\n (\'0 0 Never gonna to\n __\\ 0/_ give you up...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n1\n """"\n (\'0 0 Never gonna to\n __\\ o/_ give you up...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n2\n """"\n (\'0 0 Never gonna to\n __\\ -/_ give you up...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n2\n """"\n (\'0 0 Never gonna to\n __\\ o/_ give you up...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n5\n """"\n (\'0 0 Never gonna to\n __\\ -/_ / give you up...\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n3\n """"\n (\'0 0 Never gonna to\n __\\ o/_ / give you up...\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n1\n """"\n (\'0 0 Never gonna to\n __\\ -/_ / give you up...\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n4\n """"\n 0 0\') Never gonna to\n __\\o /_ / give you up...\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n2\n """"\n 0 0\') Never gonna to\n __\\o /_ give you up...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n2\n """"\n 0 0\') Never gonna to\n __\\- /_ give you up...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n1\n """"\n 0 0\')\n __\\- /_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n7\n """"\n Never gonna to 0 0\')\n let you down... __\\o /_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n1\n """"\n Never gonna to 0 0\')\n let you down... _\\o /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | //\n /\' | || |/\'\n / || \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n_________________________/__]___[__]_______________________________\n7\n """"\n Never gonna to 0 0\')\n let you down... _\\- /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | //\n /\' | || |/\'\n / || \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n_________________________/__]___[__]_______________________________\n3\n """"\n Never gonna to 0 0\')\n let you down... \\ _\\o /__\n \\\\ / \\ / \\\n \\\\//| || |\\\\\n \\/ | || | \\\\\n | || | //\n | || |/\'\n / || \\\n / | \\ \\\n /___/---\\__\\\n /_/ |_|\n________________________/__]____[_]________________________________\n1\n """"\n Never gonna to 0 0\')\n let you down... \\ _\\- /__\n \\\\ / \\ / \\\n \\\\//| || |\\\\\n \\/ | || | \\\\\n | || | //\n | || |/\'\n / || \\\n / | \\ \\\n /___/---\\__\\\n /_/ |_|\n________________________/__]____[_]________________________________\n1\n """"\n Never gonna to 0 0\')\n let you down... _\\- /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n /_/ |_|\n________________________/__]____[_]________________________________\n5\n """"\n Never gonna to 0 0\')\n let you down... _\\o /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n /_/ |_|\n________________________/__]____[_]________________________________\n1\n """"\n Never gonna to 0 0\')\n let you down... _\\o /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n /_/ |_|\n_________________________/__]____[_]_______________________________\n1\n """"\n Never gonna to 0 0\')\n let you down... _\\- /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n1\n """"\n Never gonna to (\'0 0\n let you down... __\\ -/_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n___________________________/__]__[__]______________________________\n3\n """"\n Never gonna to (\'0 0\n let you down... __\\ o/_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n___________________________/__]__[__]______________________________\n1\n """"\n Never gonna to (\'0 0\n let you down... __\\ o/_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n2\n """"\n Never gonna to (\'0 0\n let you down... __\\ -/_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n1\n """"\n (\'0 0\n __\\ o/_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n1\n """"\n (\'0 0\n __\\ o/_ ,|\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n1\n """"\n (\'0 0 Never gonna to\n __\\ o/_ ,| run around and\n / \\ / \\ // desert you!\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n1\n """"\n (\'0 0 Never gonna to\n __\\ -/_ ,| run around and\n / \\ / \\ // desert you!\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n3\n """"\n (\'0 0 Never gonna to\n __\\ o/_ ,| run around and\n / \\ / \\ // desert you!\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n6\n """"\n (\'0 0 Never gonna to\n __\\ -/_ ,| run around and\n / \\ / \\ // desert you!\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n8\n """"\n (\'0 0 Never gonna to\n __\\ o/_ ,| run around and\n / \\ / \\ // desert you!\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n1\n """"\n 0 0\') Never gonna to\n __\\o /_ \\ run around and\n / \\ / \\ // desert you!\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n1\n """"\n 0 0\') Never gonna to\n __\\- /_ \\ run around and\n / \\ / \\ // desert you!\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n4\n """"\n 0 0\') Never gonna to\n __\\o /_ \\ run around and\n / \\ / \\ // desert you!\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n4\n """"\n 0 0\') Never gonna to\n __\\o /_ run around and\n / \\ / \\ desert you!\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n4\n """"\n 0 0\') Never gonna to\n _\\o /__ run around and\n / \\ / \\ desert you!\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n4\n """"\n (\'0 0 Never gonna to\n __\\ o/_ run around and\n / \\ / \\ desert you!\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n___________________________/__]__[__]______________________________\n4\n """"\n (\'0 0 Never gonna to\n __\\ -/_ run around and\n / \\ / \\ desert you!\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n2\n """"\n (\'0 0 Never gonna to\n __\\ -/_ run around and\n / \\ / \\ desert you!\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n3\n """"\n (\'0 0 Never gonna to\n __\\ o/_ run around and\n / \\ / \\ desert you!\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n3\n """"\n (\'0 0 Never gonna to\n __\\ -/_ ,| run around and\n / \\ / \\ // desert you!\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n3\n """"\n (\'0 0 Never gonna to\n __\\ o/_ ,| run around and\n / \\ / \\ // desert you!\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n1\n """"\n (\'0 0\n __\\ o/_ ,|\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n2\n """"\n (\'0 0\n __\\ -/_ ,|\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n2\n """"\n 0 0\')\n __\\- /_ \\\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n2\n """"\n Never gonna to 0 0\')\n make you cry... __\\- /_ \\\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n10\n """"\n Never gonna to 0 0\')\n make you cry... __\\o /_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n7\n """"\n Never gonna to 0 0\')\n make you cry... __\\- /_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n1\n """"\n Never gonna to 0 0\')\n make you cry... __\\o /_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n1\n """"\n Never gonna to 0 0\')\n make you cry... _\\- /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | //\n /\' | || |/\'\n / || \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n_________________________/__]___[__]_______________________________\n5\n """"\n Never gonna to 0 0\')\n make you cry... _\\o /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | //\n /\' | || |/\'\n / || \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n_________________________/__]___[__]_______________________________\n4\n """"\n Never gonna to 0 0\')\n make you cry... \\ _\\- /__\n \\\\ / \\ / \\\n \\\\//| || |\\\\\n \\/ | || | \\\\\n | || | //\n | || |/\'\n / || \\\n / | \\ \\\n /___/---\\__\\\n /_/ |_|\n________________________/__]____[_]________________________________\n2\n """"\n Never gonna to 0 0\')\n make you cry... _\\- /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n /_/ |_|\n________________________/__]____[_]________________________________\n1\n """"\n Never gonna to 0 0\')\n make you cry... _\\o /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n /_/ |_|\n________________________/__]____[_]________________________________\n1\n """"\n Never gonna to 0 0\')\n make you cry... _\\- /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n /_/ |_|\n_________________________/__]____[_]_______________________________\n1\n """"\n 0 0\')\n _\\- /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n8\n """"\n (\'0 0 Never gonna to\n __\\ o/_ say goodbye...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n___________________________/__]__[__]______________________________\n1\n """"\n (\'0 0 Never gonna to\n __\\ -/_ say goodbye...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n___________________________/__]__[__]______________________________\n1\n """"\n (\'0 0 Never gonna to\n __\\ o/_ say goodbye...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n1\n """"\n (\'0 0 Never gonna to\n __\\ -/_ say goodbye...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n5\n """"\n (\'0 0 Never gonna to\n __\\ o/_ / say goodbye...\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n9\n """"\n (\'0 0 Never gonna to\n __\\ -/_ / say goodbye...\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n1\n """"\n (\'0 0 Never gonna to\n __\\ o/_ / say goodbye...\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n3\n """"\n (\'0 0 Never gonna to\n __\\ -/_ / say goodbye...\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n2\n """"\n 0 0\') Never gonna to\n __\\o /_ / say goodbye...\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n1\n """"\n 0 0\') Never gonna to\n __\\- /_ / say goodbye...\n / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n1\n """"\n 0 0\') Never gonna to\n __\\o /_ say goodbye...\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n2\n """"\n 0 0\')\n _\\- /__\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n2\n """"\n Never gonna tell (\'0 0\n a lie and __\\ -/_\n hurt you! / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n___________________________/__]__[__]______________________________\n2\n """"\n Never gonna tell (\'0 0\n a lie and __\\ o/_\n hurt you! / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n___________________________/__]__[__]______________________________\n2\n """"\n Never gonna tell (\'0 0\n a lie and __\\ o/_\n hurt you! / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n4\n """"\n Never gonna tell (\'0 0\n a lie and __\\ -/_\n hurt you! / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n2\n """"\n Never gonna tell (\'0 0\n a lie and __\\ o/_\n hurt you! / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n5\n """"\n Never gonna tell (\'0 0\n a lie and __\\ o/_\n hurt you! / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n8\n """"\n Never gonna tell (\'0 0\n a lie and __\\ -/_ ,|\n hurt you! / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n // | || |\n /\' | || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n1\n """"\n Never gonna tell 0 0\')\n a lie and __\\- /_ ,|\n hurt you! / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n1\n """"\n Never gonna tell 0 0\')\n a lie and __\\- /_ \\\n hurt you! / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n2\n """"\n Never gonna tell 0 0\')\n a lie and __\\o /_ \\\n hurt you! / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n8\n """"\n Never gonna tell 0 0\')\n a lie and __\\- /_ \\\n hurt you! / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n11\n """"\n Never gonna tell 0 0\')\n a lie and __\\o /_ \\\n hurt you! / \\ / \\ //\n //| || |\\\\//\n // | || | \\/\n \\\\ | || |\n \'\\| || |\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]____[__\\____________________________\n1\n """"\n Never gonna tell 0 0\')\n a lie and __\\o /_\n hurt you! / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__\\_____________________________\n1\n """"\n Never gonna tell 0 0\')\n a lie and __\\o /_\n hurt you! / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]___[__]_____________________________\n1\n """"\n Never gonna tell 0 0\')\n a lie and _\\o /__\n hurt you! / \\ / \\\n //| | | |\\\\\n // | | | | \\\\\n // | | | | \\\\\n /\' | | | | \'\\\n / | | \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n3\n """"\n Never gonna tell 0 0\')\n a lie and _\\o /__\n hurt you! / \\ / \\\n //| | | |\\\\\n // | | | | \\\\\n // | | | | \\\\\n /\' | | | | \'\\\n / | | \\\n / | \\ \\\n /___/---\\__\\\n |_| \\_\\\n__________________________/__]___[__]______________________________\n1\n """"\n Never gonna tell (\'0 0\n a lie and __\\ o/_\n hurt you! / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n___________________________/__]__[__]______________________________\n3\n """"\n (\'0 0\n __\\ -/_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n // | || | \\\\\n /\' | || | \'\\\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n___________________________/__]__[__]______________________________\n1\n """"\n (\'0 0\n __\\ -/_\n / \\ / \\\n //| || |\\\\\n // | || | \\\\\n \\\\ | || | \\\\\n \'\\| || | \'|\n / || \\\n / | \\ \\\n /___ /-- \\__\\\n |_| \\_\\\n____________________________[_]__[__\\______________________________\n48\n\n\n\n\n To be continued.\n\n Simon Jansen (C) 1997 - 2008\n\n www.asciimation.co.nz\n\n\n\n\n1\n\n\n\n\n\n\n\n\n\n\n\n\n\n˙\n' + +local function iterator() + return coroutine.wrap( function() + for line in string.gmatch( filmText, "([^\n]*)\n") do + coroutine.yield(line) + end + return false + end ) +end + +term.clear() +local it = iterator() + +local bFinished = false +while not bFinished do + -- Read the frame header + local holdLine = it() + if not holdLine then + bFinished = true + break + end + + -- Get this every frame incase the monitor resizes + local w,h = term.getSize() + local startX = math.floor( (w - 65) / 2 ) + local startY = math.floor( (h - 14) / 2 ) + + -- Print the frame + term.clear() + for n=1,13 do + local line = it() + if line then + term.setCursorPos(startX, startY + n) + term.write( line ) + else + bFinished = true + break + end + end + + -- Hold the frame + local hold = tonumber(holdLine) or 1 + local delay = (hold * 0.05) - 0.01 + sleep( delay ) +end diff --git a/src/main/resources/assets/computercraft/lua/treasure/deprecated/GopherAtl/talk/talk b/src/main/resources/assets/computercraft/lua/treasure/deprecated/GopherAtl/talk/talk new file mode 100755 index 0000000000..ee7e8a8f87 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/deprecated/GopherAtl/talk/talk @@ -0,0 +1 @@ +print( "\"talk\" was removed in ComputerCraft 1.6, use the builtin \"chat\" program instead!" ) \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/treasure/fredthead/protector/protector b/src/main/resources/assets/computercraft/lua/treasure/fredthead/protector/protector new file mode 100755 index 0000000000..255c238d1e --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/fredthead/protector/protector @@ -0,0 +1,1311 @@ +function initVariables() + w,h =term.getSize() -- 51, 19 + shipYPos = 10 + shipXPos = 24 + shipFacingRight=true + pressedKey=0 + killedState = false + lives=3 + score =0 + aliens=10 + killedDelay=0 + running=true + moveLeft=false + moveRight=true + moveUp=false + moveDown=false + human1x = 3 + human1y = 18 + human2x = 15 + human2y = 18 + human3x = 40 + human3y = 18 + human4x = 60 + human4y = 18 + human5x = 70 + human5y = 18 + human6x = 85 + human6y = 18 + human1 = true + human2 = true + human3 = true + human4 = true + human5 = true + human6 = true + human1Abducted=false + human2Abducted=false + human3Abducted=false + human4Abducted=false + human5Abducted=false + human6Abducted=false + humansLeft=6 + bulletXPos=0 + bulletYPos=0 + bulletState=false + bulletGoingRight=true + alien1 = false + alien1y = 2 + alien1x =84 + alien1Abduct=false + alien1Carry=false + alien1Step=2 + stepValue=0.1 --0.1 +end + +function clear() + term.clear() + term.setCursorPos(1,1) + term.setBackgroundColour(colours.black) + term.setTextColour(colours.white) +end + +function drawGrass() + term.setCursorPos(1,h) + term.setBackgroundColour(colours.green) + write(string.rep(" ",w)) + term.setCursorPos(1,1) + term.setBackgroundColour(colours.black) +end + +function drawShip(yPos) + if shipFacingRight==true then + term.setCursorPos(24,yPos) + term.setBackgroundColour(colours.orange) + print(" ") + term.setCursorPos(25,yPos) + term.setBackgroundColour(colours.white) + print(" ") + else + term.setCursorPos(26,yPos) + term.setBackgroundColour(colours.orange) + print(" ") + term.setCursorPos(24,yPos) + term.setBackgroundColour(colours.white) + print(" ") + end + term.setBackgroundColour(colours.black) +end + +function delShip(yPos) + term.setCursorPos(24,yPos) + term.setBackgroundColour(colours.black) + print(" ") +end + +function drawAliens() + term.setBackgroundColour(colours.cyan) + if alien1==true then + term.setCursorPos(alien1x,alien1y) + write(" ") + end + term.setBackgroundColour(colours.black) +end + +function delAliens() + term.setBackgroundColour(colours.black) + if alien1==true then + term.setCursorPos(alien1x,alien1y) + write(" ") + end +end + +function drawHumans() + term.setBackgroundColour(colours.pink) + if human1==true then + term.setCursorPos(human1x,human1y) + write(" ") + end + if human2==true then + term.setCursorPos(human2x,human2y) + write(" ") + end + if human3==true then + term.setCursorPos(human3x,human3y) + write(" ") + end + if human4==true then + term.setCursorPos(human4x,human4y) + write(" ") + end + if human5==true then + term.setCursorPos(human5x,human5y) + write(" ") + end + if human6==true then + term.setCursorPos(human6x,human6y) + write(" ") + end + term.setBackgroundColour(colours.green) + term.setCursorPos(1,19) + write(" ") + term.setBackgroundColour(colours.black) +end + +function delHumans() + term.setBackgroundColour(colours.black) + if human1==true then + term.setCursorPos(human1x,human1y) + write(" ") + end + if human2==true then + term.setCursorPos(human2x,human2y) + write(" ") + end + if human3==true then + term.setCursorPos(human3x,human3y) + write(" ") + end + if human4==true then + term.setCursorPos(human4x,human4y) + write(" ") + end + if human5==true then + term.setCursorPos(human5x,human5y) + write(" ") + end + if human6==true then + term.setCursorPos(human6x,human6y) + write(" ") + end +end + +function drawBullet() + term.setBackgroundColour(colours.yellow) + term.setCursorPos(bulletXPos,bulletYPos) + write(" ") + term.setBackgroundColour(colours.black) +end + +function delBullet() + term.setBackgroundColour(colours.black) + term.setCursorPos(bulletXPos,bulletYPos) + write(" ") +end + +function newHighScoreTable() + name1="Dan" score1=1000 + name2="Fred" score2=800 + name3="Fred" score3=600 + name4="Fred" score4=400 + name5="Fred" score5=200 + local highScoreTable = {{name1, score1}, {name2,score2}, {name3,score3}, {name4,score4}, {name5,score5}} + local newHighScoreStr = textutils.serialize(highScoreTable) + --print("new table "..newHighScoreStr)-- debug + fs.makeDir("protectordata") + local handle = fs.open("protectordata/pdata","w") + handle.write(newHighScoreStr) + handle.close() +end + +function printCent(xpos,text) + local ypos = w/2 - (string.len(text)/2) + term.setCursorPos(ypos,xpos) + write(text) +end + +function introHighScoreTable() + term.clear() + term.setCursorPos(35,1) write("SPACE WHEN READY") + if fs.exists("protectordata")==false then + newHighScoreTable() + end + local handle = fs.open("protectordata/pdata","r") + local dataStr = handle.readAll() + handle.close() + --print("dataStr "..dataStr) + highScoreData = textutils.unserialize(dataStr) + --print(highScoreData[2]) + name1 = highScoreData[1][1] score1 = highScoreData[1][2] + name2 = highScoreData[2][1] score2 = highScoreData[2][2] + name3 = highScoreData[3][1] score3 = highScoreData[3][2] + name4 = highScoreData[4][1] score4 = highScoreData[4][2] + name5 = highScoreData[5][1] score5 = highScoreData[5][2] + term.setTextColour(colours.yellow) + printCent(5,"HIGH SCORES") + term.setTextColour(colours.white) + printCent(7,name1.." "..score1) + printCent(8,name2.." "..score2) + printCent(9,name3.." "..score3) + printCent(10,name4.." "..score4) + printCent(11,name5.." "..score5) +end + + +function printScore() + term.clear() + term.setTextColour(colours.yellow) + printCent(3,"HIGH SCORES") + term.setTextColour(colours.white) + printCent(5,name1.." "..score1) + printCent(6,name2.." "..score2) + printCent(7,name3.." "..score3) + printCent(8,name4.." "..score4) + printCent(9,name5.." "..score5) + playAgain() +end + +function rewriteScores() + if newScore > score1 then + name5=name4 score5=score4 + name4=name3 score4=score3 + name3=name2 score3=score2 + name2=name1 score2=score1 + name1= newName score1=newScore + elseif newScore > score2 then + name5=name4 score5=score4 + name4=name3 score4=score3 + name3=name2 score3=score2 + name2=newName score2=newScore + elseif newScore > score3 then + name5=name4 score5=score4 + name4=name3 score4=score3 + name3=newName score3=newScore + elseif newScore > score4 then + name5=name4 score5=score4 + name4=newName score4=newScore + elseif newScore > score5 then + name5=newName score5=newScore + end + local highScoreTable = {{name1, score1}, {name2,score2}, {name3,score3}, {name4,score4}, {name5,score5}} + local newHighScoreStr = textutils.serialize(highScoreTable) + local handle = fs.open("protectordata/pdata","w") + handle.write(newHighScoreStr) + handle.close() +end + +function newHighScoreObtained() + clear() + term.setTextColour(colours.yellow) + printCent(8,"CONGRATULATIONS") + term.setTextColour(colours.white) + printCent(10,"You have a new high score!") + printCent(12,"Enter your name: ") + printCent(14," ") + local newNameStr = "" + local newNameStrLen = 0 + while true do + local event,p1,p2,p3 = os.pullEvent() + if event=="char" and newNameStrLen < 9 then + newNameStr=newNameStr..p1 + newNameStrLen=newNameStrLen+1 + printCent(14,newNameStr.." ") + + elseif event=="key" and p1 == 14 and newNameStrLen>0 then + newNameStr=string.sub(newNameStr,1,string.len(newNameStr)-1) + newNameStrLen=newNameStrLen-1 + term.setCursorPos(1,14) + write(string.rep(" ",w)) + printCent(14,newNameStr.." ") + elseif event=="key" and p1== 28 then + newName = newNameStr + newScore = score + rewriteScores() + printScore() + end + end + + + +end + +function highScore() + if fs.exists("protectordata")==false then + newHighScoreTable() + end + local handle = fs.open("protectordata/pdata","r") + local dataStr = handle.readAll() + handle.close() + --print("dataStr "..dataStr) + highScoreData = textutils.unserialize(dataStr) + --print(highScoreData[2]) + name1 = highScoreData[1][1] score1 = highScoreData[1][2] + name2 = highScoreData[2][1] score2 = highScoreData[2][2] + name3 = highScoreData[3][1] score3 = highScoreData[3][2] + name4 = highScoreData[4][1] score4 = highScoreData[4][2] + name5 = highScoreData[5][1] score5 = highScoreData[5][2] + if score>score5 then + newHighScoreObtained() + end + printScore() + + +end + + + + +function gameOver(gameOverMsg) + clear() + delShip(shipYPos) + term.setCursorPos(40,1) + write("Lives: "..lives.." ") + term.setCursorPos(5,1) + if score<0 then score=0 end + write("Score: "..score.." ") + term.setTextColour(colours.red) + term.setCursorPos( (w/2)-5 , h/2 -1) + print("GAME OVER") + term.setCursorPos( (w/2)-(string.len(gameOverMsg)/2) , (h/2)+1) + print(gameOverMsg) + term.setTextColour(colours.white) + running=false + sleep(1.5) + highScore()-- new + --playAgain +end + +function playAgain() + sleep(1) + printCent(12,"Play again (Y or N)") + + while true do + local event,p1,p2,p3 = os.pullEvent() + if event=="char" then + if string.lower(p1)=="y" then + runGame() + elseif string.lower(p1)=="n" then + os.shutdown() + end + end + end + +end + +function killPlayer() + moveLeft=false + moveRight=false + moveUp=false + moveDown=false + delShip(shipYPos) + lives=lives-1 + if lives==0 then + gameOver("OUT OF LIVES") + end + killedState=true + --killedStr="true" +end + +function left() + delHumans() + delAliens() + human1x=human1x+1 + human2x=human2x+1 + human3x=human3x+1 + human4x=human4x+1 + human5x=human5x+1 + human6x=human6x+1 + alien1x=alien1x+1 + if human1x>100 then human1x=0 end + if human2x>100 then human2x=0 end + if human3x>100 then human3x=0 end + if human4x>100 then human4x=0 end + if human5x>100 then human5x=0 end + if human6x>100 then human6x=0 end + if alien1x>100 then alien1x=0 end + shipFacingRight=false + checkShipCollision() + drawShip(shipYPos) + drawHumans() + drawAliens() + drawBorder() + moveRight=false +end + +function right() + delHumans() + delAliens() + human1x=human1x-1 + human2x=human2x-1 + human3x=human3x-1 + human4x=human4x-1 + human5x=human5x-1 + human6x=human6x-1 + alien1x=alien1x-1 + if human1x<1 then human1x=100 end + if human2x<1 then human2x=100 end + if human3x<1 then human3x=100 end + if human4x<1 then human4x=100 end + if human5x<1 then human5x=100 end + if human6x<1 then human6x=100 end + if alien1x<1 then alien1x=100 end + shipFacingRight=true + checkShipCollision() + drawShip(shipYPos) + drawHumans() + drawAliens() + drawBorder() + moveLeft=false +end + +function up() + if shipYPos > 2 then + delShip(shipYPos) + shipYPos=shipYPos-1 + checkShipCollision() + drawShip(shipYPos) + end + moveUp=false + moveDown=false +end + +function down() + if shipYPos<17 then + delShip(shipYPos) + shipYPos=shipYPos+1 + checkShipCollision() + drawShip(shipYPos) + end + moveDown=false + moveUp=false +end + +function checkShipCollision() + if killedState==false then + if shipYPos == alien1y and alien1== true then + if alien1x >= 22 and alien1x <= 26 then + alien1Hit() + killPlayer() + end + elseif human1==true and human1y==shipYPos then + if human1x >=24 and human1x <= 26 then + human1=false + humanHitRoutine() + end + elseif human2==true and human2y==shipYPos then + if human2x >=24 and human2x <= 26 then + human2=false + humanHitRoutine() + end + elseif human3==true and human3y==shipYPos then + if human3x >=24 and human3x <= 26 then + human3=false + humanHitRoutine() + end + elseif human4==true and human4y==shipYPos then + if human4x >=24 and human4x <= 26 then + human4=false + humanHitRoutine() + end + elseif human5==true and human5y==shipYPos then + if human5x >=24 and human5x <= 26 then + human5=false + humanHitRoutine() + end + elseif human6==true and human6y==shipYPos then + if human6x >=24 and human6x <= 26 then + human6=false + humanHitRoutine() + end + end + end +end + +function alienGen() + if alien1==false then + local alienChance= math.random(1,10) + if alienChance==1 then + if human1==true then + alien1 = true + alien1y = 2 + alien1x = human1x - 1 + end + elseif alienChance == 2 then + if human2==true then + alien1 = true + alien1y=2 + alien1x = human2x-1 + end + elseif alienChance == 3 then + if human3==true then + alien1 = true + alien1y=2 + alien1x = human3x-1 + end + elseif alienChance == 4 then + if human4==true then + alien1 = true + alien1y=2 + alien1x = human4x-1 + end + elseif alienChance == 5 then + if human5==true then + alien1 = true + alien1y=2 + alien1x = human5x-1 + end + elseif alienChance == 6 then + if human6==true then + alien1 = true + alien1y=2 + alien1x = human6x-1 + end + end + end +end + +function alienDown() + if alien1==true and alien1Abduct==false and alien1y<19 then + alien1Step=alien1Step+stepValue + alien1y=math.floor(alien1Step) + if alien1==true and alien1Abduct==false and alien1y==17 then + alien1Abduct=true + alien1Carry=true + alien1Step=17 + end + end +end + +function alienRoutine() + alien1=false + alien1Step=2 + if alien1Carry==true then + score= score -50 + humansLeft=humansLeft-1 + end + alien1Abduct=false + alien1Carry=false + if humansLeft==0 then + gameOver("NO HUMANS LEFT") + end + +end + +function alienUp() + if alien1==true and alien1Abduct==true then + if alien1x+1 == human1x then + human1Abducted=true + alien1Step=alien1Step-stepValue + alien1y=math.floor(alien1Step) + human1y=math.floor(alien1Step)+1 + human1x=alien1x+1 + if human1y<=2 then + alienRoutine() + human1=false + end + elseif alien1x+1 == human2x then + human2Abducted=true + alien1Step=alien1Step-stepValue + alien1y=math.floor(alien1Step) + human2y=math.floor(alien1Step)+1 + human2x=alien1x+1 + if human2y<=2 then + alienRoutine() + human2=false + end + elseif alien1x+1 == human3x then + human3Abducted=true + alien1Step=alien1Step-stepValue + alien1y=math.floor(alien1Step) + human3y=math.floor(alien1Step)+1 + human3x=alien1x+1 + if human3y<=2 then + alienRoutine() + human3=false + end + elseif alien1x+1 == human4x then + human4Abducted=true + alien1Step=alien1Step-stepValue + alien1y=math.floor(alien1Step) + human4y=math.floor(alien1Step)+1 + human4x=alien1x+1 + if human4y<=2 then + alienRoutine() + human4=false + end + elseif alien1x+1 == human5x then + human5Abducted=true + alien1Step=alien1Step-stepValue + alien1y=math.floor(alien1Step) + human5y=math.floor(alien1Step)+1 + human5x=alien1x+1 + if human5y<=2 then + alienRoutine() + human5=false + end + elseif alien1x+1 == human6x then + human6Abducted=true + alien1Step=alien1Step-stepValue + alien1y=math.floor(alien1Step) + human6y=math.floor(alien1Step)+1 + human6x=alien1x+1 + if human6y<=2 then + alienRoutine() + human6=false + end + end + end + if alien1==false then alienGen() end +end + +function keyPress() -- 200 UP, 208 DOWN, 203 LEFT, 205 RIGHT, 57 SPACE, 16 Q + if pressedKey==200 or pressedKey == 17 then -- up + moveUp=true + moveDown=false + elseif pressedKey==208 or pressedKey == 31 then -- DOWN + moveDown=true + moveUp=false + elseif pressedKey==203 or pressedKey == 30 then -- left + moveLeft=true + moveRight=false + elseif pressedKey==205 or pressedKey == 32 then -- right + moveRight=true + moveLeft=false + elseif pressedKey==57 then -- space + if bulletState==false then + bulletYPos=shipYPos + bulletState=true + if shipFacingRight==true then + bulletXPos=shipXPos+3 + bulletGoingRight=true + else + bulletXPos=shipXPos-1 + bulletGoingRight=false + end + end + elseif pressedKey==25 then -- q (use 25 if p for quit) + gameOver("YOU QUIT") + end + + --term.setCursorPos(30,1) + --write(pressedKey.." ") +end + +function removeBullet() + if bulletGoingRight==true then + bulletXPos = 60 + else + bulletXPos = -10 + end +end + +function alien1Hit() + delAliens() + alien1=false + score=score+20 + alien1Step=2 + alien1Abduct=false + removeBullet() + drawAliens() +end + +function humanHitRoutine() + score=score-50 + humansLeft=humansLeft-1 + if humansLeft==0 then + gameOver("NO HUMANS LEFT") + end + if alien1Carry==true then alien1Carry=false end +end + + +function checkBulletCollision() + if alien1 == true and bulletYPos == alien1y then + if bulletXPos >= alien1x and bulletXPos <= alien1x + 3 then + alien1Hit() + end + end + if human1 == true and bulletYPos == human1y and bulletXPos == human1x then human1=false humanHitRoutine() end + if human2 == true and bulletYPos == human2y and bulletXPos == human2x then human2=false humanHitRoutine() end + if human3 == true and bulletYPos == human3y and bulletXPos == human3x then human3=false humanHitRoutine() end + if human4 == true and bulletYPos == human4y and bulletXPos == human4x then human4=false humanHitRoutine() end + if human5 == true and bulletYPos == human5y and bulletXPos == human5x then human5=false humanHitRoutine() end + if human6 == true and bulletYPos == human6y and bulletXPos == human6x then human6=false humanHitRoutine() end +end + +function drawBorder() + term.setBackgroundColour(colours.black) + for i=1,h-2 do + term.setCursorPos(1,i+1) + write(" ") + term.setCursorPos(w,i+1) + write(" ") + end +end + +function dropHumans() + if alien1Abduct==false then + if human1y<18 then human1y = human1y+1 end + if human2y<18 then human2y = human2y+1 end + if human3y<18 then human3y = human3y+1 end + if human4y<18 then human4y = human4y+1 end + if human5y<18 then human5y = human5y+1 end + if human6y<18 then human6y = human6y+1 end + end +end + + +function gameControl() + + gameTimer=os.startTimer(0.1) + + while running do + local event,p1,p2,p3 = os.pullEvent() + if score<0 then score=0 end + term.setCursorPos(1,1) + term.setBackgroundColour(colours.yellow) + write(string.rep(" ",w)) + + + term.setTextColour(colours.red) + term.setCursorPos(5,1) + write("Score: "..score.." ") + term.setCursorPos(20,1) + write("Humans Left: "..humansLeft.." ") + term.setCursorPos(40,1) + write("Lives: "..lives.." ") + + term.setBackgroundColour(colours.black) + term.setTextColour(colours.white) + + local newStepValue = (score+0.1)/1000 + if newStepValue > stepValue then stepValue= newStepValue end + if stepValue>0.4 then stepValue=0.4 end + + + --[[DEBUG + term.setCursorPos(2,2) + write("human1x "..human1x.." ") + term.setCursorPos(2,3) + write("human2x "..human2x.." ") + term.setCursorPos(2,4) + write("human3x "..human3x.." ") + term.setCursorPos(2,5) + write("human4x "..human4x.." ") + term.setCursorPos(2,6) + write("human5x "..human5x.." ") + term.setCursorPos(2,7) + write("human6x "..human6x.." ") + ]]-- + + + if event=="timer" and gameTimer == p1 then + if killedState==true then + delShip(shipYPos) + delHumans() + dropHumans() + drawHumans() + killedDelay = killedDelay + 1 + if killedDelay>20 then + shipYPos = 10 + killedState = false + term.setBackgroundColour(colours.black) + for i = 2, h-2 do + term.setCursorPos(1,i) + write(string.rep(" ",w)) + end + drawGrass() + if shipFacingRight==true then + moveRight=true + moveLeft=false + else + moveLeft=true + moveRight=false + end + killedDelay=0 + end + else + + --alienGen() + drawShip(shipYPos) + delAliens() + + delHumans() + dropHumans() + alienDown() + alienUp() + drawAliens() + drawHumans() + drawBorder() + end + + if bulletState==true then + if bulletGoingRight==true then + delBullet() + bulletXPos=bulletXPos+1 + checkBulletCollision() + if bulletXPos>45 then + bulletState=false + else + if killedState==false then drawBullet() end + end + else + delBullet() + bulletXPos=bulletXPos-1 + checkBulletCollision() + if bulletXPos<6 then + bulletState=false + else + if killedState==false then drawBullet() end + end + end + end + + if moveLeft==true then + left() + end + if moveRight==true then + right() + end + if moveUp==true then + up() + end + if moveDown==true then + down() + end + + gameTimer=os.startTimer(0.1) + + elseif event=="key" and killedState==false then + pressedKey=p1 + keyPress() + end + + end + +end + +function runGame() + initVariables() + clear() + drawGrass() + drawHumans() + alienGen() + gameControl() +end + + +function pix(xCo,yCo,text,col) + if col== nil then term.setBackgroundColour(colours.black) + elseif col =="white" then term.setBackgroundColour(colours.white) + elseif col =="green" then term.setBackgroundColour(colours.green) + elseif col =="pink" then term.setBackgroundColour(colours.pink) + elseif col =="orange" then term.setBackgroundColour(colours.orange) + elseif col =="cyan" then term.setBackgroundColour(colours.cyan) + elseif col =="yellow" then term.setBackgroundColour(colours.yellow) + end + term.setCursorPos(xCo,yCo) + write(text) +end + +function drawHumanPix() + drawGrass() + pix(23,humanPixY," ","pink") + pix(27,humanPixY," ","pink") + pix(24,humanPixY-1," ","pink") + pix(26,humanPixY-1," ","pink") + pix(25,humanPixY-2," ","pink") + pix(23,humanPixY-3," ","pink") + pix(25,humanPixY-4," ","pink") + pix(24,humanPixY-5," ","pink") + pix(24,humanPixY-6," ","pink") +end + +function delHumanPix() + pix(23,humanPixY," ") + pix(27,humanPixY," ") + pix(24,humanPixY-1," ") + pix(26,humanPixY-1," ") + pix(25,humanPixY-2," ") + pix(23,humanPixY-3," ") + pix(25,humanPixY-4," ") + pix(24,humanPixY-5," ") + pix(24,humanPixY-6," ") +end + +function drawAlienPix() + pix(19,alienPixY," ","cyan") + pix(17,alienPixY+1," ","cyan") + pix(19,alienPixY+2," ","cyan") +end + +function delAlienPix() + pix(19,alienPixY," ") + pix(17,alienPixY+1," ") + pix(19,alienPixY+2," ") +end + +function drawShipPix() + pix(shipPixX+3,3," ","white") + pix(shipPixX+3,4," ","white") + pix(shipPixX+3,5," ","white") + pix(shipPixX+3,6," ","white") + pix(shipPixX+3,7," ","white") + pix(shipPixX+2,5," ","orange") + pix(shipPixX+2,6," ","yellow") + pix(shipPixX+2,7," ","orange") + pix(shipPixX,6," ","orange") + pix(shipPixX+14,5," ","cyan") +end + +function delShipPix() + pix(shipPixX+3,3," ") + pix(shipPixX+3,4," ") + pix(shipPixX+3,5," ") + pix(shipPixX+3,6," ") + pix(shipPixX+3,7," ") + pix(shipPixX+2,5," ") + pix(shipPixX+2,6," ") + pix(shipPixX+2,7," ") + pix(shipPixX,6," ") + pix(shipPixX+14,5," ") +end + +function line1() + pix(8,4," ","white") + pix(12,4," ","white") + pix(16,4," ","white") + pix(20,4," ","white") + pix(24,4," ","white") + pix(28,4," ","white") + pix(32,4," ","white") + pix(36,4," ","white") + pix(40,4," ","white") +end + +function line2() + pix(8,5," ","white") + pix(10,5," ","white") + pix(12,5," ","white") + pix(14,5," ","white") + pix(16,5," ","white") + pix(18,5," ","white") + pix(21,5," ","white") + pix(24,5," ","white") + pix(28,5," ","white") + pix(33,5," ","white") + pix(36,5," ","white") + pix(38,5," ","white") + pix(40,5," ","white") + pix(42,5," ","white") + +end + +function line3() + pix(8,6," ","white") + pix(12,6," ","white") + pix(16,6," ","white") + pix(18,6," ","white") + pix(21,6," ","white") + pix(24,6," ","white") + pix(28,6," ","white") + pix(33,6," ","white") + pix(36,6," ","white") + pix(38,6," ","white") + pix(40,6," ","white") +end + +function line4() + pix(8,7," ","white") + pix(12,7," ","white") + pix(16,7," ","white") + pix(18,7," ","white") + pix(21,7," ","white") + pix(24,7," ","white") + pix(28,7," ","white") + pix(33,7," ","white") + pix(36,7," ","white") + pix(38,7," ","white") + pix(40,7," ","white") +end + +function line5() + pix(8,8," ","white") + pix(12,8," ","white") + pix(14,8," ","white") + pix(16,8," ","white") + pix(21,8," ","white") + pix(24,8," ","white") + pix(28,8," ","white") + pix(33,8," ","white") + pix(36,8," ","white") + pix(40,8," ","white") + pix(42,8," ","white") +end + + +function startScreen() + + clear() + term.setBackgroundColour(colours.green) + term.setCursorPos(1,h) + write(string.rep(" ",w)) + local screenStage=0 + + screenTimer=os.startTimer(0.1) + while true do + local event,p1,p2,p3=os.pullEvent() + if event=="key"and p1==57 then + term.setBackgroundColour(colours.black) + clear() + runGame() + elseif event=="timer" and screenTimer == p1 then + + --term.setCursorPos(1,1) write("screenStage: "..screenStage.." ") + + term.setBackgroundColour(colours.black) + term.setCursorPos(35,1) write("SPACE WHEN READY") + + if screenStage>0 and screenStage<0.5 then + humanPixY = 18 + drawHumanPix() + elseif screenStage>2 and screenStage<2.9 then + alienPixY = -2 + drawAlienPix() + elseif screenStage>3 and screenStage<3.9 then + alienPixY = -2 + delAlienPix() + alienPixY = -1 + drawAlienPix() + elseif screenStage>4 and screenStage<4.9 then + alienPixY = -1 + delAlienPix() + alienPixY = 0 + drawAlienPix() + elseif screenStage>5 and screenStage<5.9 then + alienPixY = 0 + delAlienPix() + alienPixY = 1 + drawAlienPix() + elseif screenStage>6 and screenStage<6.9 then + alienPixY = 1 + delAlienPix() + alienPixY = 2 + drawAlienPix() + elseif screenStage>7 and screenStage<7.9 then + alienPixY = 2 + delAlienPix() + alienPixY = 3 + drawAlienPix() + elseif screenStage>8 and screenStage<8.9 then + alienPixY = 3 + delAlienPix() + alienPixY = 4 + drawAlienPix() + elseif screenStage>8 and screenStage<9.9 then + alienPixY = 4 + delAlienPix() + alienPixY = 5 + drawAlienPix() + elseif screenStage>10 and screenStage<10.4 then + pix(25,8," ","yellow") + pix(25,9," ","yellow") + pix(25,10," ","yellow") + pix(25,11," ","yellow") + pix(25,17," ","yellow") + pix(25,18," ","yellow") + elseif screenStage>10.4 and screenStage<10.6 then + pix(25,8," ","yellow") + pix(25,9," ","yellow") + pix(25,10," ","yellow") + pix(24,11," ","yellow") + pix(24,12," ","yellow") + pix(24,13," ","yellow") + pix(24,14," ","yellow") + pix(23,15," ","yellow") + pix(23,16," ","yellow") + pix(23,17," ","yellow") + pix(23,18," ","yellow") + humanPixY = 18 + drawHumanPix() + elseif screenStage>10.6 and screenStage<10.8 then + pix(25,8," ","yellow") + pix(25,9," ","yellow") + pix(24,10," ","yellow") + pix(24,11," ","yellow") + pix(24,12," ","yellow") + pix(23,13," ","yellow") + pix(23,14," ","yellow") + pix(23,15," ","yellow") + pix(22,16," ","yellow") + pix(22,17," ","yellow") + pix(22,18," ","yellow") + humanPixY = 18 + drawHumanPix() + elseif screenStage>10.8 and screenStage<11 then + pix(25,8," ","yellow") + pix(24,9," ","yellow") + pix(24,10," ","yellow") + pix(23,11," ","yellow") + pix(23,12," ","yellow") + pix(22,13," ","yellow") + pix(22,14," ","yellow") + pix(21,15," ","yellow") + pix(21,16," ","yellow") + pix(20,17," ","yellow") + pix(20,18," ","yellow") + humanPixY = 18 + drawHumanPix() + elseif screenStage>11.9 and screenStage<12 then + pix(1,6," ","yellow") + elseif screenStage>12 and screenStage<12.1 then + pix(1,6," ") + pix(3,6," ","yellow") + elseif screenStage>12.1 and screenStage<12.2 then + pix(3,6," ") + pix(5,6," ","yellow") + elseif screenStage>12.2 and screenStage<12.3 then + pix(5,6," ") + pix(7,6," ","yellow") + elseif screenStage>12.3 and screenStage<12.4 then + pix(7,6," ") + pix(9,6," ","yellow") + elseif screenStage>12.4 and screenStage<12.5 then + pix(9,6," ") + pix(11,6," ","yellow") + elseif screenStage>12.5 and screenStage<12.6 then + pix(11,6," ") + pix(13,6," ","yellow") + elseif screenStage>12.6 and screenStage<12.7 then + pix(13,6," ") + pix(15,6," ","yellow") + elseif screenStage>12.7 and screenStage<12.8 then + term.setBackgroundColour(colours.black) + for i= 5, h-1 do + term.setCursorPos(15,i) + write(" ") + end + humanPixY=18 + drawHumanPix() + elseif screenStage>13 and screenStage<13.1 then + shipPixX= -16 + drawShipPix() + elseif screenStage>13 and screenStage<13.1 then + delShipPix() + shipPixX= -15 + drawShipPix() + elseif screenStage>13.1 and screenStage<13.2 then + delShipPix() + shipPixX= -12 + drawShipPix() + elseif screenStage>13.2 and screenStage<13.3 then + delShipPix() + shipPixX= -9 + drawShipPix() + elseif screenStage>13.2 and screenStage<13.3 then + delShipPix() + shipPixX= -6 + drawShipPix() + elseif screenStage>13.3 and screenStage<13.4 then + delShipPix() + shipPixX= -3 + drawShipPix() + elseif screenStage>13.4 and screenStage<13.5 then + delShipPix() + shipPixX= 0 + drawShipPix() + elseif screenStage>13.6 and screenStage<13.7 then + delShipPix() + shipPixX= 3 + drawShipPix() + elseif screenStage>13.8 and screenStage<13.9 then + delShipPix() + shipPixX= 6 + drawShipPix() + elseif screenStage>13.9 and screenStage<14 then + delShipPix() + shipPixX= 9 + drawShipPix() + elseif screenStage>14.1 and screenStage<14.2 then + delShipPix() + shipPixX= 12 + drawShipPix() + elseif screenStage>14.2 and screenStage<14.3 then + delShipPix() + shipPixX= 15 + drawShipPix() + elseif screenStage>14.3 and screenStage<14.4 then + delShipPix() + shipPixX= 18 + drawShipPix() + elseif screenStage>14.4 and screenStage<14.5 then + delShipPix() + shipPixX= 21 + drawShipPix() + elseif screenStage>14.5 and screenStage<14.6 then + delShipPix() + shipPixX= 24 + drawShipPix() + elseif screenStage>14.6 and screenStage<14.7 then + delShipPix() + shipPixX= 27 + drawShipPix() + elseif screenStage>14.7 and screenStage<14.8 then + delShipPix() + shipPixX= 30 + drawShipPix() + elseif screenStage>14.8 and screenStage<14.9 then + delShipPix() + shipPixX= 33 + drawShipPix() + elseif screenStage>14.9 and screenStage<15 then + delShipPix() + shipPixX= 36 + drawShipPix() + elseif screenStage>15 and screenStage<15.1 then + delShipPix() + shipPixX= 39 + drawShipPix() + elseif screenStage>15.1 and screenStage<15.2 then + delShipPix() + shipPixX= 41 + drawShipPix() + elseif screenStage>15.2 and screenStage<15.3 then + delShipPix() + shipPixX= 44 + drawShipPix() + elseif screenStage>15.3 and screenStage<15.4 then + delShipPix() + shipPixX= 47 + drawShipPix() + elseif screenStage>15.4 and screenStage<15.5 then + delShipPix() + shipPixX= 50 + drawShipPix() + elseif screenStage>15.5 and screenStage<15.6 then + delShipPix() + elseif screenStage>16 and screenStage<16.9 then + humanPixY=18 + delHumanPix() + line1() + line2() + line3() + line4() + line5() + elseif screenStage>17 and screenStage<22 then + term.setCursorPos((w/2)-6,10) + write("by FredTHead") + term.setCursorPos((w/2)-13,12) + write("WSAD or arrow keys to move") + term.setCursorPos((w/2)-6,13) + write("SPACE to fire") + term.setCursorPos((w/2)-4,14) + write("P to quit") + term.setCursorPos((w/2)-8,16) + write("Fire when ready") + elseif screenStage>22.1 and screenStage <27 then + introHighScoreTable() + elseif screenStage>27 then + term.setBackgroundColour(colours.black) + for i = 2,h-1 do + term.setCursorPos(1,i) + write(string.rep(" ",w-1)) + end + screenStage=0 + end + + screenStage=screenStage+0.1 + screenTimer=os.startTimer(0.025) + end + end +end + +w,h =term.getSize() +if term.isColour() and w==51 then + initVariables() + startScreen() +else + term.clear() + term.setCursorPos(1,1) + print("I'm sorry, Protector requires an Advanced Computer to run") + print(" ") +end \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/goldrunner b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/goldrunner new file mode 100644 index 0000000000..2aeaf40720 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/goldrunner @@ -0,0 +1,1314 @@ +--[[ + Gold Runner + Inspired by the game by Doug Smith + + Written by: Nitrogen Fingers +]]-- + +w,h = term.getSize() +if not term.isColour() then + printError("Requires an Advanced Computer") + return +end + + +running = true +started = false +nextLevel = false + +inLevelSelect = false +inLevelEditor = false +local levelEditName = nil +local hexnums = { [10] = "a", [11] = "b", [12] = "c", [13] = "d", [14] = "e" , [15] = "f" } + +titleLoaded = false +local menSel = "none" +local titleOptions = { "New Game", "Select Level", "Create Level", "Quit" } +local inGameOptions = { "Restart", "Edit Level", "Back to Title", "Quit" } +local levelEditOptions = { "Save", "Play Level", "Save and Exit", "Discard and Exit" } +local menIndex = 1 + +local maxnamelen = 14 + +local drawOffsetX = 1 +local drawOffsetY = 0 + +local map = {} +local goldMap = {} +local blockTimers = {} +local blockIntv = 5 + +local monks = {} +local monkTimer = -1 +local monkSpawnIntv = 3 +local monkTrapIntv = blockIntv/2 + +local goldCount = 0 +local maxGoldCount = 0 +local playerLives = 3 +local playerScore = 0 +local plspawnX = 0 +local plspawnY = 0 + +local plX = 0 +local plY = 0 +local pfalling = false +local moveTimer = -1 +local shootTimer = -1 +local spawnTimer = -1 +local moveIntv = 0.15 + +local exX = 0 +local exY = 0 + +local levelList = {} +local currentLevel = 1 +local levelLot = 1 + +local titleLevel = { + " "; + " dddddddddddc "; + " 4 c "; + " 4 4 c "; + " bbbbbbc bcbbbb "; + " b 4 b c c "; + " bbbbb c 4 dd 0 4 c 4 "; + " bbcb bbb bbbbc "; + " c c "; + " c ddd c eb"; + " dddddc bcb cbbbbb"; + " c c c bbbb"; + "b4 c 4c bb44b"; + "bbb c 4 e bbbcbbbbbbbbbbbbb"; + "bbbbbbbbbbbbbbc 4 cbbbbb 4 bbbb"; + "bbbbbbfff44fbbc 4 cbbbbbbb cbbbbbbb bbbbb"; + "bbbbffffbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 4 bbbbbbb"; + "bbbffbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb5 bbbbbbbbb"; +} + +local function parseValue(x, y, lchar) +if tonumber(lchar, 16) then + lchar = math.pow(2, tonumber(lchar,16)) + + if lchar == colours.blue then + map[y][x] = 0 + elseif lchar == colours.brown then + map[y][x] = 'H' + elseif lchar == colours.yellow then + goldMap[y][x] = 1 + goldCount = goldCount + 1 + elseif lchar == colours.orange then + map[y][x] = 'V' + elseif lchar == colours.green then + map[y][x] = '-' + elseif lchar == colours.lightGrey then + map[y][x] = 'h' + elseif lchar == colours.grey then + map[y][x] = '#' + elseif lchar == colours.white then + plX = x + plspawnX = x + plY = y + plspawnY = y + elseif lchar == colours.lime then + exX = x + exY = y + elseif lchar == colours.red then + table.insert(monks, { + --X and Y, clear enough + x = x, y = y; + --Where they spawn when they die + spawnX = x, spawnY = y; + -- Any gold they're carring- it's a 1 in 5 + gold = false; + -- Whether or not they're falling + falling = false; + -- Timer if they're dead to respawn + dead = nil; + --Whether or not the monk has just spawned + justSpawned = true; + --Whether or not the monk has just escaped + justEscaped = false; + -- Current aim- it's "up", "down", "across" or "none" + behaviour = "none"; + -- The desired x position to travel to, when one is necessary. + desX = nil; + -- The escape timer + trapped = nil; + }) + end + end +end + +local function loadMap(_sPath) + if not fs.exists(_sPath) then return false end + map = {} + goldMap = {} + monks = {} + goldCount = 0 + + local file = fs.open(_sPath, "r") + local line = file:readLine() + while line do + goldMap[#map+1] = {} + map[#map+1] = {} + for i=1,math.min(#line,49) do + local lchar = string.sub(line,i,i) + parseValue(i, #map, lchar) + end + if #map == 18 then break end + line = file:readLine() + end + file:close() + maxGoldCount = goldCount + titleLoaded = false + return true +end + +--When something moves or something needs to be drawn, we +--just change the appropriate tile with this method. +local function updateMap(x,y) + term.setCursorPos(x + drawOffsetX, y + drawOffsetY) + term.setBackgroundColour(colours.black) + if plX == x and plY == y and map[y][x] ~= 0 then + term.setTextColour(colours.white) + if map[y][x] == 1 then term.setBackgroundColour(colours.lightBlue) + elseif map[y][x] == "V" then term.setBackgroundColour(colours.blue) end + term.write("&") + elseif map[y][x] == 'H' then + term.setTextColour(colours.brown) + term.write("H") + --Level Editor stuff + elseif map[y][x] == 'h' and (goldCount == 0 or inLevelEditor) then + if inLevelEditor then term.setTextColour(colours.lightGrey) + else term.setTextColour(colours.brown) end + term.write("H") + elseif map[y][x] == '&' and inLevelEditor then + term.setTextColour(colours.pink) + term.write('&') + elseif map[y][x] == 'V' then + term.setBackgroundColour(colours.blue) + if inLevelEditor then + term.setTextColour(colours.orange) + term.write("V") + else + term.write(" ") + end + elseif map[y][x] == '-' then + term.setTextColour(colours.brown) + term.write(map[y][x]) + elseif map[y][x] == '#' then + term.setBackgroundColour(colours.grey) + term.write(" ") + elseif type(map[y][x]) == "number" then + local uchar = ' ' + if map[y][x] == 3 then + term.setBackgroundColour(colours.lightBlue) + elseif map[y][x] == 2 and goldMap[y][x] == 1 then + term.setTextColour(colours.yellow) + uchar = '$' + elseif map[y][x] == 1 then + term.setBackgroundColour(colours.lightBlue) + elseif map[y][x] == 0 then + term.setBackgroundColour(colours.blue) + end + term.write(uchar) + elseif goldMap[y][x] == 1 then + term.setTextColour(colours.yellow) + term.write("$") + elseif exX == x and exY == y and (goldCount == 0 or inLevelEditor) then + term.setTextColour(colours.lime) + term.write("@") + else + term.write(" ") + end +end + +--It's silly to iterate through all monks when drawing tiles, so +--we do it separately. +local function drawMonk(monk) + term.setCursorPos(monk.x + drawOffsetX, monk.y + drawOffsetY) + if monk.justSpawned then term.setTextColour(colours.pink) + else term.setTextColour(colours.red) end + if map[monk.y][monk.x] == 1 then term.setBackgroundColour(colours.lightBlue) + elseif map[monk.y][monk.x] == "V" then term.setBackgroundColour(colours.blue) + else term.setBackgroundColour(colours.black) end + term.write("&") +end + +--Draws the map for the first time. It barely changes, so we really +--only call this the once. +local function drawMap() + term.setBackgroundColour(colours.black) + term.clear() + for y=1,#map do + for x=1,49 do + updateMap(x,y) + end + end + for _,monk in pairs(monks) do drawMonk(monk)end +end + +--When all coins have been collected, we add in invisble ladders and +--the end game portal. +local function drawEndgameMap() + for y=1,#map do + for x=1,49 do + if map[y][x] == 'h' or (exX == x and exY == y) then + updateMap(x,y) + end + end + end +end + +--Sets the map back to defaults, so we can start afresh +local function resetMap() + goldCount = maxGoldCount + for i=1,#goldMap do + for j=1,49 do + if goldMap[i][j] == 0 then goldMap[i][j] = 1 end + end + end + for _,monk in pairs(monks) do + monk.justSpawned = true + monk.dead = nil + monk.trapped = nil + monk.justEscaped = false + monk.falling = false + monk.behaviour = "none" + monk.x = monk.spawnX + monk.y = monk.spawnY + end + + for _,timer in pairs(blockTimers) do + map[timer.y][timer.x] = 0 + end + blockTimers = {} + plX = plspawnX + plY = plspawnY + + moveTimer = -1 + shootTimer = -1 + spawnTimer = -1 + monkTimer = -1 + pfalling = false +end + +--Draws the HUD. This also rarely changes, so we update it when something happens. +local function drawHUD() + term.setCursorPos(2,19) + term.setBackgroundColour(colours.black) + term.clearLine() + term.setTextColour(colours.blue) + term.write("Score: ") + term.setTextColour(colours.yellow) + term.write(string.rep("0", 5-math.floor(math.log(playerScore + 1,10))) + ..playerScore) + term.setTextColour(colours.yellow) + term.setCursorPos(25 - #levelList[currentLevel]/2, 19) + term.write(levelList[currentLevel]) + local lstr = "Men: " + term.setCursorPos(50 - #lstr - math.floor(math.log(playerLives,10)), 19) + term.setTextColour(colours.blue) + term.write(lstr) + term.setTextColour(colours.yellow) + term.write(playerLives.."") +end + +--Draws the list of levels known, with respect to screen +--real estate +local function drawLevelList() + local minLev = ((levelLot-1) * 10 + 1) + local maxLev = minLev + math.min(10, #levelList - (levelLot-1) * 10) - 1 + + term.setCursorPos(7, 2) + term.setBackgroundColour(colours.black) + term.clearLine() + for j = 1,49 do updateMap(j,2) end + + term.setBackgroundColour(colours.black) + term.setTextColour(colours.white) + term.setCursorPos(7, 2) + local msg = "Levels "..minLev.." to "..maxLev.." of "..#levelList + term.write(msg) + + term.setTextColour(colours.yellow) + term.setCursorPos(4, 2) + if levelLot > 1 then term.write("<-") + else term.write(" ") end + + term.setCursorPos(8 + #msg, 2) + if maxLev < #levelList then term.write("->") + else term.write(" ") end + + for i = 1,10 do + term.setCursorPos(1, 3+i) + for j = 1,49 do updateMap(j,3+i) end + term.setTextColour(colours.white) + term.setBackgroundColour(colours.black) + term.setCursorPos(17, 3+i) + if i + (levelLot-1)*10 - 1 < maxLev then + term.write(levelList[10 * (levelLot-1) + i]) + end + end +end + +--Loads up and draws up the title screen, for a nice +--intro to Gold Runner +local function loadTitleScreen() + map = {} + goldMap = {} + monks = {} + goldCount = 0 + for i=1,#titleLevel do + local line = titleLevel[i] + goldMap[#map+1] = {} + map[#map+1] = {} + for i=1,math.min(#line,49) do + local lchar = string.sub(line,i,i) + parseValue(i, #map, lchar) + end + if #map == 18 then break end + end + maxGoldCount = goldCount + + drawMap() + term.setCursorPos(1,19) + term.setBackgroundColour(colours.blue) + term.clearLine() + + menIndex = 1 + titleLoaded = true +end + +--Opens an in-game menu to display a series of options. +local function inGameMenu(menuList) + menIndex = 1 + + local squareTop,squareBottom = 4,6 + #menuList * 2 + local squareSize = 0 + for i=1,#menuList do squareSize = math.max(squareSize, #menuList[i] + 6) end + + for y=squareTop,squareBottom do + term.setCursorPos(w/2 - squareSize/2, y) + term.setBackgroundColour(colours.lightBlue) + term.write(string.rep(" ", squareSize)) + + if y ~= squareTop and y ~= squareBottom then + term.setCursorPos(w/2 - squareSize/2 + 1, y) + term.setBackgroundColour(colours.black) + term.write(string.rep(" ", squareSize - 2)) + end + + if y ~= squareTop and y ~= squareBottom and y % 2 == 0 then + local opt = menuList[(y - squareTop) / 2] + term.setCursorPos(w/2 - #opt/2, y) + term.setTextColour(colours.white) + term.write(opt) + end + end + + local p1 = nil + repeat + for i=1,#menuList do + term.setBackgroundColour(colours.black) + term.setTextColour(colours.yellow) + if i == menIndex then + term.setCursorPos(w/2 - squareSize/2 + 1, squareTop + i * 2) + term.write(">") + term.setCursorPos(w/2 + squareSize/2 - 2, squareTop + i * 2) + term.write("<") + else + term.setCursorPos(w/2 - squareSize/2 + 1, squareTop + i * 2) + term.write(" ") + term.setCursorPos(w/2 + squareSize/2 - 2, squareTop + i * 2) + term.write(" ") + end + end + _,p1 = os.pullEvent("key") + + if p1 == keys.up and menIndex > 1 then menIndex = menIndex - 1 + elseif p1 == keys.down and menIndex < #menuList then menIndex = menIndex + 1 end + until p1 == keys.enter + + return menuList[menIndex] +end + +--Checks to see if any given desired move is legal. Monks and players both use this. +local function isLegalMove(initX,initY,finX,finY) + if finY < 1 or finY > #map or finX < 1 or finX > 49 then + return false + end + + if map[finY][finX] ~= 0 and map[finY][finX] ~= '#' then + --This reports 'self moves' as being illegal, but that's fine + for _,monk in pairs(monks) do + if monk.x == finX and monk.y == finY then return false end + end + + if finY == initY-1 and (map[initY][initX] == "H" or (map[initY][initX] == "h" and goldCount == 0)) + then return true + elseif finY == initY+1 and (map[finY][finX] == "H" or (map[finY][finX] == "h" and goldCount == 0) + or (type(map[finY][finX]) == "number" and map[finY][finX] > 0) or map[finY][finX] == nil or + map[finY][finX] == "V" or map[finY][finX] == "-" or (map[finY][finX] == 'h' and goldCount ~= 0)) + then return true + elseif finX == initX-1 or finX == initX+1 then + return true + end + end +end + +--Moves the player to a given step. +local function movePlayer(x,y,ignoreLegal) + if not ignoreLegal and not isLegalMove(plX,plY,x,y) then return false end + + local ox = plX + local oy = plY + plX = x + plY = y + + updateMap(ox,oy) + updateMap(x,y) + if goldMap[y][x] == 1 then + goldMap[y][x] = 0 + goldCount = goldCount - 1 + playerScore = playerScore + 5 + if started then drawHUD() end + if (goldCount == 0) then + drawEndgameMap() + end + elseif exX == plX and exY == plY and goldCount == 0 then + started = false + nextLevel = true + end + + pfalling = (y < #map and map[y][x] ~= '-' and map[y][x] ~= 'H' and not (map[y][x] == 'h' and goldCount == 0) + and (map[y+1][x] == nil or map[y+1][x] == "V" or map[y+1][x] == 2 or map[y+1][x] == '-')) + if (y < #map and map[y+1][x] == 'h' and goldCount ~= 0) then pfalling = true end + for _,monk in pairs(monks) do + if monk.x == plX and monk.y == plY + 1 then pfalling = false break end + end + + return true +end + +local function updateMonks() + for _,monk in pairs(monks) do + --Absolute first step- if he's trapped or dead, he's going nowhere + if monk.trapped or monk.dead then + --If he's just spawned he takes a second to orient himself + elseif monk.justSpawned then + monk.justSpawned = false + --We evaluate their falling behaviour here (as freed monks CAN stand on air) + monk.falling = (monk.y < #map and map[monk.y][monk.x] ~= '-' and map[monk.y][monk.x] ~= "H" and not + (map[monk.y][monk.x] == 'h' and goldCount == 0) and (map[monk.y+1][monk.x] == nil or map[monk.y+1][monk.x] == "V" or + map[monk.y+1][monk.x] == 2 or map[monk.y+1][monk.x] == '-') and type(map[monk.y][monk.x] ~= "number")) + for _,omonk in pairs(monks) do + if omonk.x == monk.x and omonk.y == monk.y + 1 then monk.falling = false break end + end + if monk.x == plX and monk.y == plY + 1 then monk.falling = false end + --Then we consider if he's just gotten out of a hole + elseif monk.justEscaped then + monk.justEscaped = false + --He tries the player side first + local playerSide = (plX-monk.x) / math.abs(plX-monk.x) + if isLegalMove(monk.x, monk.y, monk.x + playerSide, monk.y) then + monk.x = monk.x + playerSide + updateMap(monk.x - playerSide, monk.y) + elseif isLegalMove(monk.x, monk.y, monk.x - playerSide, monk.y) then + monk.x = monk.x - playerSide + updateMap(monk.x + playerSide, monk.y) + end + drawMonk(monk) + --Then we evaluate falling + elseif monk.falling then + monk.behaviour = "none" + monk.y = monk.y + 1 + updateMap(monk.x, monk.y-1) + drawMonk(monk) + monk.desX = nil + if type(map[monk.y][monk.x]) == "number" then + monk.trapped = os.startTimer(monkTrapIntv) + monk.falling = false + else + monk.falling = (monk.y < #map and map[monk.y][monk.x] ~= '-' and map[monk.y][monk.x] ~= "H" and not + (map[monk.y][monk.x] == 'h' and goldCount == 0) and (map[monk.y+1][monk.x] == nil or map[monk.y+1][monk.x] == "V" or + map[monk.y+1][monk.x] == 2 or map[monk.y+1][monk.x] == '-') and type(map[monk.y][monk.x] ~= "number")) + for _,omonk in pairs(monks) do + if omonk.x == monk.x and omonk.y == monk.y + 1 then monk.falling = false break end + end + if monk.x == plX and monk.y == plY + 1 then monk.falling = false end + if monk.justEscaped then monk.falling = false end + end + --If he's on his feet and not trapped, he's allowed to think about where to move + elseif monk.y == plY then + --Is the monk on the same level as the player? How lucky! They'll just walk towards him + monk.desX = plX + monk.behaviour = "across" + --Y difference takes precedence over X (as in the original, makes them a bit smarter) + elseif monk.y < plY then + --If they can move up, they will + if isLegalMove(monk.x,monk.y,monk.x,monk.y+1) and not monk.justEscaped then + monk.y = monk.y+1 + updateMap(monk.x, monk.y-1) + drawMonk(monk) + monk.desX = nil + --A down move can lead to a fall, so we check if they're now falling. + monk.falling = (monk.y < #map and map[monk.y][monk.x] ~= '-' and map[monk.y][monk.x] ~= "H" and not + (map[monk.y][monk.x] == 'h' and goldCount == 0) and (map[monk.y+1][monk.x] == nil or map[monk.y+1][monk.x] == "V" or + map[monk.y+1][monk.x] == 2 or map[monk.y+1][monk.x] == '-') and type(map[monk.y][monk.x] ~= "number")) + for _,omonk in pairs(monks) do + if omonk.x == monk.x and omonk.y == monk.y + 1 then monk.falling = false break end + end + if monk.x == plX and monk.y == plY + 1 then monk.falling = false end + --Otherwise, it's off to the nearest ladder, monkey bars or perilous ledge to jump off + --assuming they haven't found one already + elseif monk.desX == nil then + if monk.behaviour ~= "down" then monk.desX = nil end + monk.behaviour = "down" + monk.desX = nil + local cmLeft = true + local cmRight = true + --We try to find the nearest by searching alternate left and right at variable distance + for i=1,math.max(monk.x - 1, 49 - monk.x) do + if monk.x-i > 0 and cmLeft then + --If a wall blocks the monks path, they can't keep going left or right + cmLeft = map[monk.y][monk.x-i] ~= 0 + --But if it's all clear, they look for something to climb/jump down + if cmLeft and (map[monk.y+1][monk.x-i] == "H" or (map[monk.y+1][monk.x-i] == 'h' and goldCount == 0) + or map[monk.y+1][monk.x-i] == nil or map[monk.y][monk.x-i] == '-') then + monk.desX = monk.x-i + break + end + end + if monk.x+i < 50 and cmRight then + --If a wall blocks the monks path, they can't keep going left or right + cmRight = map[monk.y][monk.x+i] ~= 0 + --But if it's all clear, they look for something to climb/jump down + if cmRight and (map[monk.y+1][monk.x+i] == "H" or (map[monk.y+1][monk.x+i] == 'h' and goldCount == 0) + or map[monk.y+1][monk.x+i] == nil or map[monk.y][monk.x+i] == '-') then + monk.desX = monk.x+i + break + end + end + end + end + elseif monk.y > plY then + if monk.behaviour ~= "up" then monk.desX = nil end + monk.behaviour = "up" + --Same deal again- try moving up first + if isLegalMove(monk.x,monk.y,monk.x,monk.y-1) then + monk.y = monk.y-1 + updateMap(monk.x, monk.y+1) + drawMonk(monk) + monk.desX = nil + --You can never move up and start falling, so we don't bother to check + --Otherwise they need ladders to climb up + elseif monk.desX == nil then + monk.behaviour = "up" + monk.desX = nil + local cmLeft = true + local cmRight = true + --We try to find the nearest by searching alternate left and right at variable distance + for i=1,math.max(monk.x - 1, 49 - monk.x) do + if monk.x-i > 0 and cmLeft then + --If a wall blocks the monks path or a pit is in the way, they can't keep going left or right + cmLeft = map[monk.y][monk.x-i] ~= 0 and (monk.y == #map or map[monk.y+1][monk.x-i] ~= nil + or map[monk.y][monk.x-i] == '-' or map[monk.y][monk.x-i] == "H" or (map[monk.y][monk.x-i] == "h" + and goldCount == 0)) + --But if it's all clear, they look for a ladder + if cmLeft and (map[monk.y][monk.x-i] == "H" or (map[monk.y][monk.x-i] == 'h' and goldCount == 0)) then + monk.desX = monk.x-i + break + end + end + if monk.x+i < 50 and cmRight then + cmRight = map[monk.y][monk.x+i] ~= 0 and (monk.y == #map or map[monk.y+1][monk.x+i] ~= nil + or map[monk.y][monk.x+i] == '-' or map[monk.y][monk.x+i] == "H" or (map[monk.y][monk.x+i] == "h" + and goldCount == 0)) + if cmRight and (map[monk.y][monk.x+i] == "H" or (map[monk.y][monk.x+i] == 'h' and goldCount == 0)) then + monk.desX = monk.x+i + break + end + end + end + end + end + + if not (monk.trapped or monk.dead) then + --Has the monk decided on moving left or right? If so we try to move him + if monk.desX and not monk.falling then + local mdir = monk.desX - monk.x + local mdir = mdir / math.abs(mdir) + if isLegalMove(monk.x,monk.y,monk.x+mdir,monk.y) then + monk.x = monk.x + mdir + updateMap(monk.x - mdir, monk.y) + drawMonk(monk) + else + --This allows re-evaluations if they get stuck- not ideal but good enough + monk.desX = nil + end + end + monk.falling = (monk.y < #map and map[monk.y][monk.x] ~= '-' and map[monk.y][monk.x] ~= "H" and not + (map[monk.y][monk.x] == 'h' and goldCount == 0) and (map[monk.y+1][monk.x] == nil or map[monk.y+1][monk.x] == "V" or + map[monk.y+1][monk.x] == 2 or map[monk.y+1][monk.x] == '-') and type(map[monk.y][monk.x] ~= "number")) + for _,omonk in pairs(monks) do + if omonk.x == monk.x and omonk.y == monk.y + 1 then monk.falling = false break end + end + if monk.x == plX and monk.y == plY + 1 then monk.falling = false end + --We have caught and killed the player + if monk.x == plX and monk.y == plY and spawnTimer == -1 then + spawnTimer = os.startTimer(2) + end + end + end +end + +local function updateBlockTimer(tid) + local remAt = nil + for i,v in ipairs(blockTimers) do + if v.timer == tid then + if map[v.y][v.x] == 3 then + for _,monk in pairs(monks) do + if monk.x == v.x and monk.y == v.y-1 then + map[v.y][v.x] = 0 + remAt = i + break + end + end + if not remAt then + map[v.y][v.x] = 2 + v.timer = os.startTimer(blockIntv) + end + elseif map[v.y][v.x] == 2 then + map[v.y][v.x] = 1 + v.timer = os.startTimer(0.1) + elseif map[v.y][v.x] == 1 then + map[v.y][v.x] = 0 + --If the player is caught in a block, he dies + if v.y == plY and v.x == plX then + spawnTimer = os.startTimer(2) + end + for _,monk in pairs(monks) do + if monk.x == v.x and monk.y == v.y then + monk.dead = os.startTimer(monkSpawnIntv) + --Easiest way to get them out of the way rather than evaluation + monk.x = -1 + monk.y = -1 + monk.trapped = nil + end + end + remAt = i + end + updateMap(v.x,v.y) + break + end + end + if remAt then table.remove(blockTimers,remAt) end +end + +local function shootBlock(x,y) + if y <= #map and map[y][x] == 0 and (map[y-1][x] == nil + or map[y-1][x] == 2 or (map[y-1][x] == 'h' and goldCount > 0)) then + map[y][x] = 3 + table.insert(blockTimers, {x = x; y = y; timer = os.startTimer(0.1);} ) + updateMap(x,y) + end +end + +local function handleEvents() + local id,p1,p2,p3 = os.pullEvent() + + if id == "key" then + --Menu Handling + if p1 == keys.up then + if menIndex > 1 then menIndex = menIndex - 1 end + elseif p1 == keys.down then + if inLevelSelect then + if menIndex < math.min(10, #levelList - (levelLot-1)*10) then + menIndex = menIndex + 1 + end + elseif menIndex < #titleOptions then menIndex = menIndex + 1 end + elseif p1 == keys.left and inLevelSelect and levelLot > 1 then + levelLot = levelLot - 1 + drawLevelList() + elseif p1 == keys.right and inLevelSelect and levelLot * 10 < #levelList then + levelLot = levelLot + 1 + drawLevelList() + end + + --Game Handling + if p1 == keys.a and moveTimer == -1 and spawnTimer == -1 then + movePlayer(plX-1,plY) + moveTimer = os.startTimer(moveIntv) + elseif p1 == keys.d and moveTimer == -1 and spawnTimer == -1 then + movePlayer(plX+1,plY) + moveTimer = os.startTimer(moveIntv) + elseif p1 == keys.w and moveTimer == -1 and spawnTimer == -1 then + movePlayer(plX,plY-1) + moveTimer = os.startTimer(moveIntv) + elseif p1 == keys.s and moveTimer == -1 and spawnTimer == -1 then + movePlayer(plX,plY+1) + moveTimer = os.startTimer(moveIntv) + elseif p1 == keys.q and shootTimer == -1 and not pfalling and spawnTimer == -1 then + shootBlock(plX-1,plY+1) + shootTimer = os.startTimer(moveIntv) + elseif p1 == keys.e and shootTimer == -1 and not pfalling and spawnTimer == -1 then + shootBlock(plX+1,plY+1) + shootTimer = os.startTimer(moveIntv) + elseif p1 == keys.space and started then + started = false + elseif p1 == keys.enter then + if not started then + if inLevelSelect then + currentLevel = menIndex + (levelLot - 1) * 10 + menSel = "New Game" + else + menSel = titleOptions[menIndex] + end + else + started = false + menIndex = 1 + menSel = inGameMenu(inGameOptions) + end + end + elseif id == "timer" then + if p1 == shootTimer then shootTimer = -1 + elseif p1 == spawnTimer then + started = false + elseif p1 == moveTimer then + if pfalling then + movePlayer(plX,plY+1) + moveTimer = os.startTimer(moveIntv) + else + moveTimer = -1 + end + elseif p1 == monkTimer then + updateMonks() + monkTimer = os.startTimer(moveIntv * 2) + elseif updateBlockTimer(p1) then + else + for _,monk in pairs(monks) do + if p1 == monk.trapped then + --You can stand on a monk to force them to be killed- so we check for that + --along with being buried in tunnels, etc. + local stillTrapped = map[monk.y-1][monk.x] == 0 or (plX == monk.x and plY == monk.y-1) + for _,omonk in pairs(monks) do + if omonk.x == monk.x and omonk.y == monk.y-1 then + stillTrapped = true + break + end + end + --Perpetually trapped monks will try to excape much more quickly + if stillTrapped then + --This needs to be tweaked + monk.trapped = os.startTimer(0.75) + else + --When free, they head in your general direction, re-evaluate later + monk.y = monk.y - 1 + --This is necessary to stop 'double jumping' + monk.desX = nil + monk.trapped = nil + monk.behaviour = "none" + monk.justEscaped = true + + updateMap(monk.x, monk.y+1) + drawMonk(monk) + end + break + elseif p1 == monk.dead then + --Same deal- you can camp spawn + local stillDead = plX == monk.spawnX and plY == monk.spawnY + for _,omonk in pairs(monks) do + if omonk.x == monk.spawnX and omonk.y == monk.spawnY then + stillDead = true + break + end + end + --They'll spawn the second you give them the chance + if stillDead then + monk.dead = os.startTimer(0.5) + else + monk.x = monk.spawnX + monk.y = monk.spawnY + monk.dead = nil + monk.justSpawned = true + monk.behaviour = "none" + drawMonk(monk) + break + end + end + end + end + end +end + +--[[ Level Editor ]]-- + +local pallette = { { t = colours.black, b = colours.blue, s = " ", n = "Solid Ground", v = 0 }, + { t = colours.orange, b = colours.blue, s = "V", n = "Trap Ground", v = "V" }, + { t = colours.grey, b = colours.grey, s = " ", n = "Cement Ground", v = "#" }, + { t = colours.brown, b = colours.black, s = "H", n = "Ladder", v = "H" }, + { t = colours.brown, b = colours.black, s = "-", n = "Monkey Bars", v = "-" }, + { t = colours.white, b = colours.black, s = "&", n = "Player Spawn", v = "player" }, + { t = colours.red, b = colours.black, s = "&", n = "Mad Monk", v = "&" }, + { t = colours.yellow, b = colours.black, s = "$", n = "Gold", v = "$" }, + { t = colours.lightGrey, b = colours.black, s = "H", n = "Hidden Ladder", v = "h" }, + { t = colours.lime, b = colours.black, s = "@", n = "Exit Portal", v = "@" }, + { t = colours.red, b = colours.black, s = "ERASE", n = "Eraser", v = nil } } +local brushType = 1 + +local function getHexOf(colour) + if not colour or not tonumber(colour) then + return " " + end + local value = math.log(colour)/math.log(2) + if value > 9 then + value = hexnums[value] + end + return value +end + +local function drawFooter() + for i=1,h-1 do + if i % 2 == 0 then term.setBackgroundColour(colours.grey) + else term.setBackgroundColour(colours.yellow) end + term.setCursorPos(1,i) + term.write(" ") + term.setCursorPos(w,i) + term.write(" ") + end + + term.setBackgroundColour(colours.black) + term.setTextColour(colours.blue) + term.setCursorPos(2,h) + term.clearLine() + term.write("Editor Mode: ") + term.setTextColour(colours.yellow) + term.write(levelEditName) + local msg = "Tool: "..pallette[brushType].n.." "..pallette[brushType].s + term.setCursorPos(w - #msg - 1, 19) + term.setTextColour(colours.blue) + term.write("Tool: ") + term.setTextColour(colours.yellow) + term.write(pallette[brushType].n.." ") + term.setBackgroundColour(pallette[brushType].b) + term.setTextColour(pallette[brushType].t) + term.write(pallette[brushType].s) +end + +local function drawPallette(xpos,ypos) + local xdim = 7 + local ydim = 5 + local left = xpos + local top = ypos + if xpos + xdim > w then left = left + (w - xpos - xdim) end + if ypos + ydim > h then top = top + (h - ypos - ydim) end + + --There's no easy way to do this... so we draw it manually :( + for i=0,4 do + term.setCursorPos(left, top + i) + term.setBackgroundColour(colours.black) + term.setTextColour(colours.red) + if i == 0 or i == 4 then term.write("*-----*") + else term.write("* *") end + end + + for i=1,#pallette-1 do + local ypl = 1 + local xmv = i + if i > 5 then ypl = 2 xmv = i - 5 end + + term.setCursorPos(left + xmv, top+ypl) + term.setBackgroundColour(pallette[i].b) + term.setTextColour(pallette[i].t) + term.write(pallette[i].s) + end + + term.setCursorPos(left + 1, top + 3) + term.setBackgroundColour(colours.red) + term.setTextColour(colours.black) + term.write("ERASE") + + local _,button,x,y = os.pullEvent("mouse_click") + + if button == 1 then + if y == top + 1 and x > left and x < left + 6 then + brushType = x-left + elseif y == top + 2 and x > left and x < left + 6 then + brushType = x-left+5 + elseif y == top + 3 and x > left and x < left + 6 then + brushType = 11 + end + end + + for y = top,top+ydim do + for x = left,left+xdim do + --Not sure why the -2 is necessary + if map[y+drawOffsetY] then updateMap(x-2,y+drawOffsetY) end + end + end + drawFooter() + return +end + +local function saveCurrentMap(path) + local file = io.open(shell.resolve(".").."/levels/"..path, "w") + if not file then return false end + + drawMap() + drawFooter() + local msg = "Saving.." + term.setCursorPos(w/2-#msg/2, 5) + term.setTextColour(colours.yellow) + term.setBackgroundColour(colours.blue) + term.write(msg) + term.setCursorPos(w/2-9, 6) + term.setBackgroundColour(colours.red) + term.write(string.rep(" ", 18)) + term.setCursorPos(w/2-9,6) + term.setBackgroundColour(colours.lime) + + for y=1,#map do + local xstr = "" + for x=1,49 do + --This again... + if map[y][x] == 0 then xstr = xstr..getHexOf(colours.blue) + elseif map[y][x] == "V" then xstr = xstr..getHexOf(colours.orange) + elseif map[y][x] == "#" then xstr = xstr..getHexOf(colours.grey) + elseif map[y][x] == "H" then xstr = xstr..getHexOf(colours.brown) + elseif map[y][x] == "h" then xstr = xstr..getHexOf(colours.lightGrey) + elseif map[y][x] == "-" then xstr = xstr..getHexOf(colours.green) + elseif map[y][x] == "&" then xstr = xstr..getHexOf(colours.red) + elseif goldMap[y][x] == 1 then xstr = xstr..getHexOf(colours.yellow) + elseif plX == x and plY == y then xstr = xstr..getHexOf(colours.white) + elseif exX == x and exY == y then xstr = xstr..getHexOf(colours.lime) + else xstr = xstr.." " + end + end + file:write(xstr.."\n") + term.write(" ") + sleep(0) + end + file:close() + return true +end + +local function runLevelEditor() + inLevelEditor = true + term.setBackgroundColour(colours.black) + term.clear() + if not fs.exists(shell.resolve(".").."/levels/"..levelEditName) then + map = {} + goldMap = {} + monks = {} + for i=1,18 do map[i] = {} goldMap[i] = {} end + plX = 2 + plY = 2 + plspawnX = plX + plspawnY = plY + exX = 48 + exY = 17 + else + loadMap(shell.resolve(".").."/levels/"..levelEditName) + for _,monk in pairs(monks) do + map[monk.y][monk.x] = "&" + end + monks = {} + end + + drawMap() + drawFooter() + + while inLevelEditor do + local id,button,x,y = os.pullEvent() + if id == "mouse_click" or id == "mouse_drag" then + if button == 2 then + drawPallette(x,y) + elseif x > drawOffsetX and x <= 49 + drawOffsetX and y > drawOffsetY and y <= 18 + drawOffsetY then + if pallette[brushType].v == "player" then + local ox = plX + local oy = plY + if plX == exX and plY == exY then + exX = ox + exY = oy + end + plX = x - drawOffsetX + plY = y - drawOffsetY + map[plY][plX] = nil + goldMap[plY][plX] = nil + updateMap(ox,oy) + elseif pallette[brushType].v == "@" then + local ox = exX + local oy = exY + if plX == exX and plY == exY then + plX = ox + plY = oy + end + exX = x - drawOffsetX + exY = y - drawOffsetY + map[plY][plX] = nil + goldMap[plY][plX] = nil + updateMap(ox,oy) + elseif pallette[brushType].v == "$" then + goldMap[y-drawOffsetY][x-drawOffsetX] = 1 + map[y-drawOffsetY][x-drawOffsetX] = nil + elseif pallette[brushType].v == nil then + map[y-drawOffsetY][x-drawOffsetX] = nil + goldMap[y-drawOffsetY][x-drawOffsetX] = nil + else + map[y-drawOffsetY][x-drawOffsetX] = pallette[brushType].v + goldMap[y-drawOffsetY][x-drawOffsetX] = nil + --term.setCursorPos(1,19) + --print("At "..(x-drawOffsetX)..", "..(y-drawOffsetY).." have placed "..pallette[brushType].v) + end + updateMap(x-drawOffsetX, y-drawOffsetY) + end + elseif id == "mouse_scroll" then + brushType = brushType + button + if brushType == 0 then brushType = #pallette + elseif brushType > #pallette then brushType = 1 end + drawFooter() + elseif id == "key" and button == keys.enter then + menSel = inGameMenu(levelEditOptions) + if menSel == "Save" then + saveCurrentMap(levelEditName) + drawMap() + drawFooter() + elseif menSel == "Save and Exit" then + saveCurrentMap(levelEditName) + menSel = "none" + inLevelEditor = false + elseif menSel == "Discard and Exit" then + menSel = "none" + inLevelEditor = false + elseif menSel == "Play Level" then + saveCurrentMap(levelEditName) + inLevelEditor = false + end + end + end +end + + +local function runLevelSelect() + if not titleLoaded then + loadTitleScreen() + monkTimer = os.startTimer(moveIntv * 1.5) + else + drawMap() + drawEndgameMap() + term.setCursorPos(1,19) + term.setBackgroundColour(colours.blue) + term.clearLine() + end + drawLevelList() + + menSel = "none" + repeat + handleEvents() + + term.setBackgroundColour(colours.black) + term.setTextColour(colours.yellow) + for i=1,10 do + term.setCursorPos(16,3+i) + if i == menIndex then + term.write(">") + else + term.write(" ") + end + end + until menSel ~= "none" + inLevelSelect = false + menSel = "New Game" +end + +local function runTitle() + loadTitleScreen() + term.setCursorPos(15,3) + term.setTextColour(colours.red) + term.setBackgroundColour(colours.black) + term.write("Gold Runner") + term.setCursorPos(16,4) + term.write("By Nitrogen Fingers") + + term.setTextColour(colours.white) + for i=1,#titleOptions do + term.setCursorPos(19, 5 + (i*2)) + term.write(titleOptions[i]) + end + + term.setCursorPos(16, 7) + term.setTextColour(colours.yellow) + term.write("->") + + menSel = "none" + monkTimer = os.startTimer(moveIntv * 1.5) + + repeat + handleEvents() + + term.setBackgroundColour(colours.black) + term.setTextColour(colours.yellow) + for i=1,#titleOptions do + term.setCursorPos(16, 5 + i*2) + if menIndex == i then term.write("->") + else term.write(" ") end + end + until menSel ~= "none" +end + +local function playLevel() + loadMap(shell.resolve(".").."/levels/"..levelList[currentLevel]) + running = true + while running do + drawMap() + drawHUD() + os.pullEvent("key") + movePlayer(plX,plY,true) + + monkTimer = os.startTimer(moveIntv * 1.5) + moveTimer = os.startTimer(moveIntv) + shootTimer = -1 + spawnTimer = -1 + + started = true + while started do + handleEvents() + end + + if menSel == "Quit" or menSel == "Back to Title" or menSel == "Edit Level" then + running = false + return + end + menSel = "none" + + if nextLevel then + if currentLevel == #levelList then + started = false + running = false + break + else + currentLevel = currentLevel + 1 + playerLives = playerLives + 1 + resetMap() + loadMap(shell.resolve(".").."/levels/"..levelList[currentLevel]) + end + nextLevel = false + else + playerLives = playerLives-1 + if playerLives > 0 then resetMap() + else + running = false + end + end + end + + if nextLevel then + local msg = "All levels defeated, Gold Runner!" + term.setBackgroundColour(colours.black) + term.setTextColour(colours.lime) + term.setCursorPos(25 - #msg/2, 2) + term.write(msg) + else + local msg = "Game over!" + term.setBackgroundColour(colours.black) + term.setTextColour(colours.red) + term.setCursorPos(25 - #msg/2, 2) + term.write(msg) + end + currentLevel = 1 + sleep(2) +end + +term.clear() +if not fs.exists(shell.resolve(".").."/levels") then + error("Level directory not present!") +end +levelList = fs.list(shell.resolve(".").."/levels") +if #levelList == 0 then + error("Level directory is empty!") +end + +runTitle() +menIndex = 1 + +while menSel ~= "Quit" do + if menSel == "Select Level" then + inLevelSelect = true + runLevelSelect() + elseif menSel == "New Game" then + playerLives = 3 + playerScore = 0 + playLevel() + elseif menSel == "Create Level" then + --This is a bit lazy... well it's all been a bit lazy :P + drawMap() + term.setCursorPos(1,19) + term.setBackgroundColour(colours.blue) + term.clearLine() + + term.setCursorPos(16,10) + term.setBackgroundColour(colours.black) + term.setTextColour(colours.white) + term.write("Enter level name:") + term.setTextColour(colours.lime) + term.setCursorPos(17,11) + term.setCursorBlink(true) + local levelName = "" + + local id,p1 + repeat + id,p1 = os.pullEvent() + if id == "key" and p1 == keys.backspace then + levelName = string.sub(levelName, 1, #levelName - 1) + elseif id == "timer" and p1 == monkTimer then + updateMonks() + monkTimer = os.startTimer(moveIntv * 2) + elseif id == "char" and #levelName < 14 then + levelName = levelName..p1 + end + term.setTextColour(colours.lime) + term.setCursorPos(17,11) + term.write(levelName..string.rep(" ",14 - #levelName)) + term.setCursorPos(17 + #levelName ,11) + until id == "key" and p1 == keys.enter and #levelName > 0 + + term.setCursorBlink(false) + levelEditName = levelName + runLevelEditor() + + if menSel == "Play Level" then + currentLevel = nil + levelList = fs.list(shell.resolve(".").."/levels") + for num,name in pairs(levelList) do + if name == levelName then + currentLevel = num + break + end + end + menSel = "New Game" + else + menSel = "none" + end + elseif menSel == "Edit Level" then + levelEditName = levelList[currentLevel] + runLevelEditor() + term.setBackgroundColour(colours.black) + term.clear() + + if menSel == "Play Level" then + menSel = "New Game" + else + menSel = "none" + end + elseif menSel == "none" or menSel == "Back to Title" then + runTitle() + end + menIndex = 1 +end + +term.setBackgroundColour(colours.black) +shell.run("clear") +term.setTextColour(colours.white) +print("Thanks for playing Gold Runner!") diff --git a/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/01_welcome b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/01_welcome new file mode 100644 index 0000000000..9be5a826be --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/01_welcome @@ -0,0 +1,18 @@ + + 5 + bb8bb + b8b + 8 + 4 ddddddddddddddd 8 + bbbbcbbbbbbb 8 + bbbc 8 + c 4 4 8 + c bbbbbbb + bcbbbbbbbb bbbbbbb + c 44 bbbb + c 4 bbbb bbb + 4bbbbbbbbbbc bb 4 4 bb + bbbbbbbbbb c bbbcbbbbb bb +b bbb c c bb +bbb c 4 4 c 0 bbb +bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb diff --git a/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/02_coalmine b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/02_coalmine new file mode 100644 index 0000000000..219a502e2c --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/02_coalmine @@ -0,0 +1,18 @@ +bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +b 0 b +bbbb bb dddd cb b +b bbbb e cbb 4 4 cb 44 b +bbbbbbbbbbbbbbbbbbbbcbbbbbbb bbbbbbbbbbbb7777b +b b dddddddd c b +b b c cbb b +b 44 b c cbbbb 4 4 4 b +bbbbbbbbbbbbcbbbbbbbbbbbbbbbbbbbbbbbb7b7bbbbb7bbb +bbbbbb4 bbbbcb4 4 4bb4 4bbbbbbbbbbb7bbb7b7b77b +b bb bbbcbbbbbbbbbbbbbbbbb b +b c 7777777777b +b c dd ddddddddddddcb7777777777b +bbbbbbbbbbbbbbbbbb cbbb cbbbb 5 b +bbbbbbbbbbbbbbbbbb cbbb c7b 8bbbbbb +b cbbb c7b 8 4 4 b +b 4 4 4 4 4 cb cbb c7b cbbbbbbbb +bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb777777777777b diff --git a/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/03_seeker b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/03_seeker new file mode 100644 index 0000000000..49cff842df --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/03_seeker @@ -0,0 +1,18 @@ + + + 5 + 4 4 8 4 4 + bbcbb 8 bbbbbbcb + c 8 c + c 4 dddd 4 e 4 dddddd 8 c + bbbb bbbbcbbbbbb 8 c + c 4 8 e 4 c + c bbbbbbbbcbb c + c c c + 4 c 4 0 4 c 4 c + bbbcbbbbbbbbb bbbbcbbbbbbbc + c c + c c + c c +b c 4 4 4 4 c b +bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb diff --git a/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/04_fortress b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/04_fortress new file mode 100644 index 0000000000..461eceeab1 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/04_fortress @@ -0,0 +1,18 @@ + +7 4 547 0 +7ccbbbb7 cbbbbb +7cc77777 cb 4 4 +7cc cb7777 +7cc7 +7cc7 +7cc 4 dddd dddd dddd +7cc77 c777b777c c c c7 +7cc7c77 dddddd 4 4 c 7c c e c c7 +7cc c bbbbcbbbbc 777777777777777777 +7777c7 7 c c +7c77c 77 c c4 4 dddddddd 4 4 +7c c 77 4 bbbbc7b7b7b7b7c bbbbbc +7c c 7bb c c c +77c777c777b 4 c c c +7ece 7c 7bbbbbb c c e c +7777777777777777777777777777777777777777777777777 diff --git a/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/05_caged b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/05_caged new file mode 100644 index 0000000000..b286f0ae3f --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/05_caged @@ -0,0 +1,18 @@ + + 88888888888 + e 4 cb8 8bc 4 e + cbbbbbbcdddddddcb8 8bcdddddddcbbbbbbc + cb bc b8 8b cb bc + cb bc b8 8b cb bc + cb bc b8 8b cb bc + cbb4 bc b8 5 8b cbb 4 bc + cbbbbbbc b8dddd dddd8b cbbbbbbc + cb bcddddddddb8 4 4 8bddddddddcb bc + cb b cbcbbbbbbbbbcbc b bc + cb b cbc cbc b bc + cb 4ebb cbc e cbc bbe4 bc + cbbbbbb cb77777777777bc bbbbbbc + c b c c b c + c b c c b c + c 4b c 0 c b4 c +bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb diff --git a/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/06_flowers b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/06_flowers new file mode 100644 index 0000000000..db0c50e4b0 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/06_flowers @@ -0,0 +1,18 @@ + ddddddd +c bbbbcddddddd dddc d 4ed dddd +c bbe44ebb c 4 c bbb c 4 c +c 4777 7b7777b7 bbbb bbbb c +c bb c +c 4 dd 4 4 4c +c 4 e bb dd 4 4ddd bb bb bc +c bbb bb b c 4 0 bb c +c 4 c bb 4 4 c +cb 4 bbb c bb c +cbb bb dddd d 4d c 4 c +cbbbb bbc bb c 4 cd 5 dc +c 4 4 4 c 4 c bbb c c +c bb 4 bb c bb 4 c 444 c +c 4 4 4 4c bb cbbbc 444 c +c bbb cbbc c 444 c +c c c c +bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb diff --git a/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/07_pyramid b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/07_pyramid new file mode 100644 index 0000000000..6f861bfc15 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/07_pyramid @@ -0,0 +1,18 @@ + 8 bbbb 0 b b + 8b bbbb 8bbb 5 b + 8b 8bbb 8 b + 8bbbbbbbbbbbbbbbbbbbb + 8 + 8 ddd b + 8 c bbbbbbbbbcb + 8 c 4bbb cb +b 8ddd ddddddd e dddddddc bbb4 cb +bbbbbbbbb c bbbbbbb c 4bbb cb +b b c bbb444bbb c bbb4 cb +b 4 b c bbb4 4bbb c 4bbb cb +b bbb b c bbb4 4bbb c 7777 cb +b 4 4 b c bbb4 4bbb cbbbbbbbbbbbbbb +b bbbbb b c bbb bbb c b +bddd4dddb c bbbbbbbbbbbbbbbbbbb c cbbb b +b4 b 4 c e e c cbbb 4444 b +bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb diff --git a/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/08_cavein b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/08_cavein new file mode 100644 index 0000000000..f7cfd6e11e --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/08_cavein @@ -0,0 +1,18 @@ +bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbb +b 8 8 8 8 8 b 4 5 b4 e 4 b +b 888 8 8 8 bbbbbbbcbbbbc 8 bbbbbbbcbbbbbb +b 8 8 8 88888 bbbb4bbcbbbbbbbbbb bbb c b +b e c bbbb bbb c b +bbbbbbbbbbbbbbbb77bcbbbbbbbbbbbcbbbb bbb c 4 4b +b 4 4 bb bbc cb44b bbb c b +bbbbbbbbbbbbb bc cbbbbbbbb c b +b 4 4 b4 4 4bc c 4bbb4 c b +bbbbbbbbbbbbb4 4 4bc bbbcbbbbbbbbbbbbbbbbbccbb +b 4 4 b bc bbbc e 4 cbbccbb +bbbbbbbbbbbbbbbcbbbc 4bbbc cbbbbbbbbbbcbbccbb +b c cbbbbb c4 c bbbbbbcbbccbb +b c cbbbbbcbbbbbcbbbbbb44 cbbccbb +b 4 4 cbbbbbbbcbbbbbcbbbbbcbbbb4bbbbbbbbccbb +bbbbbbbbbbbbbbbbbbbce cbb4bbc 0 cc4b +bb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +7777777777777777777777777777777777777777777777777 diff --git a/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/09_skyislands b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/09_skyislands new file mode 100644 index 0000000000..b666d74f0c --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/09_skyislands @@ -0,0 +1,18 @@ + + 05 ddddd 4e4 + 4ddddddd cc bbcbb + bbbc 4 ccddddd 4 c + 4 c 4 dddddcc bbbb c 4 + bcbb 4 4 cc b44bddd 4 c4 + c4 bbbbbbbb cc bbbb bbbbbbbb + bbcb 4 4 ccdddddddd b e 44b + c 4 4 cc b cbbbbb + c ddd cc 4 b4c b + bbbb bbbbbbbbbbbb cc cbbb bbcddc b + bbbbbbbbbbbb cc 4 c4 b c c b + b4 c ddddcc bbbbbbb b4c4bc4b + c bbbbbbc 4b cc bbbbbbbb + c4b4 ec b cc 4 + bbbbbbbbbbbb cc +7 e 4 cc 4 7 +7b7b7b7b7b7b7b7b7b7b7b7b77b7b7b7b7b7b7b7b7b7b7b77 diff --git a/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/10_convert b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/10_convert new file mode 100644 index 0000000000..14a5f70eab --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/goldrunner/levels/10_convert @@ -0,0 +1,16 @@ + 8 + 8 4 e +777 8 7777c7777777 + 77 8 77 c + 77 8 77 c +4e 777 8 4777 c 4 +77c7777 8 7777c777c7777777 + c 77 8 77 c + c4e 77c77 c 4 +c777c c 7c77c777 +c c c +c c 4 e c +c c7777777c777777c77777c77 +c c c +c c 0 c +7777777777777777777777777777 diff --git a/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/npaintpro/3dprint b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/npaintpro/3dprint new file mode 100644 index 0000000000..be40631ff0 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/npaintpro/3dprint @@ -0,0 +1,119 @@ +--[[ + 3D Print + A printing program for use with NPaintPro + + By NitrogenFingers +]]-- + +local activeCommander = -1 +local operatingPrint = false + +--Whether or not the print can be ended +local function endPrint() + operatingPrint = false +end + +--The list of all commands the printer can be ginve +local commandList = { + ["FW"] = { turtle.dig, turtle.forward }; + ["BK"] = turtle.back; + ["UP"] = { turtle.digUp, turtle.up }; + ["DW"] = { turtle.digDown, turtle.down }; + ["TL"] = turtle.turnLeft; + ["TR"] = turtle.turnRight; + ["TU"] = { turtle.turnLeft, turtle.turnLeft }; + ["PF"] = { turtle.dig, turtle.place }; + ["PU"] = { turtle.digUp, turtle.placeUp }; + ["PD"] = { turtle.digDown, turtle.placeDown }; + ["SS"] = turtle.select; + ["RF"] = turtle.refuel; + ["DE"] = endPrint; +} + +--Splits a string according to a pattern into a table +local function split(str, pattern) + local t = { } + local fpat = "(.-)" .. pattern + local last_end = 1 + local s, e, cap = str:find(fpat, 1) + while s do + if s ~= 1 or cap ~= "" then + table.insert(t,cap) + end + last_end = e+1 + s, e, cap = str:find(fpat, last_end) + end + if last_end <= #str then + cap = str:sub(last_end) + table.insert(t, cap) + end + return t +end + +--Listens for any instructions given referring to identification and activation. Once activated, the mode exits. +local function respondToQuery() + while true do + print("Listening for ACT/ID query") + local id,key = rednet.receive() + print("Received : "..key) + + if key == "$3DPRINT IDENTIFY" then + print("Requested Identification") + rednet.send(id, "$3DPRINT IDACK "..os.getComputerLabel()) + + elseif key == "$3DPRINT ACTIVATE" then + print("Requested Activation") + activeCommander = id + rednet.send(id, "$3DPRINT ACTACK") + break + end + end +end + +--Performs the print. Follows instrutions as given, and responds as necessary +local function performPrint() + operatingPrint = true + while operatingPrint do + local id,msg = rednet.receive() + print("Command : "..msg) + + if id == activeCommander and string.find(msg, "$PC") == 1 then + local cmds = split(msg, " ") + + --It's a bit of a hack, but those are the 2 methods required for a refuel + if turtle.getFuelLevel() == 0 and cmds[2] ~= "SS" and cmds[2] ~= "RF" then + rednet.send(id, "$3DPRINT OOF") + elseif (tonumber(cmds[3])) and turtle.getItemCount(tonumber(cmds[3])) == 0 and + turtle.getFuelLevel() ~= 0 then + rednet.send(id, "$3DPRINT DEP") + else + if cmds[2] == "RF" then cmds[3] = "64" end + if type(commandList[cmds[2]]) == "function" then + commandList[cmds[2]](tonumber(cmds[3])) + elseif type(commandList[cmds[2]]) == "table" then + for i=1,#commandList[cmds[2]] do + commandList[cmds[2]][i](tonumber(cmds[3])) + end + end + + rednet.send(activeCommander, "$3DPRINT ACK") + end + end + end +end + +rednet.open("right") +term.clear() +term.setCursorPos(1,1) +if not os.getComputerLabel() then + term.write("Name this computer:") + os.setComputerLabel(io.read()) +end +print("3D printer online") + +while true do + --Wait for activation + respondToQuery() + --Perform the print + performPrint() +end \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/npaintpro/gameutils b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/npaintpro/gameutils new file mode 100644 index 0000000000..8a029e83b3 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/npaintpro/gameutils @@ -0,0 +1,615 @@ +--[[ + GameUtil + An API for drawing sprites and animations made in NPaintPro + By NitrogenFingers +]]-- + + +--The back buffer. Initialized as nil +local backbuffer = nil +--The bounds of the terminal the back buffer displays to +local tw,th = nil, nil + +--[[Constructs a new buffer. This must be done before the buffer can written to. + Params: terminal:?table = The function table to draw to a screen. By default (nil) this refers + to the native terminal, but monitor displays can be passed through as well: + local leftMonitor = peripherals.wrap("left") + initializeBuffer(leftMonitor) + Returns:boolean = True if the buffer was successfully initialized; false otherwise +]]-- +function initializeBuffer(terminal) + if not terminal then terminal = term end + if not terminal.getSize then + error("Parameter cannot be used to initialize the backbuffer.") + end + if not terminal.isColour() then + error("Parameter does not represent an advanced computer.") + end + + tw,th = terminal.getSize() + backbuffer = { } + for y=1,th do + backbuffer[y] = { } + end + return true +end + +--[[Will clear the buffer and reset to nil, or to a colour if provided + Params: colour:?number = The colour to set the back buffer to + Returns:nil +]]-- +function clearBuffer(colour) + if not backbuffer then + error("Back buffer not yet initialized!") + end + + for y=1,#backbuffer do + backbuffer[y] = { } + if colour then + for x=1,tw do + backbuffer[y][x] = colour + end + end + end +end + +--[[Draws the given entity to the back buffer + Params: entity:table = the entity to draw to the buffer + Returns:nil +]]-- +function writeToBuffer(entity) + if not backbuffer then + error("Back buffer not yet initialized!") + end + + local image = nil + if entity.type == "animation" then + image = entity.frames[entity.currentFrame] + else + image = entity.image + end + + for y=1,image.dimensions.height do + for x=1,image.dimensions.width do + if image[y][x] then + local xpos,ypos = x,y + if entity.mirror.x then xpos = image.dimensions.width - x + 1 end + if entity.mirror.y then ypos = image.dimensions.height - y + 1 end + + --If the YPos doesn't exist, no need to loop through the rest of X! + --Don't you love optimization? + if not backbuffer[entity.y + ypos - 1] then break end + + backbuffer[entity.y + ypos - 1][entity.x + xpos - 1] = image[y][x] + end + end + end +end + +--[[Draws the contents of the buffer to the screen. This will not clear the screen or the buffer. + Params: terminal:table = the terminal to draw to + Returns:nil +]]-- +function drawBuffer(terminal) + if not backbuffer then + error("Back buffer not yet initialized!") + end + if not terminal then terminal = term end + if not terminal.setCursorPos or not terminal.setBackgroundColour or not terminal.write then + error("Parameter cannot be used to initialize the backbuffer.") + end + if not terminal.isColour() then + error("Parameter does not represent an advanced computer.") + end + + for y=1,math.min(#backbuffer, th) do + for x=1,tw do + if backbuffer[y][x] then + terminal.setCursorPos(x,y) + terminal.setBackgroundColour(backbuffer[y][x]) + terminal.write(" ") + end + end + end +end + +--[[Converts a hex digit into a colour value + Params: hex:?string = the hex digit to be converted + Returns:string A colour value corresponding to the hex, or nil if the character is invalid +]]-- +local function getColourOf(hex) + local value = tonumber(hex, 16) + if not value then return nil end + value = math.pow(2,value) + return value +end + +--[[Converts every pixel of one colour in a given sprite to another colour + Use for "reskinning". Uses OO function. + Params: self:sprite = the sprite to reskin + oldcol:number = the colour to replace + newcol:number = the new colour + Returns:nil +]]-- +local function repaintS(self, oldcol, newcol) + for y=1,self.image.bounds.height do + for x=1, self.image.bounds.width do + if self.image[y][x] == oldcol then + self.image[y][x] = newcol + end + end + end +end + +--[[Converts every pixel of one colour in a given animation to another colour + Use for "reskinning". Uses OO function. + Params: self:animation = the animation to reskin + oldcol:number = the colour to replace + newcol:number = the new colour + Returns:nil +]]-- +local function repaintA(self, oldcol, newcol) + for f=1,#self.frames do + print(self.frames[f].bounds) + for y=1,self.frames[f].bounds.height do + for x=1, self.frames[f].bounds.width do + if self.frames[f][y][x] == oldcol then + self.frames[f][y][x] = newcol + end + end + end + end +end + +--[[Prints the sprite on the screen + Params: self:sprite = the sprite to draw + Returns:nil +]]-- +local function drawS(self) + local image = self.image + + for y=1,image.dimensions.height do + for x=1,image.dimensions.width do + if image[y][x] then + local xpos,ypos = x,y + if self.mirror.x then xpos = image.dimensions.width - x + 1 end + if self.mirror.y then ypos = image.dimensions.height - y + 1 end + + term.setBackgroundColour(image[y][x]) + term.setCursorPos(self.x + xpos - 1, self.y + ypos - 1) + term.write(" ") + end + end + end +end + +--[[Prints the current frame of the animation on screen + Params: self:anim = the animation to draw + frame:?number = the specific frame to draw (default self.currentFrame) + Returns:nil +]]-- +local function drawA(self, frame) + if not frame then frame = self.currentFrame end + local image = self.frames[frame] + + for y=1,image.dimensions.height do + for x=1,image.dimensions.width do + if image[y][x] then + local xpos,ypos = x,y + if self.mirror.x then xpos = image.dimensions.width - x + 1 end + if self.mirror.y then ypos = image.dimensions.height - y + 1 end + + term.setBackgroundColour(image[y][x]) + term.setCursorPos(self.x + xpos - 1, self.y + ypos - 1) + term.write(" ") + end + end + end +end + +--[[Checks the animation timer provided to see whether or not the animation needs to be updated. + If so, it makes the necessary change. + Params: self:animation = the animation to be updated + timerID:number = the ID of the most recent timer event + Returns:bool = true if the animation was update; false otherwise +]]-- +local function updateA(self, timerID) + if self.timerID and timerID and self.timerID == timerID then + self.currentFrame = self.currentFrame + 1 + if self.currentFrame > self.upperBound then + self.currentFrame = self.lowerBound + end + return true + else + return false + end +end + +--[[Moves immediately to the next frame in the sequence, as though an update had been called. + Params: self:animation = the animation to update + Returns:nil +]]-- +local function nextA(self) + self.currentFrame = self.currentFrame + 1 + if self.currentFrame > self.upperBound then + self.currentFrame = self.lowerBound + end +end + +--[[Moves immediately to the previous frame in the sequence + Params: self:animation = the animation to update + Returns:nil +]]-- +local function previousA(self) + self.currentFrame = self.currentFrame - 1 + if self.currentFrame < self.lowerBound then + self.currentFrame = self.upperBound + end +end + +--[[A simple debug function that displays the outline of the bounds + on a given shape. Useful when testing collision detection or other game + features. + Params: entity:table = the bounded entity to represent + colour:?number = the colour to draw the rectangle (default red) + Returns:nil +]]-- +local function drawBounds(entity, colour) + if not colour then colour = colours.red end + local image = nil + if entity.type == "animation" then image = entity.frames[entity.currentFrame] + else image = entity.image end + + term.setBackgroundColour(colour) + + corners = { + topleft = { x = entity.x + image.bounds.x - 1, y = entity.y + image.bounds.y - 1 }; + topright = { x = entity.x + image.bounds.x + image.bounds.width - 2, y = entity.y + image.bounds.y - 1 }; + botleft = { x = entity.x + image.bounds.x - 1, y = entity.y + image.bounds.y + image.bounds.height - 2 }; + botright = { x = entity.x + image.bounds.x + image.bounds.width - 2, y = entity.y + image.bounds.y + image.bounds.height - 2 }; + } + + term.setCursorPos(corners.topleft.x, corners.topleft.y) + term.write(" ") + term.setCursorPos(corners.topright.x, corners.topright.y) + term.write(" ") + term.setCursorPos(corners.botleft.x, corners.botleft.y) + term.write(" ") + term.setCursorPos(corners.botright.x, corners.botright.y) + term.write(" ") +end + +--[[Creates a bounding rectangle object. Used in drawing the bounds and the rCollidesWith methods + Params: self:table = the entity to create the rectangle + Returns:table = the left, right, top and bottom edges of the rectangle +]]-- +local function createRectangle(entity) + local image = nil + if entity.type == "animation" then + image = entity.frames[entity.currentFrame] + else + image = entity.image + end + --Note that the origin is always 1, so we subtract 1 for every absolute coordinate we have to test. + return { + left = entity.x + image.bounds.x - 1; + right = entity.x + image.bounds.x + image.bounds.width - 2; + top = entity.y + image.bounds.y - 1; + bottom = entity.y + image.bounds.y + image.bounds.height - 2; + } +end + +--[[Performs a rectangle collision with another given entity. Entity can be of sprite or animation + type (also true of the self). Bases collision using a least squared approach (rectangle precision). + Params: self:sprite,animation = the object in question of the testing + other:sprite,animation = the other object tested for collision + Returns:bool = true if bounding rectangle intersect is true; false otherwse +]]-- +local function rCollidesWith(self, other) + --First we construct the rectangles + local img1C, img2C = createRectangle(self), createRectangle(other) + + --We then determine the "relative position" , in terms of which is farther left or right + leftmost,rightmost,topmost,botmost = nil,nil,nil,nil + if img1C.left < img2C.left then + leftmost = img1C + rightmost = img2C + else + leftmost = img2C + rightmost = img1C + end + if img1C.top < img2C.top then + topmost = img1C + botmost = img2C + else + topmost = img2C + botmost = img1C + end + + --Then we determine the distance between the "extreme" edges- + --distance between leftmost/right edge and rightmost/left edge + --distance between topmost/bottom edge and bottommost/top edge + local xdist = rightmost.left - leftmost.right + local ydist = botmost.top - topmost.bottom + + --If both are negative, our rectangles intersect! + return xdist <= 0 and ydist <= 0 +end + +--[[Performs a pixel collision test on another given entity. Either entity can be of sprite or animation + type. This is done coarsegrain-finegrain, we first find the intersection between the rectangles + (if there is one), and then test the space within that intersection for any intersecting pixels. + Params: self:sprite,animation = the object in question of the testing + other:sprite,animation = the other object being tested for collision + Returns:?number,?number: The X and Y position in which the collision occurred. +]]-- +local function pCollidesWith(self, other) + --Identically to rCollidesWith, we create our rectangles... + local img1C, img2C = createRectangle(self), createRectangle(other) + --We'll also need the images to compare pixels later + local img1, img2 = nil,nil + if self.type == "animation" then img1 = self.frames[self.currentFrame] + else img1 = self.image end + if other.type == "animation" then img2 = other.frames[other.currentFrame] + else img2 = other.image end + + --...then we position them... + leftmost,rightmost,topmost,botmost = nil,nil,nil,nil + --We also keep track of which is left and which is right- it doesn't matter in a rectangle + --collision but it does in a pixel collision. + img1T,img2T = {},{} + + if img1C.left < img2C.left then + leftmost = img1C + rightmost = img2C + img1T.left = true + else + leftmost = img2C + rightmost = img1C + img2T.left = true + end + if img1C.top < img2C.top then + topmost = img1C + botmost = img2C + img1T.top = true + else + topmost = img2C + botmost = img1C + img2T.top = true + end + + --...and we again find the distances between the extreme edges. + local xdist = rightmost.left - leftmost.right + local ydist = botmost.top - topmost.bottom + + --If these distances are > 0 then we stop- no need to go any farther. + if xdist > 0 or ydist > 0 then return false end + + + for x = rightmost.left, rightmost.left + math.abs(xdist) do + for y = botmost.top, botmost.top + math.abs(ydist) do + --We know a collision has occurred if a pixel is occupied by both images. We do this by + --first transforming the coordinates based on which rectangle is which, then testing if a + --pixel is at that point + -- The leftmost and topmost takes the distance on x and y and removes the upper component + -- The rightmost and bottommost, being the farther extremes, compare from 1 upwards + local testX,testY = 1,1 + if img1T.left then testX = x - img1C.left + 1 + else testX = x - img1C.left + 1 end + if img1T.top then testY = y - img1C.top + 1 + else testY = y - img1C.top + 1 end + + local occupy1 = img1[testY + img1.bounds.y-1][testX + img1.bounds.x-1] ~= nil + + if img2T.left then testX = x - img2C.left + 1 + else testX = x - img2C.left + 1 end + if img2T.top then testY = y - img2C.top + 1 + else testY = y - img2C.top + 1 end + + local occupy2 = img2[testY + img2.bounds.y-1][testX + img2.bounds.x-1] ~= nil + + if occupy1 and occupy2 then return true end + end + end + --If the looop terminates without returning, then no pixels overlap + return false +end + +--[[Moves the sprite or animation to the specified coordinates. This performs the auto-centering, so + the user doesn't have to worry about adjusting for the bounds of the shape. Recommended for absolute + positioning operations (as relative direct access to the X will have unexpected results!) + Params: self:table = the animation or sprite to move + x:number = the new x position + y:number = the new y position +]]-- +local function moveTo(self, x, y) + local image = nil + if self.type == "animation" then + image = self.frames[self.currentFrame] + else + image = self.image + end + + self.x = x - image.bounds.x + 1 + self.y = y - image.bounds.y + 1 +end + +--[[ + Sprites Fields: +x:number = the x position of the sprite in the world +y:number = the y position of the sprite in the world +image:table = a table of the image. Indexed by height, a series of sub-tables, each entry being a pixel + at [y][x]. It also contains: + bounds:table = + x:number = the relative x position of the bounding rectangle + y:number = the relative y position of the bounding rectangle + width:number = the width of the bounding rectangle + height:number = the height of the bounding rectangle + dimensions:table = + width = the width of the entire image in pixels + height = the height of the entire image in pixels + +mirror:table = + x:bool = whether or not the image is mirrored on the X axis + y:bool = whether or not the image is mirrored on the Y axis +repaint:function = see repaintS (above) +rCollidesWith:function = see rCollidesWith (above) +pCollidesWith:function = see pCollidesWith (above) +draw:function = see drawS (above) +]]-- + +--[[Loads a new sprite into a table, and returns it to the user. + Params: path:string = the absolute path to the desired sprite + x:number = the initial X position of the sprite + y:number = the initial Y position of the sprite +]]-- +function loadSprite(path, x, y) + local sprite = { + type = "sprite", + x = x, + y = y, + image = { }, + mirror = { x = false, y = false } + } + + if fs.exists(path) then + local file = io.open(path, "r" ) + local leftX, rightX = math.huge, 0 + local topY, botY = nil,nil + + local lcount = 0 + for line in file:lines() do + lcount = lcount+1 + table.insert(sprite.image, {}) + for i=1,#line do + if string.sub(line, i, i) ~= " " then + leftX = math.min(leftX, i) + rightX = math.max(rightX, i) + if not topY then topY = lcount end + botY = lcount + end + sprite.image[#sprite.image][i] = getColourOf(string.sub(line,i,i)) + end + end + file:close() + + sprite.image.bounds = { + x = leftX, + width = rightX - leftX + 1, + y = topY, + height = botY - topY + 1 + } + sprite.image.dimensions = { + width = rightX, + height = botY + } + + sprite.x = sprite.x - leftX + 1 + sprite.y = sprite.y - topY + 1 + + sprite.repaint = repaintS + sprite.rCollidesWith = rCollidesWith + sprite.pCollidesWith = pCollidesWith + sprite.draw = drawS + sprite.moveTo = moveTo + return sprite + else + error(path.." not found!") + end +end + +--Animations contain + --Everything a sprite contains, but the image is a series of frames, not just one image + --An timerID that tracks the last animation + --An upper and lower bound on the active animation + --An update method that takes a timer event and updates the animation if necessary + +--[[ + +]]-- +function loadAnimation(path, x, y, currentFrame) + local anim = { + type = "animation", + x = x, + y = y, + frames = { }, + mirror = { x = false, y = false }, + currentFrame = currentFrame + } + + table.insert(anim.frames, { }) + if fs.exists(path) then + local file = io.open(path, "r") + local leftX, rightX = math.huge, 0 + local topY, botY = nil,nil + + local lcount = 0 + for line in file:lines() do + lcount = lcount+1 + local cFrame = #anim.frames + if line == "~" then + anim.frames[cFrame].bounds = { + x = leftX, + y = topY, + width = rightX - leftX + 1, + height = botY - topY + 1 + } + anim.frames[cFrame].dimensions = { + width = rightX, + height = botY + } + table.insert(anim.frames, { }) + leftX, rightX = math.huge, 0 + topY, botY = nil,nil + lcount = 0 + else + table.insert(anim.frames[cFrame], {}) + for i=1,#line do + if string.sub(line, i, i) ~= " " then + leftX = math.min(leftX, i) + rightX = math.max(rightX, i) + if not topY then topY = lcount end + botY = lcount + end + anim.frames[cFrame][#anim.frames[cFrame]] [i] = getColourOf(string.sub(line,i,i)) + end + end + end + file:close() + local cFrame = #anim.frames + anim.frames[cFrame].bounds = { + x = leftX, + y = topY, + width = rightX - leftX + 1, + height = botY - topY + 1 + } + anim.frames[cFrame].dimensions = { + width = rightX, + height = botY + } + anim.x = anim.x - leftX + 1 + anim.y = anim.y - topY + 1 + + if not currentFrame or type(currentFrame) ~= "number" or currentFrame < 1 or + currentFrame > #anim.frames then + anim.currentFrame = 1 + end + + anim.timerID = nil + anim.lowerBound = 1 + anim.upperBound = #anim.frames + anim.updating = false + + anim.repaint = repaintA + anim.rCollidesWith = rCollidesWith + anim.pCollidesWith = pCollidesWith + anim.draw = drawA + anim.update = updateA + anim.next = nextA + anim.previous = previousA + anim.moveTo = moveTo + return anim + else + error(path.." not found!") + end +end \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/npaintpro/npaintpro b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/npaintpro/npaintpro new file mode 100644 index 0000000000..0c214a60d5 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/nitrogenfingers/npaintpro/npaintpro @@ -0,0 +1,2517 @@ +--[[ + NPaintPro + By NitrogenFingers +]]-- + +--The screen size +local w,h = term.getSize() +--Whether or not the program is currently waiting on user input +local inMenu = false +--Whether or not a drop down menu is active +local inDropDown = false +--Whether or not animation tools are enabled (use -a to turn them on) +local animated = false +--Whether or not the text tools are enabled (use -t to turn them on) +local textual = false +--Whether or not "blueprint" display mode is on +local blueprint = false +--Whether or not the "layer" display is on +local layerDisplay = false +--Whether or not the "direction" display is on +local printDirection = false +--The tool/mode npaintpro is currently in. Default is "paint" +--For a list of modes, check out the help file +local state = "paint" +--Whether or not the program is presently running +local isRunning = true +--The rednet address of the 3D printer, if one has been attached +local printer = nil + +--The list of every frame, containing every image in the picture/animation +--Note: nfp files always have the picture at frame 1 +local frames = { } +--How many frames are currently in the given animation. +local frameCount = 1 +--The Colour Picker column +local column = {} +--The currently selected left and right colours +local lSel,rSel = colours.white,nil +--The amount of scrolling on the X and Y axis +local sx,sy = 0,0 +--The alpha channel colour +--Change this to change default canvas colour +local alphaC = colours.black +--The currently selected frame. Default is 1 +local sFrame = 1 +--The contents of the image buffer- contains contents, width and height +local buffer = nil +--The position, width and height of the selection rectangle +local selectrect = nil + +--Whether or not text tools are enabled for this document +local textEnabled = false +--The X and Y positions of the text cursor +local textCurX, textCurY = 1,1 + +--The currently calculated required materials +local requiredMaterials = {} +--Whether or not required materials are being displayed in the pallette +local requirementsDisplayed = false +--A list of the rednet ID's all in-range printers located +local printerList = { } +--A list of the names of all in-range printers located. Same as the printerList in reference +local printerNames = { } +--The selected printer +local selectedPrinter = 1 +--The X,Y,Z and facing of the printer +local px,py,pz,pfx,pfz = 0,0,0,0,0 +--The form of layering used +local layering = "up" + +--The animation state of the selection rectangle and image buffer +local rectblink = 0 +--The ID for the timer +local recttimer = nil +--The radius of the brush tool +local brushsize = 3 +--Whether or not "record" mode is activated (animation mode only) +local record = false +--The time between each frame when in play mode (animation mode only) +local animtime = 0.3 + +--The current "cursor position" in text mode +local cursorTexX,cursorTexY = 1,1 + +--A list of hexidecimal conversions from numbers to hex digits +local hexnums = { [10] = "a", [11] = "b", [12] = "c", [13] = "d", [14] = "e" , [15] = "f" } +--The NPaintPro logo (divine, isn't it?) +local logo = { +"fcc 3 339"; +" fcc 9333 33"; +" fcc 933 333 33"; +" fcc 933 33 33"; +" fcc 933 33 33"; +" c88 333 93333"; +" 888 333 9333"; +" 333 3 333 939"; +} +--The Layer Up and Layer Forward printing icons +local layerUpIcon = { + "0000000"; + "0088880"; + "0888870"; + "07777f0"; + "0ffff00"; + "0000000"; +} +local layerForwardIcon = { + "0000000"; + "000fff0"; + "00777f0"; + "0888700"; + "0888000"; + "0000000"; +} +--The available menu options in the ctrl menu +local mChoices = {"Save","Exit"} +--The available modes from the dropdown menu- tables indicate submenus (include a name!) +local ddModes = { { "paint", "brush", "pippette", "flood", "move", "clear", "select", name = "painting" }, { "alpha to left", "alpha to right", name = "display" }, "help", { "print", "save", "exit", name = "file" }, name = "menu" } +--The available modes from the selection right-click menu +local srModes = { "cut", "copy", "paste", "clear", "hide", name = "selection" } +--The list of available help topics for each mode 127 +local helpTopics = { + [1] = { + name = "Paint Mode", + key = nil, + animonly = false, + textonly = false, + message = "The default mode for NPaintPro, for painting pixels." + .." Controls here that are not overridden will apply for all other modes. Leaving a mode by selecting that mode " + .." again will always send the user back to paint mode.", + controls = { + { "Arrow keys", "Scroll the canvas" }, + { "Left Click", "Paint/select left colour" }, + { "Right Click", "Paint/select right colour" }, + { "Z Key", "Clear image on screen" }, + { "Tab Key", "Hide selection rectangle if visible" }, + { "Q Key", "Set alpha mask to left colour" }, + { "W Key", "Set alpha mask to right colour" }, + { "Number Keys", "Swich between frames 1-9" }, + { " keys", "Move to the next/last frame" }, + { "R Key", "Removes every frame after the current frame"} + } + }, + [2] = { + name = "Brush Mode", + key = "b", + animonly = false, + textonly = false, + message = "Brush mode allows painting a circular area of variable diameter rather than a single pixel, working in ".. + "the exact same way as paint mode in all other regards.", + controls = { + { "Left Click", "Paints a brush blob with the left colour" }, + { "Right Click", "Paints a brush blob with the right colour" }, + { "Number Keys", "Changes the radius of the brush blob from 2-9" } + } + }, + [3] = { + name = "Pippette Mode", + key = "p", + animonly = false, + textonly = false, + message = "Pippette mode allows the user to click the canvas and set the colour clicked to the left or right ".. + "selected colour, for later painting.", + controls = { + { "Left Click", "Sets clicked colour to the left selected colour" }, + { "Right Click", "Sets clicked colour to the right selected colour" } + } + }, + [4] = { + name = "Move Mode", + key = "m", + animonly = false, + textonly = false, + message = "Mode mode allows the moving of the entire image on the screen. This is especially useful for justifying".. + " the image to the top-left for animations or game assets.", + controls = { + { "Left/Right Click", "Moves top-left corner of image to selected square" }, + { "Arrow keys", "Moves image one pixel in any direction" } + } + }, + [5] = { + name = "Flood Mode", + key = "f", + animonly = false, + textonly = false, + message = "Flood mode allows the changing of an area of a given colour to that of the selected colour. ".. + "The tool uses a flood4 algorithm and will not fill diagonally. Transparency cannot be flood filled.", + controls = { + { "Left Click", "Flood fills selected area to left colour" }, + { "Right Click", "Flood fills selected area to right colour" } + } + }, + [6] = { + name = "Select Mode", + key = "s", + animonly = false, + textonly = false, + message = "Select mode allows the creation and use of the selection rectangle, to highlight specific areas on ".. + "the screen and perform operations on the selected area of the image. The selection rectangle can contain an ".. + "image on the clipboard- if it does, the image will flash inside the rectangle, and the rectangle edges will ".. + "be light grey instead of dark grey.", + controls = { + { "C Key", "Copy: Moves selection into the clipboard" }, + { "X Key", "Cut: Clears canvas under the rectangle, and moves it into the clipboard" }, + { "V Key", "Paste: Copys clipboard to the canvas" }, + { "Z Key", "Clears clipboard" }, + { "Left Click", "Moves top-left corner of rectangle to selected pixel" }, + { "Right Click", "Opens selection menu" }, + { "Arrow Keys", "Moves rectangle one pixel in any direction" } + } + }, + [7] = { + name = "Corner Select Mode", + key = nil, + animonly = false, + textonly = false, + message = "If a selection rectangle isn't visible, this mode is selected automatically. It allows the ".. + "defining of the corners of the rectangle- one the top-left and bottom-right corners have been defined, ".. + "NPaintPro switches to selection mode. Note rectangle must be at least 2 pixels wide and high.", + controls = { + { "Left/Right Click", "Defines a corner of the selection rectangle" } + } + }, + [8] = { + name = "Play Mode", + key = "space", + animonly = true, + textonly = false, + message = "Play mode will loop through each frame in your animation at a constant rate. Editing tools are ".. + "locked in this mode, and the coordinate display will turn green to indicate it is on.", + controls = { + { " Keys", "Increases/Decreases speed of the animation" }, + { "Space Bar", "Returns to paint mode" } + } + }, + [9] = { + name = "Record Mode", + key = "\\", + animonly = true, + textonly = false, + message = "Record mode is not a true mode, but influences how other modes work. Changes made that modify the ".. + "canvas in record mode will affect ALL frames in the animation. The coordinates will turn red to indicate that ".. + "record mode is on.", + controls = { + { "", "Affects:" }, + { "- Paint Mode", "" }, + { "- Brush Mode", "" }, + { "- Cut and Paste in Select Mode", ""}, + { "- Move Mode", ""} + } + }, + [10] = { + name = "Help Mode", + key = "h", + animonly = false, + textonly = false, + message = "Displays this help screen. Clicking on options will display help on that topic. Clicking out of the screen".. + " will leave this mode.", + controls = { + { "Left/Right Click", "Displays a topic/Leaves the mode" } + } + }, + [11] = { + name = "File Mode", + key = nil, + animonly = false, + textonly = false, + message = "Clicking on the mode display at the bottom of the screen will open the options menu. Here you can".. + " activate all of the modes in the program with a simple mouse click. Pressing left control will open up the".. + " file menu automatically.", + controls = { + { "leftCtrl", "Opens the file menu" }, + { "leftAlt", "Opens the paint menu" } + } + }, + [12] = { + name = "Text Mode", + key = "t", + animonly = false, + textonly = true, + message = "In this mode, the user is able to type letters onto the document for display. The left colour ".. + "pallette value determines what colour the text will be, and the right determines what colour the background ".. + "will be (set either to nil to keep the same colours as already there).", + controls = { + { "Backspace", "Deletes the character on the previous line" }, + { "Arrow Keys", "Moves the cursor in any direction" }, + { "Left Click", "Moves the cursor to beneath the mouse cursor" } + } + }, + [13] = { + name = "Textpaint Mode", + key = "y", + animonly = false, + textonly = true, + message = "Allows the user to paint any text on screen to the desired colour with the mouse. If affects the text colour".. + " values rather than the background values, but operates identically to paint mode in all other regards.", + controls = { + { "Left Click", "Paints the text with the left colour" }, + { "Right Click", "Paints the text with the right colour" } + } + }, + [14] = { + name = "About NPaintPro", + keys = nil, + animonly = false, + textonly = false, + message = "NPaintPro: The feature-bloated paint program for ComputerCraft by Nitrogen Fingers.", + controls = { + { "Testers:", " "}, + { " ", "Faubiguy"}, + { " ", "TheOriginalBIT"} + } + } +} +--The "bounds" of the image- the first/last point on both axes where a pixel appears +local toplim,botlim,leflim,riglim = nil,nil,nil,nil +--The selected path +local sPath = nil + +--[[ + Section: Helpers +]]-- + +--[[Converts a colour parameter into a single-digit hex coordinate for the colour + Params: colour:int = The colour to be converted + Returns:string A string conversion of the colour +]]-- +local function getHexOf(colour) + if not colour or not tonumber(colour) then + return " " + end + local value = math.log(colour)/math.log(2) + if value > 9 then + value = hexnums[value] + end + return value +end + +--[[Converts a hex digit into a colour value + Params: hex:?string = the hex digit to be converted + Returns:string A colour value corresponding to the hex, or nil if the character is invalid +]]-- +local function getColourOf(hex) + local value = tonumber(hex, 16) + if not value then return nil end + value = math.pow(2,value) + return value +end + +--[[Finds the biggest and smallest bounds of the image- the outside points beyond which pixels do not appear + These values are assigned to the "lim" parameters for access by other methods + Params: forAllFrames:bool = True if all frames should be used to find bounds, otherwise false or nil + Returns:nil +]]-- +local function updateImageLims(forAllFrames) + local f,l = sFrame,sFrame + if forAllFrames == true then f,l = 1,framecount end + + toplim,botlim,leflim,riglim = nil,nil,nil,nil + for locf = f,l do + for y,_ in pairs(frames[locf]) do + if type(y) == "number" then + for x,_ in pairs(frames[locf][y]) do + if frames[locf][y][x] ~= nil then + if leflim == nil or x < leflim then leflim = x end + if toplim == nil or y < toplim then toplim = y end + if riglim == nil or x > riglim then riglim = x end + if botlim == nil or y > botlim then botlim = y end + end + end + end + end + end + + --There is just... no easier way to do this. It's horrible, but necessary + if textEnabled then + for locf = f,l do + for y,_ in pairs(frames[locf].text) do + for x,_ in pairs(frames[locf].text[y]) do + if frames[locf].text[y][x] ~= nil then + if leflim == nil or x < leflim then leflim = x end + if toplim == nil or y < toplim then toplim = y end + if riglim == nil or x > riglim then riglim = x end + if botlim == nil or y > botlim then botlim = y end + end + end + end + for y,_ in pairs(frames[locf].textcol) do + for x,_ in pairs(frames[locf].textcol[y]) do + if frames[locf].textcol[y][x] ~= nil then + if leflim == nil or x < leflim then leflim = x end + if toplim == nil or y < toplim then toplim = y end + if riglim == nil or x > riglim then riglim = x end + if botlim == nil or y > botlim then botlim = y end + end + end + end + end + end +end + +--[[Determines how much of each material is required for a print. Done each time printing is called. + Params: none + Returns:table A complete list of how much of each material is required. +]]-- +function calculateMaterials() + updateImageLims(animated) + requiredMaterials = {} + for i=1,16 do + requiredMaterials[i] = 0 + end + + if not toplim then return end + + for i=1,#frames do + for y = toplim, botlim do + for x = leflim, riglim do + if type(frames[i][y][x]) == "number" then + requiredMaterials[math.log(frames[i][y][x],10)/math.log(2,10) + 1] = + requiredMaterials[math.log(frames[i][y][x],10)/math.log(2,10) + 1] + 1 + end + end + end + end +end + + +--[[Updates the rectangle blink timer. Should be called anywhere events are captured, along with a timer capture. + Params: nil + Returns:nil +]]-- +local function updateTimer(id) + if id == recttimer then + recttimer = os.startTimer(0.5) + rectblink = (rectblink % 2) + 1 + end +end + +--[[Constructs a message based on the state currently selected + Params: nil + Returns:string A message regarding the state of the application +]]-- +local function getStateMessage() + local msg = " "..string.upper(string.sub(state, 1, 1))..string.sub(state, 2, #state).." mode" + if state == "brush" then msg = msg..", size="..brushsize end + return msg +end + +--[[Calls the rednet_message event, but also looks for timer events to keep then + system timer ticking. + Params: timeout:number how long before the event times out + Returns:number the id of the sender + :number the message send +]]-- +local function rsTimeReceive(timeout) + local timerID + if timeout then timerID = os.startTimer(timeout) end + + local id,key,msg = nil,nil + while true do + id,key,msg = os.pullEvent() + + if id == "timer" then + if key == timerID then return + else updateTimer(key) end + end + if id == "rednet_message" then + return key,msg + end + end +end + +--[[Draws a picture, in paint table format on the screen + Params: image:table = the image to display + xinit:number = the x position of the top-left corner of the image + yinit:number = the y position of the top-left corner of the image + alpha:number = the color to display for the alpha channel. Default is white. + Returns:nil +]]-- +local function drawPictureTable(image, xinit, yinit, alpha) + if not alpha then alpha = 1 end + for y=1,#image do + for x=1,#image[y] do + term.setCursorPos(xinit + x-1, yinit + y-1) + local col = getColourOf(string.sub(image[y], x, x)) + if not col then col = alpha end + term.setBackgroundColour(col) + term.write(" ") + end + end +end + +--[[ + Section: Loading +]]-- + +--[[Loads a non-animted paint file into the program + Params: path:string = The path in which the file is located + Returns:nil +]]-- +local function loadNFP(path) + sFrame = 1 + frames[sFrame] = { } + if fs.exists(path) then + local file = io.open(path, "r" ) + local sLine = file:read() + local num = 1 + while sLine do + table.insert(frames[sFrame], num, {}) + for i=1,#sLine do + frames[sFrame][num][i] = getColourOf(string.sub(sLine,i,i)) + end + num = num+1 + sLine = file:read() + end + file:close() + end +end + +--[[Loads a text-paint file into the program + Params: path:string = The path in which the file is located + Returns:nil +]]-- +local function loadNFT(path) + sFrame = 1 + frames[sFrame] = { } + frames[sFrame].text = { } + frames[sFrame].textcol = { } + + if fs.exists(path) then + local file = io.open(path, "r") + local sLine = file:read() + local num = 1 + while sLine do + table.insert(frames[sFrame], num, {}) + table.insert(frames[sFrame].text, num, {}) + table.insert(frames[sFrame].textcol, num, {}) + + --As we're no longer 1-1, we keep track of what index to write to + local writeIndex = 1 + --Tells us if we've hit a 30 or 31 (BG and FG respectively)- next char specifies the curr colour + local bgNext, fgNext = false, false + --The current background and foreground colours + local currBG, currFG = nil,nil + term.setCursorPos(1,1) + for i=1,#sLine do + local nextChar = string.sub(sLine, i, i) + if nextChar:byte() == 30 then + bgNext = true + elseif nextChar:byte() == 31 then + fgNext = true + elseif bgNext then + currBG = getColourOf(nextChar) + bgNext = false + elseif fgNext then + currFG = getColourOf(nextChar) + fgNext = false + else + if nextChar ~= " " and currFG == nil then + currFG = colours.white + end + frames[sFrame][num][writeIndex] = currBG + frames[sFrame].textcol[num][writeIndex] = currFG + frames[sFrame].text[num][writeIndex] = nextChar + writeIndex = writeIndex + 1 + end + end + num = num+1 + sLine = file:read() + end + file:close() + end +end + +--[[Loads an animated paint file into the program + Params: path:string = The path in which the file is located + Returns:nil +]]-- +local function loadNFA(path) + frames[sFrame] = { } + if fs.exists(path) then + local file = io.open(path, "r" ) + local sLine = file:read() + local num = 1 + while sLine do + table.insert(frames[sFrame], num, {}) + if sLine == "~" then + sFrame = sFrame + 1 + frames[sFrame] = { } + num = 1 + else + for i=1,#sLine do + frames[sFrame][num][i] = getColourOf(string.sub(sLine,i,i)) + end + num = num+1 + end + sLine = file:read() + end + file:close() + end + framecount = sFrame + sFrame = 1 +end + +--[[Saves a non-animated paint file to the specified path + Params: path:string = The path to save the file to + Returns:nil +]]-- +local function saveNFP(path) + local sDir = string.sub(sPath, 1, #sPath - #fs.getName(sPath)) + if not fs.exists(sDir) then + fs.makeDir(sDir) + end + + local file = io.open(path, "w") + updateImageLims(false) + if not toplim then + file:close() + return + end + for y=1,botlim do + local line = "" + if frames[sFrame][y] then + for x=1,riglim do + line = line..getHexOf(frames[sFrame][y][x]) + end + end + file:write(line.."\n") + end + file:close() +end + +--[[Saves a text-paint file to the specified path + Params: path:string = The path to save the file to + Returns:nil +]]-- +local function saveNFT(path) + local sDir = string.sub(sPath, 1, #sPath - #fs.getName(sPath)) + if not fs.exists(sDir) then + fs.makeDir(sDir) + end + + local file = io.open(path, "w") + updateImageLims(false) + if not toplim then + file:close() + return + end + for y=1,botlim do + local line = "" + local currBG, currFG = nil,nil + for x=1,riglim do + if frames[sFrame][y] and frames[sFrame][y][x] ~= currBG then + line = line..string.char(30)..getHexOf(frames[sFrame][y][x]) + currBG = frames[sFrame][y][x] + end + if frames[sFrame].textcol[y] and frames[sFrame].textcol[y][x] ~= currFG then + line = line..string.char(31)..getHexOf(frames[sFrame].textcol[y][x]) + currFG = frames[sFrame].textcol[y][x] + end + if frames[sFrame].text[y] then + local char = frames[sFrame].text[y][x] + if not char then char = " " end + line = line..char + end + end + file:write(line.."\n") + end + file:close() +end + +--[[Saves a animated paint file to the specified path + Params: path:string = The path to save the file to + Returns:nil +]]-- +local function saveNFA(path) + local sDir = string.sub(sPath, 1, #sPath - #fs.getName(sPath)) + if not fs.exists(sDir) then + fs.makeDir(sDir) + end + + local file = io.open(path, "w") + updateImageLims(true) + if not toplim then + file:close() + return + end + for i=1,#frames do + for y=1,botlim do + local line = "" + if frames[i][y] then + for x=1,riglim do + line = line..getHexOf(frames[i][y][x]) + end + end + file:write(line.."\n") + end + if i < #frames then file:write("~\n") end + end + file:close() +end + + +--[[Initializes the program, by loading in the paint file. Called at the start of each program. + Params: none + Returns:nil +]]-- +local function init() + if textEnabled then + loadNFT(sPath) + table.insert(ddModes, 2, { "text", "textpaint", name = "text"}) + elseif animated then + loadNFA(sPath) + table.insert(ddModes, #ddModes, { "record", "play", name = "anim" }) + table.insert(ddModes, #ddModes, { "go to", "remove", name = "frames"}) + table.insert(ddModes[2], #ddModes[2], "blueprint on") + table.insert(ddModes[2], #ddModes[2], "layers on") + else + loadNFP(sPath) + table.insert(ddModes[2], #ddModes[2], "blueprint on") + end + + for i=0,15 do + table.insert(column, math.pow(2,i)) + end +end + +--[[ + Section: Drawing +]]-- + + +--[[Draws the rather superflous logo. Takes about 1 second, before user is able to move to the + actual program. + Params: none + Returns:nil +]]-- +local function drawLogo() + term.setBackgroundColour(colours.white) + term.clear() + drawPictureTable(logo, w/2 - #logo[1]/2, h/2 - #logo/2, colours.white) + term.setBackgroundColour(colours.white) + term.setTextColour(colours.black) + local msg = "NPaintPro" + term.setCursorPos(w/2 - #msg/2, h-3) + term.write(msg) + msg = "By NitrogenFingers" + term.setCursorPos(w/2 - #msg/2, h-2) + term.write(msg) + + os.pullEvent() +end + +--[[Clears the display to the alpha channel colour, draws the canvas, the image buffer and the selection + rectanlge if any of these things are present. + Params: none + Returns:nil +]]-- +local function drawCanvas() + --We have to readjust the position of the canvas if we're printing + turtlechar = "@" + if state == "active print" then + if layering == "up" then + if py >= 1 and py <= #frames then + sFrame = py + end + if pz < sy then sy = pz + elseif pz > sy + h - 1 then sy = pz + h - 1 end + if px < sx then sx = px + elseif px > sx + w - 2 then sx = px + w - 2 end + else + if pz >= 1 and pz <= #frames then + sFrame = pz + end + + if py < sy then sy = py + elseif py > sy + h - 1 then sy = py + h - 1 end + if px < sx then sx = px + elseif px > sx + w - 2 then sx = px + w - 2 end + end + + if pfx == 1 then turtlechar = ">" + elseif pfx == -1 then turtlechar = "<" + elseif pfz == 1 then turtlechar = "V" + elseif pfz == -1 then turtlechar = "^" + end + end + + --Picture next + local topLayer, botLayer + if layerDisplay then + topLayer = sFrame + botLayer = 1 + else + topLayer,botLayer = sFrame,sFrame + end + + for currframe = botLayer,topLayer,1 do + for y=sy+1,sy+h-1 do + if frames[currframe][y] then + for x=sx+1,sx+w-2 do + term.setCursorPos(x-sx,y-sy) + if frames[currframe][y][x] then + term.setBackgroundColour(frames[currframe][y][x]) + if textEnabled and frames[currframe].textcol[y][x] and frames[currframe].text[y][x] then + term.setTextColour(frames[currframe].textcol[y][x]) + term.write(frames[currframe].text[y][x]) + else + term.write(" ") + end + else + tileExists = false + for i=currframe-1,botLayer,-1 do + if frames[i][y][x] then + tileExists = true + break + end + end + + if not tileExists then + if blueprint then + term.setBackgroundColour(colours.blue) + term.setTextColour(colours.white) + if x == sx+1 and y % 4 == 1 then + term.write(""..((y/4) % 10)) + elseif y == sy + 1 and x % 4 == 1 then + term.write(""..((x/4) % 10)) + elseif x % 2 == 1 and y % 2 == 1 then + term.write("+") + elseif x % 2 == 1 then + term.write("|") + elseif y % 2 == 1 then + term.write("-") + else + term.write(" ") + end + else + term.setBackgroundColour(alphaC) + if textEnabled and frames[currframe].textcol[y][x] and frames[currframe].text[y][x] then + term.setTextColour(frames[currframe].textcol[y][x]) + term.write(frames[currframe].text[y][x]) + else + term.write(" ") + end + end + end + end + end + else + for x=sx+1,sx+w-2 do + term.setCursorPos(x-sx,y-sy) + + tileExists = false + for i=currframe-1,botLayer,-1 do + if frames[i][y] and frames[i][y][x] then + tileExists = true + break + end + end + + if not tileExists then + if blueprint then + term.setBackgroundColour(colours.blue) + term.setTextColour(colours.white) + if x == sx+1 and y % 4 == 1 then + term.write(""..((y/4) % 10)) + elseif y == sy + 1 and x % 4 == 1 then + term.write(""..((x/4) % 10)) + elseif x % 2 == 1 and y % 2 == 1 then + term.write("+") + elseif x % 2 == 1 then + term.write("|") + elseif y % 2 == 1 then + term.write("-") + else + term.write(" ") + end + else + term.setBackgroundColour(alphaC) + term.write(" ") + end + end + end + end + end + end + + --Then the printer, if he's on + if state == "active print" then + local bgColour = alphaC + if layering == "up" then + term.setCursorPos(px-sx,pz-sy) + if frames[sFrame] and frames[sFrame][pz-sy] and frames[sFrame][pz-sy][px-sx] then + bgColour = frames[sFrame][pz-sy][px-sx] + elseif blueprint then bgColour = colours.blue end + else + term.setCursorPos(px-sx,py-sy) + if frames[sFrame] and frames[sFrame][py-sy] and frames[sFrame][py-sy][px-sx] then + bgColour = frames[sFrame][py-sy][px-sx] + elseif blueprint then bgColour = colours.blue end + end + + term.setBackgroundColour(bgColour) + if bgColour == colours.black then term.setTextColour(colours.white) + else term.setTextColour(colours.black) end + + term.write(turtlechar) + end + + --Then the buffer + if selectrect then + if buffer and rectblink == 1 then + for y=selectrect.y1, math.min(selectrect.y2, selectrect.y1 + buffer.height-1) do + for x=selectrect.x1, math.min(selectrect.x2, selectrect.x1 + buffer.width-1) do + if buffer.contents[y-selectrect.y1+1][x-selectrect.x1+1] then + term.setCursorPos(x+sx,y+sy) + term.setBackgroundColour(buffer.contents[y-selectrect.y1+1][x-selectrect.x1+1]) + term.write(" ") + end + end + end + end + + --This draws the "selection" box + local add = nil + if buffer then + term.setBackgroundColour(colours.lightGrey) + else + term.setBackgroundColour(colours.grey) + end + for i=selectrect.x1, selectrect.x2 do + add = (i + selectrect.y1 + rectblink) % 2 == 0 + term.setCursorPos(i-sx,selectrect.y1-sy) + if add then term.write(" ") end + add = (i + selectrect.y2 + rectblink) % 2 == 0 + term.setCursorPos(i-sx,selectrect.y2-sy) + if add then term.write(" ") end + end + for i=selectrect.y1 + 1, selectrect.y2 - 1 do + add = (i + selectrect.x1 + rectblink) % 2 == 0 + term.setCursorPos(selectrect.x1-sx,i-sy) + if add then term.write(" ") end + add = (i + selectrect.x2 + rectblink) % 2 == 0 + term.setCursorPos(selectrect.x2-sx,i-sy) + if add then term.write(" ") end + end + end +end + +--[[Draws the colour picker on the right side of the screen, the colour pallette and the footer with any + messages currently being displayed + Params: none + Returns:nil +]]-- +local function drawInterface() + --Picker + for i=1,#column do + term.setCursorPos(w-1, i) + term.setBackgroundColour(column[i]) + if state == "print" then + if i == 16 then + term.setTextColour(colours.white) + else + term.setTextColour(colours.black) + end + if requirementsDisplayed then + if requiredMaterials[i] < 10 then term.write(" ") end + term.setCursorPos(w-#tostring(requiredMaterials[i])+1, i) + term.write(requiredMaterials[i]) + else + if i < 10 then term.write(" ") end + term.write(i) + end + else + term.write(" ") + end + end + term.setCursorPos(w-1,#column+1) + term.setBackgroundColour(colours.black) + term.setTextColour(colours.red) + term.write("XX") + --Pallette + term.setCursorPos(w-1,h-1) + if not lSel then + term.setBackgroundColour(colours.black) + term.setTextColour(colours.red) + term.write("X") + else + term.setBackgroundColour(lSel) + term.setTextColour(lSel) + term.write(" ") + end + if not rSel then + term.setBackgroundColour(colours.black) + term.setTextColour(colours.red) + term.write("X") + else + term.setBackgroundColour(rSel) + term.setTextColour(rSel) + term.write(" ") + end + --Footer + if inMenu then return end + + term.setCursorPos(1, h) + term.setBackgroundColour(colours.lightGrey) + term.setTextColour(colours.grey) + term.clearLine() + if inDropDown then + term.write(string.rep(" ", 6)) + else + term.setBackgroundColour(colours.grey) + term.setTextColour(colours.lightGrey) + term.write("menu ") + end + term.setBackgroundColour(colours.lightGrey) + term.setTextColour(colours.grey) + term.write(getStateMessage()) + + local coords="X:"..sx.." Y:"..sy + if animated then coords = coords.." Frame:"..sFrame.."/"..framecount.." " end + term.setCursorPos(w-#coords+1,h) + if state == "play" then term.setBackgroundColour(colours.lime) + elseif record then term.setBackgroundColour(colours.red) end + term.write(coords) + + if animated then + term.setCursorPos(w-1,h) + term.setBackgroundColour(colours.grey) + term.setTextColour(colours.lightGrey) + term.write("<>") + end +end + +--[[Runs an interface where users can select topics of help. Will return once the user quits the help screen. + Params: none + Returns:nil +]]-- +local function drawHelpScreen() + local selectedHelp = nil + while true do + term.setBackgroundColour(colours.lightGrey) + term.clear() + if not selectedHelp then + term.setCursorPos(4, 1) + term.setTextColour(colours.brown) + term.write("Available modes (click for info):") + for i=1,#helpTopics do + term.setCursorPos(2, 2 + i) + term.setTextColour(colours.black) + term.write(helpTopics[i].name) + if helpTopics[i].key then + term.setTextColour(colours.red) + term.write(" ("..helpTopics[i].key..")") + end + end + term.setCursorPos(4,h) + term.setTextColour(colours.black) + term.write("Press any key to exit") + else + term.setCursorPos(4,1) + term.setTextColour(colours.brown) + term.write(helpTopics[selectedHelp].name) + if helpTopics[selectedHelp].key then + term.setTextColour(colours.red) + term.write(" ("..helpTopics[selectedHelp].key..")") + end + term.setCursorPos(1,3) + term.setTextColour(colours.black) + print(helpTopics[selectedHelp].message.."\n") + for i=1,#helpTopics[selectedHelp].controls do + term.setTextColour(colours.brown) + term.write(helpTopics[selectedHelp].controls[i][1].." ") + term.setTextColour(colours.black) + print(helpTopics[selectedHelp].controls[i][2]) + end + end + + local id,p1,p2,p3 = os.pullEvent() + + if id == "timer" then updateTimer(p1) + elseif id == "key" then + if selectedHelp then selectedHelp = nil + else break end + elseif id == "mouse_click" then + if not selectedHelp then + if p3 >=3 and p3 <= 2+#helpTopics then + selectedHelp = p3-2 + else break end + else + selectedHelp = nil + end + end + end +end + +--[[Draws a message in the footer bar. A helper for DrawInterface, but can be called for custom messages, if the + inMenu paramter is set to true while this is being done (remember to set it back when done!) + Params: message:string = The message to be drawn + Returns:nil +]]-- +local function drawMessage(message) + term.setCursorPos(1,h) + term.setBackgroundColour(colours.lightGrey) + term.setTextColour(colours.grey) + term.clearLine() + term.write(message) +end + +--[[ + Section: Generic Interfaces +]]-- + + +--[[One of my generic text printing methods, printing a message at a specified position with width and offset. + No colour materials included. + Params: msg:string = The message to print off-center + height:number = The starting height of the message + width:number = The limit as to how many characters long each line may be + offset:number = The starting width offset of the message + Returns:number the number of lines used in printing the message +]]-- +local function wprintOffCenter(msg, height, width, offset) + local inc = 0 + local ops = 1 + while #msg - ops > width do + local nextspace = 0 + while string.find(msg, " ", ops + nextspace) and + string.find(msg, " ", ops + nextspace) - ops < width do + nextspace = string.find(msg, " ", nextspace + ops) + 1 - ops + end + local ox,oy = term.getCursorPos() + term.setCursorPos(width/2 - (nextspace)/2 + offset, height + inc) + inc = inc + 1 + term.write(string.sub(msg, ops, nextspace + ops - 1)) + ops = ops + nextspace + end + term.setCursorPos(width/2 - #string.sub(msg, ops)/2 + offset, height + inc) + term.write(string.sub(msg, ops)) + + return inc + 1 +end + +--[[Draws a message that must be clicked on or a key struck to be cleared. No options, so used for displaying + generic information. + Params: ctitle:string = The title of the confirm dialogue + msg:string = The message displayed in the dialogue + Returns:nil +]]-- +local function displayConfirmDialogue(ctitle, msg) + local dialogoffset = 8 + --We actually print twice- once to get the lines, second time to print proper. Easier this way. + local lines = wprintOffCenter(msg, 5, w - (dialogoffset+2) * 2, dialogoffset + 2) + + term.setCursorPos(dialogoffset, 3) + term.setBackgroundColour(colours.grey) + term.setTextColour(colours.lightGrey) + term.write(string.rep(" ", w - dialogoffset * 2)) + term.setCursorPos(dialogoffset + (w - dialogoffset * 2)/2 - #ctitle/2, 3) + term.write(ctitle) + term.setTextColour(colours.grey) + term.setBackgroundColour(colours.lightGrey) + term.setCursorPos(dialogoffset, 4) + term.write(string.rep(" ", w - dialogoffset * 2)) + for i=5,5+lines do + term.setCursorPos(dialogoffset, i) + term.write(" "..string.rep(" ", w - (dialogoffset) * 2 - 2).." ") + end + wprintOffCenter(msg, 5, w - (dialogoffset+2) * 2, dialogoffset + 2) + + --In the event of a message, the player hits anything to continue + while true do + local id,key = os.pullEvent() + if id == "timer" then updateTimer(key); + elseif id == "key" or id == "mouse_click" or id == "mouse_drag" then break end + end +end + +--[[Produces a nice dropdown menu based on a table of strings. Depending on the position, this will auto-adjust the position + of the menu drawn, and allows nesting of menus and sub menus. Clicking anywhere outside the menu will cancel and return nothing + Params: x:int = the x position the menu should be displayed at + y:int = the y position the menu should be displayed at + options:table = the list of options available to the user, as strings or submenus (tables of strings, with a name parameter) + Returns:string the selected menu option. +]]-- +local function displayDropDown(x, y, options) + inDropDown = true + --Figures out the dimensions of our thing + local longestX = #options.name + for i=1,#options do + local currVal = options[i] + if type(currVal) == "table" then currVal = currVal.name end + + longestX = math.max(longestX, #currVal) + end + local xOffset = math.max(0, longestX - ((w-2) - x) + 1) + local yOffset = math.max(0, #options - ((h-1) - y)) + + local clickTimes = 0 + local tid = nil + local selection = nil + while clickTimes < 2 do + drawCanvas() + drawInterface() + + term.setCursorPos(x-xOffset,y-yOffset) + term.setBackgroundColour(colours.grey) + term.setTextColour(colours.lightGrey) + term.write(options.name..string.rep(" ", longestX-#options.name + 2)) + + for i=1,#options do + term.setCursorPos(x-xOffset, y-yOffset+i) + if i==selection and clickTimes % 2 == 0 then + term.setBackgroundColour(colours.grey) + term.setTextColour(colours.lightGrey) + else + term.setBackgroundColour(colours.lightGrey) + term.setTextColour(colours.grey) + end + local currVal = options[i] + if type(currVal) == "table" then + term.write(currVal.name..string.rep(" ", longestX-#currVal.name + 1)) + term.setBackgroundColour(colours.grey) + term.setTextColour(colours.lightGrey) + term.write(">") + else + term.write(currVal..string.rep(" ", longestX-#currVal + 2)) + end + end + + local id, p1, p2, p3 = os.pullEvent() + if id == "timer" then + if p1 == tid then + clickTimes = clickTimes + 1 + if clickTimes > 2 then + break + else + tid = os.startTimer(0.1) + end + else + updateTimer(p1) + drawCanvas() + drawInterface() + end + elseif id == "mouse_click" then + if p2 >=x-xOffset and p2 <= x-xOffset + longestX + 1 and p3 >= y-yOffset+1 and p3 <= y-yOffset+#options then + selection = p3-(y-yOffset) + tid = os.startTimer(0.1) + else + selection = "" + break + end + end + end + + if type(selection) == "number" then + selection = options[selection] + end + + if type(selection) == "string" then + inDropDown = false + return selection + elseif type(selection) == "table" then + return displayDropDown(x, y, selection) + end +end + +--[[A custom io.read() function with a few differences- it limits the number of characters being printed, + waits a 1/100th of a second so any keys still in the event library are removed before input is read and + the timer for the selectionrectangle is continuously updated during the process. + Params: lim:int = the number of characters input is allowed + Returns:string the inputted string, trimmed of leading and tailing whitespace +]]-- +local function readInput(lim) + term.setCursorBlink(true) + + local inputString = "" + if not lim or type(lim) ~= "number" or lim < 1 then lim = w - ox end + local ox,oy = term.getCursorPos() + --We only get input from the footer, so this is safe. Change if recycling + term.setBackgroundColour(colours.lightGrey) + term.setTextColour(colours.grey) + term.write(string.rep(" ", lim)) + term.setCursorPos(ox, oy) + --As events queue immediately, we may get an unwanted key... this will solve that problem + local inputTimer = os.startTimer(0.01) + local keysAllowed = false + + while true do + local id,key = os.pullEvent() + + if keysAllowed then + if id == "key" and key == 14 and #inputString > 0 then + inputString = string.sub(inputString, 1, #inputString-1) + term.setCursorPos(ox + #inputString,oy) + term.write(" ") + elseif id == "key" and key == 28 and inputString ~= string.rep(" ", #inputString) then + break + elseif id == "key" and key == keys.leftCtrl then + return "" + elseif id == "char" and #inputString < lim then + inputString = inputString..key + end + end + + if id == "timer" then + if key == inputTimer then + keysAllowed = true + else + updateTimer(key) + drawCanvas() + drawInterface() + term.setBackgroundColour(colours.lightGrey) + term.setTextColour(colours.grey) + end + end + term.setCursorPos(ox,oy) + term.write(inputString) + term.setCursorPos(ox + #inputString, oy) + end + + while string.sub(inputString, 1, 1) == " " do + inputString = string.sub(inputString, 2, #inputString) + end + while string.sub(inputString, #inputString, #inputString) == " " do + inputString = string.sub(inputString, 1, #inputString-1) + end + term.setCursorBlink(false) + + return inputString +end + +--[[ + Section: Image tools +]]-- + + +--[[Copies all pixels beneath the selection rectangle into the image buffer. Empty buffers are converted to nil. + Params: removeImage:bool = true if the image is to be erased after copying, false otherwise + Returns:nil +]]-- +local function copyToBuffer(removeImage) + buffer = { width = selectrect.x2 - selectrect.x1 + 1, height = selectrect.y2 - selectrect.y1 + 1, contents = { } } + + local containsSomething = false + for y=1,buffer.height do + buffer.contents[y] = { } + local f,l = sFrame,sFrame + if record then f,l = 1, framecount end + + for fra = f,l do + if frames[fra][selectrect.y1 + y - 1] then + for x=1,buffer.width do + buffer.contents[y][x] = frames[sFrame][selectrect.y1 + y - 1][selectrect.x1 + x - 1] + if removeImage then frames[fra][selectrect.y1 + y - 1][selectrect.x1 + x - 1] = nil end + if buffer.contents[y][x] then containsSomething = true end + end + end + end + end + --I don't classify an empty buffer as a real buffer- confusing to the user. + if not containsSomething then buffer = nil end +end + +--[[Replaces all pixels under the selection rectangle with the image buffer (or what can be seen of it). Record-dependent. + Params: removeBuffer:bool = true if the buffer is to be emptied after copying, false otherwise + Returns:nil +]]-- +local function copyFromBuffer(removeBuffer) + if not buffer then return end + + for y = 1, math.min(buffer.height,selectrect.y2-selectrect.y1+1) do + local f,l = sFrame, sFrame + if record then f,l = 1, framecount end + + for fra = f,l do + if not frames[fra][selectrect.y1+y-1] then frames[fra][selectrect.y1+y-1] = { } end + for x = 1, math.min(buffer.width,selectrect.x2-selectrect.x1+1) do + frames[fra][selectrect.y1+y-1][selectrect.x1+x-1] = buffer.contents[y][x] + end + end + end + + if removeBuffer then buffer = nil end +end + +--[[Moves the entire image (or entire animation) to the specified coordinates. Record-dependent. + Params: newx:int = the X coordinate to move the image to + newy:int = the Y coordinate to move the image to + Returns:nil +]]-- +local function moveImage(newx,newy) + if not leflim or not toplim then return end + if newx <=0 or newy <=0 then return end + local f,l = sFrame,sFrame + if record then f,l = 1,framecount end + + for i=f,l do + local newlines = { } + for y=toplim,botlim do + local line = frames[i][y] + if line then + newlines[y-toplim+newy] = { } + for x,char in pairs(line) do + newlines[y-toplim+newy][x-leflim+newx] = char + end + end + end + --Exceptions that allow us to move the text as well + if textEnabled then + newlines.text = { } + for y=toplim,botlim do + local line = frames[i].text[y] + if line then + newlines.text[y-toplim+newy] = { } + for x,char in pairs(line) do + newlines.text[y-toplim+newy][x-leflim+newx] = char + end + end + end + + newlines.textcol = { } + for y=toplim,botlim do + local line = frames[i].textcol[y] + if line then + newlines.textcol[y-toplim+newy] = { } + for x,char in pairs(line) do + newlines.textcol[y-toplim+newy][x-leflim+newx] = char + end + end + end + end + + frames[i] = newlines + end +end + +--[[Prompts the user to clear the current frame or all frames. Record-dependent., + Params: none + Returns:nil +]]-- +local function clearImage() + inMenu = true + if not animated then + drawMessage("Clear image? Y/N: ") + elseif record then + drawMessage("Clear ALL frames? Y/N: ") + else + drawMessage("Clear current frame? Y/N :") + end + if string.find(string.upper(readInput(1)), "Y") then + local f,l = sFrame,sFrame + if record then f,l = 1,framecount end + + for i=f,l do + frames[i] = { } + end + end + inMenu = false +end + +--[[A recursively called method (watch out for big calls!) in which every pixel of a set colour is + changed to another colour. Does not work on the nil colour, for obvious reasons. + Params: x:int = The X coordinate of the colour to flood-fill + y:int = The Y coordinate of the colour to flood-fill + targetColour:colour = the colour that is being flood-filled + newColour:colour = the colour with which to replace the target colour + Returns:nil +]]-- +local function floodFill(x, y, targetColour, newColour) + if not newColour or not targetColour then return end + local nodeList = { } + + table.insert(nodeList, {x = x, y = y}) + + while #nodeList > 0 do + local node = nodeList[1] + if frames[sFrame][node.y] and frames[sFrame][node.y][node.x] == targetColour then + frames[sFrame][node.y][node.x] = newColour + table.insert(nodeList, { x = node.x + 1, y = node.y}) + table.insert(nodeList, { x = node.x, y = node.y + 1}) + if x > 1 then table.insert(nodeList, { x = node.x - 1, y = node.y}) end + if y > 1 then table.insert(nodeList, { x = node.x, y = node.y - 1}) end + end + table.remove(nodeList, 1) + end +end + +--[[ + Section: Animation Tools +]]-- + +--[[Enters play mode, allowing the animation to play through. Interface is restricted to allow this, + and method only leaves once the player leaves play mode. + Params: none + Returns:nil +]]-- +local function playAnimation() + state = "play" + selectedrect = nil + + local animt = os.startTimer(animtime) + repeat + drawCanvas() + drawInterface() + + local id,key,_,y = os.pullEvent() + + if id=="timer" then + if key == animt then + animt = os.startTimer(animtime) + sFrame = (sFrame % framecount) + 1 + else + updateTimer(key) + end + elseif id=="key" then + if key == keys.comma and animtime > 0.1 then animtime = animtime - 0.05 + elseif key == keys.period and animtime < 0.5 then animtime = animtime + 0.05 + elseif key == keys.space then state = "paint" end + elseif id=="mouse_click" and y == h then + state = "paint" + end + until state ~= "play" + os.startTimer(0.5) +end + +--[[Changes the selected frame (sFrame) to the chosen frame. If this frame is above the framecount, + additional frames are created with a copy of the image on the selected frame. + Params: newframe:int = the new frame to move to + Returns:nil +]]-- +local function changeFrame(newframe) + inMenu = true + if not tonumber(newframe) then + term.setCursorPos(1,h) + term.setBackgroundColour(colours.lightGrey) + term.setTextColour(colours.grey) + term.clearLine() + + term.write("Go to frame: ") + newframe = tonumber(readInput(2)) + if not newframe or newframe <= 0 then + inMenu = false + return + end + elseif newframe <= 0 then return end + + if newframe > framecount then + for i=framecount+1,newframe do + frames[i] = {} + for y,line in pairs(frames[sFrame]) do + frames[i][y] = { } + for x,v in pairs(line) do + frames[i][y][x] = v + end + end + end + framecount = newframe + end + sFrame = newframe + inMenu = false +end + +--[[Removes every frame leading after the frame passed in + Params: frame:int the non-inclusive lower bounds of the delete + Returns:nil +]]-- +local function removeFramesAfter(frame) + inMenu = true + if frame==framecount then return end + drawMessage("Remove frames "..(frame+1).."/"..framecount.."? Y/N :") + local answer = string.upper(readInput(1)) + + if string.find(answer, string.upper("Y")) ~= 1 then + inMenu = false + return + end + + for i=frame+1, framecount do + frames[i] = nil + end + framecount = frame + inMenu = false +end + +--[[ + Section: Printing Tools +]]-- + +--[[Constructs a new facing to the left of the current facing + Params: curx:number = The facing on the X axis + curz:number = The facing on the Z axis + hand:string = The hand of the axis ("right" or "left") + Returns:number,number = the new facing on the X and Z axis after a left turn +]]-- +local function getLeft(curx, curz) + local hand = "left" + if layering == "up" then hand = "right" end + + if hand == "right" then + if curx == 1 then return 0,-1 end + if curx == -1 then return 0,1 end + if curz == 1 then return 1,0 end + if curz == -1 then return -1,0 end + else + if curx == 1 then return 0,1 end + if curx == -1 then return 0,-1 end + if curz == 1 then return -1,0 end + if curz == -1 then return 1,0 end + end +end + +--[[Constructs a new facing to the right of the current facing + Params: curx:number = The facing on the X axis + curz:number = The facing on the Z axis + hand:string = The hand of the axis ("right" or "left") + Returns:number,number = the new facing on the X and Z axis after a right turn +]]-- +local function getRight(curx, curz) + local hand = "left" + if layering == "up" then hand = "right" end + + if hand == "right" then + if curx == 1 then return 0,1 end + if curx == -1 then return 0,-1 end + if curz == 1 then return -1,0 end + if curz == -1 then return 1,0 end + else + if curx == 1 then return 0,-1 end + if curx == -1 then return 0,1 end + if curz == 1 then return 1,0 end + if curz == -1 then return -1,0 end + end +end + + +--[[Sends out a rednet signal requesting local printers, and will listen for any responses. Printers found are added to the + printerList (for ID's) and printerNames (for names) + Params: nil + Returns:nil +]]-- +local function locatePrinters() + printerList = { } + printerNames = { name = "Printers" } + local oldState = state + state = "Locating printers, please wait... " + drawCanvas() + drawInterface() + state = oldState + + local modemOpened = false + for k,v in pairs(rs.getSides()) do + if peripheral.isPresent(v) and peripheral.getType(v) == "modem" then + rednet.open(v) + modemOpened = true + break + end + end + + if not modemOpened then + displayConfirmDialogue("Modem not found!", "No modem peripheral. Must have network modem to locate printers.") + return false + end + + rednet.broadcast("$3DPRINT IDENTIFY") + + while true do + local id, msg = rsTimeReceive(1) + + if not id then break end + if string.find(msg, "$3DPRINT IDACK") == 1 then + msg = string.gsub(msg, "$3DPRINT IDACK ", "") + table.insert(printerList, id) + table.insert(printerNames, msg) + end + end + + if #printerList == 0 then + displayConfirmDialogue("Printers not found!", "No active printers found in proximity of this computer.") + return false + else + return true + end +end + +--[[Sends a request to the printer. Waits on a response and updates the state of the application accordingly. + Params: command:string the command to send + param:string a parameter to send, if any + Returns:nil +]]-- +local function sendPC(command,param) + local msg = "$PC "..command + if param then msg = msg.." "..param end + rednet.send(printerList[selectedPrinter], msg) + + while true do + local id,key = rsTimeReceive() + if id == printerList[selectedPrinter] then + if key == "$3DPRINT ACK" then + break + elseif key == "$3DPRINT DEP" then + displayConfirmDialogue("Printer Empty", "The printer has exhasted a material. Please refill slot "..param.. + ", and click this message when ready to continue.") + rednet.send(printerList[selectedPrinter], msg) + elseif key == "$3DPRINT OOF" then + displayConfirmDialogue("Printer Out of Fuel", "The printer has no fuel. Please replace the material ".. + "in slot 1 with a fuel source, then click this message.") + rednet.send(printerList[selectedPrinter], "$PC SS 1") + id,key = rsTimeReceive() + rednet.send(printerList[selectedPrinter], "$PC RF") + id,key = rsTimeReceive() + rednet.send(printerList[selectedPrinter], msg) + end + end + end + + --Changes to position are handled after the event has been successfully completed + if command == "FW" then + px = px + pfx + pz = pz + pfz + elseif command == "BK" then + px = px - pfx + pz = pz - pfz + elseif command == "UP" then + if layering == "up" then + py = py + 1 + else + py = py - 1 + end + elseif command == "DW" then + if layering == "up" then + py = py - 1 + else + py = py + 1 + end + elseif command == "TL" then + pfx,pfz = getLeft(pfx,pfz) + elseif command == "TR" then + pfx,pfz = getRight(pfx,pfz) + elseif command == "TU" then + pfx = -pfx + pfz = -pfz + end + + drawCanvas() + drawInterface() +end + +--[[A printing function that commands the printer to turn to face the desired direction, if it is not already doing so + Params: desx:number = the normalized x direction to face + desz:number = the normalized z direction to face + Returns:nil +]]-- +local function turnToFace(desx,desz) + if desx ~= 0 then + if pfx ~= desx then + local temppfx,_ = getLeft(pfx,pfz) + if temppfx == desx then + sendPC("TL") + elseif temppfx == -desx then + sendPC("TR") + else + sendPC("TU") + end + end + else + print("on the z axis") + if pfz ~= desz then + local _,temppfz = getLeft(pfx,pfz) + if temppfz == desz then + sendPC("TL") + elseif temppfz == -desz then + sendPC("TR") + else + sendPC("TU") + end + end + end +end + +--[[Performs the print + Params: nil + Returns:nil +]]-- +local function performPrint() + state = "active print" + if layering == "up" then + --An up layering starts our builder bot on the bottom left corner of our build + px,py,pz = leflim, 0, botlim + 1 + pfx,pfz = 0,-1 + + --We move him forward and up a bit from his original position. + sendPC("FW") + sendPC("UP") + --For each layer that needs to be completed, we go up by one each time + for layers=1,#frames do + --We first decide if we're going forwards or back, depending on what side we're on + local rowbot,rowtop,rowinc = nil,nil,nil + if pz == botlim then + rowbot,rowtop,rowinc = botlim,toplim,-1 + else + rowbot,rowtop,rowinc = toplim,botlim,1 + end + + for rows = rowbot,rowtop,rowinc do + --Then we decide if we're going left or right, depending on what side we're on + local linebot,linetop,lineinc = nil,nil,nil + if px == leflim then + --Facing from the left side has to be easterly- it's changed here + turnToFace(1,0) + linebot,linetop,lineinc = leflim,riglim,1 + else + --Facing from the right side has to be westerly- it's changed here + turnToFace(-1,0) + linebot,linetop,lineinc = riglim,leflim,-1 + end + + for lines = linebot,linetop,lineinc do + --We move our turtle forward, placing the right material at each step + local material = frames[py][pz][px] + if material then + material = math.log10(frames[py][pz][px])/math.log10(2) + 1 + sendPC("SS", material) + sendPC("PD") + end + if lines ~= linetop then + sendPC("FW") + end + end + + --The printer then has to do a U-turn, depending on which way he's facing and + --which way he needs to go + local temppfx,temppfz = getLeft(pfx,pfz) + if temppfz == rowinc and rows ~= rowtop then + sendPC("TL") + sendPC("FW") + sendPC("TL") + elseif temppfz == -rowinc and rows ~= rowtop then + sendPC("TR") + sendPC("FW") + sendPC("TR") + end + end + --Now at the end of a run he does a 180 and moves up to begin the next part of the print + sendPC("TU") + if layers ~= #frames then + sendPC("UP") + end + end + --All done- now we head back to where we started. + if px ~= leflim then + turnToFace(-1,0) + while px ~= leflim do + sendPC("FW") + end + end + if pz ~= botlim then + turnToFace(0,-1) + while pz ~= botlim do + sendPC("BK") + end + end + turnToFace(0,-1) + sendPC("BK") + while py > 0 do + sendPC("DW") + end + else + --The front facing is at the top-left corner, facing south not north + px,py,pz = leflim, botlim, 1 + pfx,pfz = 0,1 + --We move the printer to the last layer- he prints from the back forwards + while pz < #frames do + sendPC("FW") + end + + --For each layer in the frame we build our wall, the move back + for layers = 1,#frames do + --We first decide if we're going left or right based on our position + local rowbot,rowtop,rowinc = nil,nil,nil + if px == leflim then + rowbot,rowtop,rowinc = leflim,riglim,1 + else + rowbot,rowtop,rowinc = riglim,leflim,-1 + end + + for rows = rowbot,rowtop,rowinc do + --Then we decide if we're going up or down, depending on our given altitude + local linebot,linetop,lineinc = nil,nil,nil + if py == botlim then + linebot,linetop,lineinc = botlim,toplim,-1 + else + linebot,linetop,lineinc = toplim,botlim,1 + end + + for lines = linebot,linetop,lineinc do + --We move our turtle up/down, placing the right material at each step + local material = frames[pz][py][px] + if material then + material = math.log10(frames[pz][py][px])/math.log10(2) + 1 + sendPC("SS", material) + sendPC("PF") + end + if lines ~= linetop then + if lineinc == 1 then sendPC("DW") + else sendPC("UP") end + end + end + + if rows ~= rowtop then + turnToFace(rowinc,0) + sendPC("FW") + turnToFace(0,1) + end + end + + if layers ~= #frames then + sendPC("TU") + sendPC("FW") + sendPC("TU") + end + end + --He's easy to reset + while px ~= leflim do + turnToFace(-1,0) + sendPC("FW") + end + turnToFace(0,1) + end + + sendPC("DE") + + displayConfirmDialogue("Print complete", "The 3D print was successful.") +end + +--[[ + Section: Interface +]]-- + +--[[Runs the printing interface. Allows users to find/select a printer, the style of printing to perform and to begin the operation + Params: none + Returns:boolean true if printing was started, false otherwse +]]-- +local function runPrintInterface() + calculateMaterials() + --There's nothing on canvas yet! + if not botlim then + displayConfirmDialogue("Cannot Print Empty Canvas", "There is nothing on canvas that ".. + "can be printed, and the operation cannot be completed.") + return false + end + --No printers nearby + if not locatePrinters() then + return false + end + + layering = "up" + requirementsDisplayed = false + selectedPrinter = 1 + while true do + drawCanvas() + term.setBackgroundColour(colours.lightGrey) + for i=1,10 do + term.setCursorPos(1,i) + term.clearLine() + end + drawInterface() + term.setBackgroundColour(colours.lightGrey) + term.setTextColour(colours.black) + + local msg = "3D Printing" + term.setCursorPos(w/2-#msg/2 - 2, 1) + term.write(msg) + term.setBackgroundColour(colours.grey) + term.setTextColour(colours.lightGrey) + if(requirementsDisplayed) then + msg = "Count:" + else + msg = " Slot:" + end + term.setCursorPos(w-3-#msg, 1) + term.write(msg) + term.setBackgroundColour(colours.lightGrey) + term.setTextColour(colours.black) + + term.setCursorPos(7, 2) + term.write("Layering") + drawPictureTable(layerUpIcon, 3, 3, colours.white) + drawPictureTable(layerForwardIcon, 12, 3, colours.white) + if layering == "up" then + term.setBackgroundColour(colours.red) + else + term.setBackgroundColour(colours.lightGrey) + end + term.setCursorPos(3, 9) + term.write("Upwards") + if layering == "forward" then + term.setBackgroundColour(colours.red) + else + term.setBackgroundColour(colours.lightGrey) + end + term.setCursorPos(12, 9) + term.write("Forward") + + term.setBackgroundColour(colours.lightGrey) + term.setTextColour(colours.black) + term.setCursorPos(31, 2) + term.write("Printer ID") + term.setCursorPos(33, 3) + if #printerList > 1 then + term.setBackgroundColour(colours.grey) + term.setTextColour(colours.lightGrey) + else + term.setTextColour(colours.red) + end + term.write(" "..printerNames[selectedPrinter].." ") + + term.setBackgroundColour(colours.grey) + term.setTextColour(colours.lightGrey) + term.setCursorPos(25, 10) + term.write(" Cancel ") + term.setCursorPos(40, 10) + term.write(" Print ") + + local id, p1, p2, p3 = os.pullEvent() + + if id == "timer" then + updateTimer(p1) + elseif id == "mouse_click" then + --Layering Buttons + if p2 >= 3 and p2 <= 9 and p3 >= 3 and p3 <= 9 then + layering = "up" + elseif p2 >= 12 and p2 <= 18 and p3 >= 3 and p3 <= 9 then + layering = "forward" + --Count/Slot + elseif p2 >= w - #msg - 3 and p2 <= w - 3 and p3 == 1 then + requirementsDisplayed = not requirementsDisplayed + --Printer ID + elseif p2 >= 33 and p2 <= 33 + #printerNames[selectedPrinter] and p3 == 3 and #printerList > 1 then + local chosenName = displayDropDown(33, 3, printerNames) + for i=1,#printerNames do + if printerNames[i] == chosenName then + selectedPrinter = i + break; + end + end + --Print and Cancel + elseif p2 >= 25 and p2 <= 32 and p3 == 10 then + break + elseif p2 >= 40 and p2 <= 46 and p3 == 10 then + rednet.send(printerList[selectedPrinter], "$3DPRINT ACTIVATE") + ready = false + while true do + local id,msg = rsTimeReceive(10) + + if id == printerList[selectedPrinter] and msg == "$3DPRINT ACTACK" then + ready = true + break + end + end + if ready then + performPrint() + break + else + displayConfirmDialogue("Printer Didn't Respond", "The printer didn't respond to the activation command. Check to see if it's online") + end + end + end + end + state = "paint" +end + +--[[This function changes the current paint program to another tool or mode, depending on user input. Handles + any necessary changes in logic involved in that. + Params: mode:string = the name of the mode to change to + Returns:nil +]]-- +local function performSelection(mode) + if not mode or mode == "" then return + + elseif mode == "help" then + drawHelpScreen() + + elseif mode == "blueprint on" then + blueprint = true + ddModes[2][3] = "blueprint off" + + elseif mode == "blueprint off" then + blueprint = false + ddModes[2][3] = "blueprint on" + + elseif mode == "layers on" then + layerDisplay = true + ddModes[2][4] = "layers off" + + elseif mode == "layers off" then + layerDisplay = false + ddModes[2][4] = "layers on" + + elseif mode == "direction on" then + printDirection = true + ddModes[2][5] = "direction off" + + elseif mode == "direction off" then + printDirection = false + ddModes[2][5] = "direction on" + + elseif mode == "go to" then + changeFrame() + + elseif mode == "remove" then + removeFramesAfter(sFrame) + + elseif mode == "play" then + playAnimation() + + elseif mode == "copy" then + if selectrect and selectrect.x1 ~= selectrect.x2 then + copyToBuffer(false) + end + + elseif mode == "cut" then + if selectrect and selectrect.x1 ~= selectrect.x2 then + copyToBuffer(true) + end + + elseif mode == "paste" then + if selectrect and selectrect.x1 ~= selectrect.x2 then + copyFromBuffer(false) + end + + elseif mode == "hide" then + selectrect = nil + if state == "select" then state = "corner select" end + + elseif mode == "alpha to left" then + if lSel then alphaC = lSel end + + elseif mode == "alpha to right" then + if rSel then alphaC = rSel end + + elseif mode == "record" then + record = not record + + elseif mode == "clear" then + if state=="select" then buffer = nil + else clearImage() end + + elseif mode == "select" then + if state=="corner select" or state=="select" then + state = "paint" + elseif selectrect and selectrect.x1 ~= selectrect.x2 then + state = "select" + else + state = "corner select" + end + + elseif mode == "print" then + state = "print" + runPrintInterface() + state = "paint" + + elseif mode == "save" then + if animated then saveNFA(sPath) + elseif textEnabled then saveNFT(sPath) + else saveNFP(sPath) end + + elseif mode == "exit" then + isRunning = false + + elseif mode ~= state then state = mode + else state = "paint" + + end +end + +--[[The main function of the program, reads and handles all events and updates them accordingly. Mode changes, + painting to the canvas and general selections are done here. + Params: none + Returns:nil +]]-- +local function handleEvents() + recttimer = os.startTimer(0.5) + while isRunning do + drawCanvas() + drawInterface() + + if state == "text" then + term.setCursorPos(textCurX - sx, textCurY - sy) + term.setCursorBlink(true) + end + + local id,p1,p2,p3 = os.pullEvent() + term.setCursorBlink(false) + if id=="timer" then + updateTimer(p1) + elseif id=="mouse_click" or id=="mouse_drag" then + if p2 >=w-1 and p3 < #column+1 then + if p1==1 then lSel = column[p3] + else rSel = column[p3] end + elseif p2 >=w-1 and p3==#column+1 then + if p1==1 then lSel = nil + else rSel = nil end + elseif p2==w-1 and p3==h and animated then + changeFrame(sFrame-1) + elseif p2==w and p3==h and animated then + changeFrame(sFrame+1) + elseif p2 < w-10 and p3==h then + local sel = displayDropDown(1, h-1, ddModes) + performSelection(sel) + elseif p2 < w-1 and p3 <= h-1 then + if state=="pippette" then + if p1==1 then + if frames[sFrame][p3+sy] and frames[sFrame][p3+sy][p2+sx] then + lSel = frames[sFrame][p3+sy][p2+sx] + end + elseif p1==2 then + if frames[sFrame][p3+sy] and frames[sFrame][p3+sy][p2+sx] then + rSel = frames[sFrame][p3+sy][p2+sx] + end + end + elseif state=="move" then + updateImageLims(record) + moveImage(p2,p3) + elseif state=="flood" then + if p1 == 1 and lSel and frames[sFrame][p3+sy] then + floodFill(p2,p3,frames[sFrame][p3+sy][p2+sx],lSel) + elseif p1 == 2 and rSel and frames[sFrame][p3+sy] then + floodFill(p2,p3,frames[sFrame][p3+sy][p2+sx],rSel) + end + elseif state=="corner select" then + if not selectrect then + selectrect = { x1=p2+sx, x2=p2+sx, y1=p3+sy, y2=p3+sy } + elseif selectrect.x1 ~= p2+sx and selectrect.y1 ~= p3+sy then + if p2+sx w + sx - 2 then sx = textCurX - w + 2 end + elseif tonumber(p1) then + if state=="brush" and tonumber(p1) > 1 then + brushsize = tonumber(p1) + elseif animated and tonumber(p1) > 0 then + changeFrame(tonumber(p1)) + end + end + elseif id=="key" then + --Text needs special handlers (all other keyboard shortcuts are of course reserved for typing) + if state=="text" then + if p1==keys.backspace and textCurX > 1 then + textCurX = textCurX-1 + if frames[sFrame].text[textCurY] then + frames[sFrame].text[textCurY][textCurX] = nil + frames[sFrame].textcol[textCurY][textCurX] = nil + end + if textCurX < sx then sx = textCurX end + elseif p1==keys.left and textCurX > 1 then + textCurX = textCurX-1 + if textCurX-1 < sx then sx = textCurX-1 end + elseif p1==keys.right then + textCurX = textCurX+1 + if textCurX > w + sx - 2 then sx = textCurX - w + 2 end + elseif p1==keys.up and textCurY > 1 then + textCurY = textCurY-1 + if textCurY-1 < sy then sy = textCurY-1 end + elseif p1==keys.down then + textCurY = textCurY+1 + if textCurY > h + sy - 1 then sy = textCurY - h + 1 end + end + + elseif p1==keys.leftCtrl then + local sel = displayDropDown(1, h-1, ddModes[#ddModes]) + performSelection(sel) + elseif p1==keys.leftAlt then + local sel = displayDropDown(1, h-1, ddModes[1]) + performSelection(sel) + elseif p1==keys.h then + performSelection("help") + elseif p1==keys.x then + performSelection("cut") + elseif p1==keys.c then + performSelection("copy") + elseif p1==keys.v then + performSelection("paste") + elseif p1==keys.z then + performSelection("clear") + elseif p1==keys.s then + performSelection("select") + elseif p1==keys.tab then + performSelection("hide") + elseif p1==keys.q then + performSelection("alpha to left") + elseif p1==keys.w then + performSelection("alpha to right") + elseif p1==keys.f then + performSelection("flood") + elseif p1==keys.b then + performSelection("brush") + elseif p1==keys.m then + performSelection("move") + elseif p1==keys.backslash and animated then + performSelection("record") + elseif p1==keys.p then + performSelection("pippette") + elseif p1==keys.g and animated then + performSelection("go to") + elseif p1==keys.period and animated then + changeFrame(sFrame+1) + elseif p1==keys.comma and animated then + changeFrame(sFrame-1) + elseif p1==keys.r and animated then + performSelection("remove") + elseif p1==keys.space and animated then + performSelection("play") + elseif p1==keys.t and textEnabled then + performSelection("text") + sleep(0.01) + elseif p1==keys.y and textEnabled then + performSelection("textpaint") + elseif p1==keys.left then + if state == "move" and toplim then + updateImageLims(record) + if toplim and leflim then + moveImage(leflim-1,toplim) + end + elseif state=="select" and selectrect.x1 > 1 then + selectrect.x1 = selectrect.x1-1 + selectrect.x2 = selectrect.x2-1 + elseif sx > 0 then sx=sx-1 end + elseif p1==keys.right then + if state == "move" then + updateImageLims(record) + if toplim and leflim then + moveImage(leflim+1,toplim) + end + elseif state=="select" then + selectrect.x1 = selectrect.x1+1 + selectrect.x2 = selectrect.x2+1 + else sx=sx+1 end + elseif p1==keys.up then + if state == "move" then + updateImageLims(record) + if toplim and leflim then + moveImage(leflim,toplim-1) + end + elseif state=="select" and selectrect.y1 > 1 then + selectrect.y1 = selectrect.y1-1 + selectrect.y2 = selectrect.y2-1 + elseif sy > 0 then sy=sy-1 end + elseif p1==keys.down then + if state == "move" then + updateImageLims(record) + if toplim and leflim then + moveImage(leflim,toplim+1) + end + elseif state=="select" then + selectrect.y1 = selectrect.y1+1 + selectrect.y2 = selectrect.y2+1 + else sy=sy+1 end + end + end + end +end + +--[[ + Section: Main +]]-- + +if not term.isColour() then + printError("Requires an Advanced Computer") + return +end + +--Taken almost directly from edit (for consistency) +local tArgs = {...} + +local ca = 1 + +if tArgs[ca] == "-a" then + animated = true + ca = ca + 1 +end + +if tArgs[ca] == "-t" then + textEnabled = true + ca = ca + 1 +end + +if #tArgs < ca then + print("Usage: npaintpro [-a,-t] ") + return +end + +--Yeah you can't have animated text files YET... I haven't supported that, maybe later? +if animated and textEnabled then + print("No support for animated text files- cannot have both -a and -t") +end + +sPath = shell.resolve(tArgs[ca]) +local bReadOnly = fs.isReadOnly(sPath) +if fs.exists(sPath) then + if fs.isDir(sPath) then + print("Cannot edit a directory.") + return + elseif string.find(sPath, ".nfp") ~= #sPath-3 and string.find(sPath, ".nfa") ~= #sPath-3 and + string.find(sPath, ".nft") ~= #sPath-3 then + print("Can only edit .nfp, .nft and .nfa files:",string.find(sPath, ".nfp"),#sPath-3) + return + end + + if string.find(sPath, ".nfa") == #sPath-3 then + animated = true + end + + if string.find(sPath, ".nft") == #sPath-3 then + textEnabled = true + end + + if string.find(sPath, ".nfp") == #sPath-3 and animated then + print("Convert to nfa? Y/N") + if string.find(string.lower(io.read()), "y") then + local nsPath = string.sub(sPath, 1, #sPath-1).."a" + fs.move(sPath, nsPath) + sPath = nsPath + else + animated = false + end + end + + --Again this is possible, I just haven't done it. Maybe I will? + if textEnabled and (string.find(sPath, ".nfp") == #sPath-3 or string.find(sPath, ".nfa") == #sPath-3) then + print("Cannot convert to nft") + end +else + if not animated and not textEnabled and string.find(sPath, ".nfp") ~= #sPath-3 then + sPath = sPath..".nfp" + elseif animated and string.find(sPath, ".nfa") ~= #sPath-3 then + sPath = sPath..".nfa" + elseif textEnabled and string.find(sPath, ".nft") ~= #sPath-3 then + sPath = sPath..".nft" + end +end + +drawLogo() +init() +handleEvents() + +term.setBackgroundColour(colours.black) +shell.run("clear") \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/lua/treasure/vilsol/gameoflife/gameoflife b/src/main/resources/assets/computercraft/lua/treasure/vilsol/gameoflife/gameoflife new file mode 100755 index 0000000000..09c0cb40e7 --- /dev/null +++ b/src/main/resources/assets/computercraft/lua/treasure/vilsol/gameoflife/gameoflife @@ -0,0 +1,178 @@ +board = {} +tArgs = { ... } +generation = 0 +sleeptime = 0.5 + +if(tArgs[1] == "left" or tArgs[1] == "right" or tArgs[1] == "top" or tArgs[1] == "bottom" or tArgs[1] == "front" or tArgs[1] == "back")then + mon = peripheral.wrap(tArgs[1]) +else + mon = term +end + +if(mon.isColor() or mon.isColor)then + colored = true +else + colored = false +end + +w, h = mon.getSize() +for x = 1, w do + board[x] = {} + for y = 1, h do + board[x][y] = 0 + end +end + +function drawScreen() + w, h = mon.getSize() + for x = 1, w do + for y = 1, h do + nei = getNeighbours(x, y) + if(board[x][y] == 1)then + if colored then + if(nei < 2 or nei > 3)then + mon.setBackgroundColor(colors.red) + else + mon.setBackgroundColor(colors.green) + end + else + mon.setBackgroundColor(colors.white) + end + else + if colored then + if(nei == 3)then + mon.setBackgroundColor(colors.yellow) + else + mon.setBackgroundColor(colors.black) + end + else + mon.setBackgroundColor(colors.black) + end + end + mon.setCursorPos(x, y) + mon.write(" ") + end + end + mon.setCursorPos(1,1) + if colored then + mon.setTextColor(colors.blue) + end + mon.write(generation) +end + +function getNeighbours(x, y) + w, h = mon.getSize() + total = 0 + if(x > 1 and y > 1)then if(board[x-1][y-1] == 1)then total = total + 1 end end + if(y > 1)then if(board[x][y-1] == 1)then total = total + 1 end end + if(x < w and y > 1)then if(board[x+1][y-1] == 1)then total = total + 1 end end + if(x > 1)then if(board[x-1][y] == 1)then total = total + 1 end end + if(x < w)then if(board[x+1][y] == 1)then total = total + 1 end end + if(x > 1 and y < h)then if(board[x-1][y+1] == 1)then total = total + 1 end end + if(y < h)then if(board[x][y+1] == 1)then total = total + 1 end end + if(x < w and y < h)then if(board[x+1][y+1] == 1)then total = total + 1 end end + return total +end + +function compute() + w, h = mon.getSize() + while true do + newBoard = {} + for x = 1, w do + newBoard[x] = {} + for y = 1, h do + nei = getNeighbours(x, y) + if(board[x][y] == 1)then + if(nei < 2)then + newBoard[x][y] = 0 + elseif(nei > 3)then + newBoard[x][y] = 0 + else + newBoard[x][y] = 1 + end + else + if(nei == 3)then + newBoard[x][y] = 1 + end + end + end + end + board = newBoard + generation = generation + 1 + sleep(sleeptime) + end +end + +function loop() + while true do + event, variable, xPos, yPos = os.pullEvent() + if event == "mouse_click" or event == "monitor_touch" or event == "mouse_drag" then + if variable == 1 then + board[xPos][yPos] = 1 + else + board[xPos][yPos] = 0 + end + end + if event == "key" then + if tostring(variable) == "28" then + return true + elseif tostring(variable) == "57" then + if(mon.isColor() or mon.isColor)then + colored = not colored + end + elseif tostring(variable) == "200" then + if sleeptime > 0.1 then + sleeptime = sleeptime - 0.1 + end + elseif tostring(variable) == "208" then + if sleeptime < 1 then + sleeptime = sleeptime + 0.1 + end + end + end + drawScreen() + end +end + +function intro() + mon.setBackgroundColor(colors.black) + mon.clear() + mon.setCursorPos(1,1) + mon.write("Conway's Game Of Life") + mon.setCursorPos(1,2) + mon.write("It is a game which represents life.") + mon.setCursorPos(1,3) + mon.write("The game runs by 4 basic rules:") + mon.setCursorPos(1,4) + mon.write("1. If a cell has less than 2 neighbours, it dies.") + mon.setCursorPos(1,5) + mon.write("2. If a cell has 2 or 3 neightbours, it lives.") + mon.setCursorPos(1,6) + mon.write("3. If a cell has more than 3 neighbours, it dies.") + mon.setCursorPos(1,7) + mon.write("4. If a cell has exactly 3 neighbours it is born.") + mon.setCursorPos(1,9) + mon.write("At the top left is the generation count.") + mon.setCursorPos(1,10) + mon.write("Press spacebar to switch between color modes") + mon.setCursorPos(1,11) + mon.write("Press enter to start the game") + mon.setCursorPos(1,13) + mon.write("Colors:") + mon.setCursorPos(1,14) + mon.write("Red - Cell will die in next generation") + mon.setCursorPos(1,15) + mon.write("Green - Cell will live in next generation") + mon.setCursorPos(1,16) + mon.write("Yellow - Cell will be born in next generation") + mon.setCursorPos(1,18) + mon.write("Press any key to continue!") + event, variable, xPos, yPos = os.pullEvent("key") +end + +intro() +drawScreen() +while true do + loop() + parallel.waitForAny(loop, compute) +end \ No newline at end of file diff --git a/src/main/resources/assets/computercraft/models/block/advanced_computer_blinking.json b/src/main/resources/assets/computercraft/models/block/advanced_computer_blinking.json new file mode 100644 index 0000000000..12f3740189 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_computer_blinking.json @@ -0,0 +1,8 @@ +{ + "parent": "block/orientable", + "textures": { + "front": "computercraft:blocks/computerFrontBlinkAdvanced", + "side": "computercraft:blocks/computerSideAdvanced", + "top": "computercraft:blocks/computerTopAdvanced" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_computer_off.json b/src/main/resources/assets/computercraft/models/block/advanced_computer_off.json new file mode 100644 index 0000000000..43add357fd --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_computer_off.json @@ -0,0 +1,8 @@ +{ + "parent": "block/orientable", + "textures": { + "front": "computercraft:blocks/computerFrontAdvanced", + "side": "computercraft:blocks/computerSideAdvanced", + "top": "computercraft:blocks/computerTopAdvanced" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_computer_on.json b/src/main/resources/assets/computercraft/models/block/advanced_computer_on.json new file mode 100644 index 0000000000..bfaf36dab3 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_computer_on.json @@ -0,0 +1,8 @@ +{ + "parent": "block/orientable", + "textures": { + "front": "computercraft:blocks/computerFrontOnAdvanced", + "side": "computercraft:blocks/computerSideAdvanced", + "top": "computercraft:blocks/computerTopAdvanced" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_modem_off.json b/src/main/resources/assets/computercraft/models/block/advanced_modem_off.json new file mode 100644 index 0000000000..e2d8bcfad5 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_modem_off.json @@ -0,0 +1,7 @@ +{ + "parent": "computercraft:block/modem", + "textures": { + "front": "computercraft:blocks/advModemFace", + "back": "computercraft:blocks/modemBack" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_modem_on.json b/src/main/resources/assets/computercraft/models/block/advanced_modem_on.json new file mode 100644 index 0000000000..cd83a895e4 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_modem_on.json @@ -0,0 +1,7 @@ +{ + "parent": "computercraft:block/modem", + "textures": { + "front": "computercraft:blocks/advModemFaceOn", + "back": "computercraft:blocks/modemBack" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_monitor.json b/src/main/resources/assets/computercraft/models/block/advanced_monitor.json new file mode 100644 index 0000000000..c18bd55ed5 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_monitor.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/advMonitor16", + "side": "computercraft:blocks/advMonitor4", + "top": "computercraft:blocks/advMonitor0", + "back": "computercraft:blocks/advMonitor4" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_monitor_d.json b/src/main/resources/assets/computercraft/models/block/advanced_monitor_d.json new file mode 100644 index 0000000000..e238577018 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_monitor_d.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/advMonitor20", + "side": "computercraft:blocks/advMonitor36", + "top": "computercraft:blocks/advMonitor0", + "back": "computercraft:blocks/advMonitor36" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_monitor_item.json b/src/main/resources/assets/computercraft/models/block/advanced_monitor_item.json new file mode 100644 index 0000000000..d92b505dce --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_monitor_item.json @@ -0,0 +1,8 @@ +{ + "parent": "block/orientable", + "textures": { + "front": "computercraft:blocks/advMonitor15", + "side": "computercraft:blocks/advMonitor4", + "top": "computercraft:blocks/advMonitor0" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_monitor_l.json b/src/main/resources/assets/computercraft/models/block/advanced_monitor_l.json new file mode 100644 index 0000000000..1740a6a4c6 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_monitor_l.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/advMonitor19", + "side": "computercraft:blocks/advMonitor4", + "top": "computercraft:blocks/advMonitor1", + "back": "computercraft:blocks/advMonitor33" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_monitor_ld.json b/src/main/resources/assets/computercraft/models/block/advanced_monitor_ld.json new file mode 100644 index 0000000000..711794cc84 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_monitor_ld.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/advMonitor31", + "side": "computercraft:blocks/advMonitor7", + "top": "computercraft:blocks/advMonitor1", + "back": "computercraft:blocks/advMonitor45" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_monitor_lr.json b/src/main/resources/assets/computercraft/models/block/advanced_monitor_lr.json new file mode 100644 index 0000000000..8698bf3f99 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_monitor_lr.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/advMonitor18", + "side": "computercraft:blocks/advMonitor4", + "top": "computercraft:blocks/advMonitor2", + "back": "computercraft:blocks/advMonitor34" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_monitor_lrd.json b/src/main/resources/assets/computercraft/models/block/advanced_monitor_lrd.json new file mode 100644 index 0000000000..01aff96e37 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_monitor_lrd.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/advMonitor30", + "side": "computercraft:blocks/advMonitor7", + "top": "computercraft:blocks/advMonitor2", + "back": "computercraft:blocks/advMonitor46" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_monitor_lru.json b/src/main/resources/assets/computercraft/models/block/advanced_monitor_lru.json new file mode 100644 index 0000000000..7883be2fc8 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_monitor_lru.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/advMonitor24", + "side": "computercraft:blocks/advMonitor38", + "top": "computercraft:blocks/advMonitor2", + "back": "computercraft:blocks/advMonitor40" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_monitor_lrud.json b/src/main/resources/assets/computercraft/models/block/advanced_monitor_lrud.json new file mode 100644 index 0000000000..f87133e9ac --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_monitor_lrud.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/advMonitor27", + "side": "computercraft:blocks/advMonitor37", + "top": "computercraft:blocks/advMonitor2", + "back": "computercraft:blocks/advMonitor43" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_monitor_lu.json b/src/main/resources/assets/computercraft/models/block/advanced_monitor_lu.json new file mode 100644 index 0000000000..b01a72f6c4 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_monitor_lu.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/advMonitor25", + "side": "computercraft:blocks/advMonitor38", + "top": "computercraft:blocks/advMonitor1", + "back": "computercraft:blocks/advMonitor39" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_monitor_lud.json b/src/main/resources/assets/computercraft/models/block/advanced_monitor_lud.json new file mode 100644 index 0000000000..75e1d39540 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_monitor_lud.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/advMonitor28", + "side": "computercraft:blocks/advMonitor37", + "top": "computercraft:blocks/advMonitor1", + "back": "computercraft:blocks/advMonitor42" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_monitor_r.json b/src/main/resources/assets/computercraft/models/block/advanced_monitor_r.json new file mode 100644 index 0000000000..81869bee0e --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_monitor_r.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/advMonitor17", + "side": "computercraft:blocks/advMonitor4", + "top": "computercraft:blocks/advMonitor3", + "back": "computercraft:blocks/advMonitor35" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_monitor_rd.json b/src/main/resources/assets/computercraft/models/block/advanced_monitor_rd.json new file mode 100644 index 0000000000..1a5e3243e0 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_monitor_rd.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/advMonitor29", + "side": "computercraft:blocks/advMonitor7", + "top": "computercraft:blocks/advMonitor3", + "back": "computercraft:blocks/advMonitor47" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_monitor_ru.json b/src/main/resources/assets/computercraft/models/block/advanced_monitor_ru.json new file mode 100644 index 0000000000..cb1059007a --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_monitor_ru.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/advMonitor23", + "side": "computercraft:blocks/advMonitor38", + "top": "computercraft:blocks/advMonitor3", + "back": "computercraft:blocks/advMonitor41" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_monitor_rud.json b/src/main/resources/assets/computercraft/models/block/advanced_monitor_rud.json new file mode 100644 index 0000000000..30a0b668af --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_monitor_rud.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/advMonitor26", + "side": "computercraft:blocks/advMonitor37", + "top": "computercraft:blocks/advMonitor3", + "back": "computercraft:blocks/advMonitor44" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_monitor_u.json b/src/main/resources/assets/computercraft/models/block/advanced_monitor_u.json new file mode 100644 index 0000000000..a0a440529c --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_monitor_u.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/advMonitor22", + "side": "computercraft:blocks/advMonitor38", + "top": "computercraft:blocks/advMonitor0", + "back": "computercraft:blocks/advMonitor38" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_monitor_ud.json b/src/main/resources/assets/computercraft/models/block/advanced_monitor_ud.json new file mode 100644 index 0000000000..c5865f6aa5 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_monitor_ud.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/advMonitor21", + "side": "computercraft:blocks/advMonitor37", + "top": "computercraft:blocks/advMonitor0", + "back": "computercraft:blocks/advMonitor37" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_turtle.json b/src/main/resources/assets/computercraft/models/block/advanced_turtle.json new file mode 100644 index 0000000000..e8d8166024 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_turtle.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_base", + "textures": { + "texture": "computercraft:blocks/turtleAdvanced" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_turtle_modem_off_left.json b/src/main/resources/assets/computercraft/models/block/advanced_turtle_modem_off_left.json new file mode 100644 index 0000000000..269a54fae0 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_turtle_modem_off_left.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_upgrade_base_left", + "textures": { + "texture": "computercraft:blocks/advModemFace" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_turtle_modem_off_right.json b/src/main/resources/assets/computercraft/models/block/advanced_turtle_modem_off_right.json new file mode 100644 index 0000000000..539624390b --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_turtle_modem_off_right.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_upgrade_base_right", + "textures": { + "texture": "computercraft:blocks/advModemFace" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_turtle_modem_on_left.json b/src/main/resources/assets/computercraft/models/block/advanced_turtle_modem_on_left.json new file mode 100644 index 0000000000..2266aa126b --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_turtle_modem_on_left.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_upgrade_base_left", + "textures": { + "texture": "computercraft:blocks/advModemFaceOn" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/advanced_turtle_modem_on_right.json b/src/main/resources/assets/computercraft/models/block/advanced_turtle_modem_on_right.json new file mode 100644 index 0000000000..b5145d8254 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/advanced_turtle_modem_on_right.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_upgrade_base_right", + "textures": { + "texture": "computercraft:blocks/advModemFaceOn" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/cable_arm.json b/src/main/resources/assets/computercraft/models/block/cable_arm.json new file mode 100644 index 0000000000..8b90234b97 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/cable_arm.json @@ -0,0 +1,18 @@ +{ + "textures": { + "particle": "computercraft:blocks/cableCore", + "side": "computercraft:blocks/cableSide" + }, + "elements": [ + { + "from": [ 6, 6, 10 ], + "to": [ 10, 10, 16 ], + "faces": { + "down": { "uv": [ 6, 0, 10, 6 ], "texture": "#side" }, + "up": { "uv": [ 6, 10, 10, 16 ], "texture": "#side" }, + "west": { "uv": [ 0, 6, 6, 10 ], "texture": "#side" }, + "east": { "uv": [ 10, 6, 16, 10 ], "texture": "#side" } + } + } + ] +} diff --git a/src/main/resources/assets/computercraft/models/block/cable_core.json b/src/main/resources/assets/computercraft/models/block/cable_core.json new file mode 100644 index 0000000000..5c5d1b390e --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/cable_core.json @@ -0,0 +1,21 @@ +{ + "textures": { + "particle": "computercraft:blocks/cableCore", + "side": "computercraft:blocks/cableSide", + "end": "computercraft:blocks/cableCore" + }, + "elements": [ + { + "from": [ 6, 6, 6 ], + "to": [ 10, 10, 10 ], + "faces": { + "down": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" }, + "up": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" }, + "north": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" }, + "south": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" }, + "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" }, + "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" } + } + } + ] +} diff --git a/src/main/resources/assets/computercraft/models/block/cable_item.json b/src/main/resources/assets/computercraft/models/block/cable_item.json new file mode 100644 index 0000000000..56402f75e8 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/cable_item.json @@ -0,0 +1,21 @@ +{ + "textures": { + "particle": "computercraft:blocks/cableCore", + "side": "computercraft:blocks/cableSide", + "end": "computercraft:blocks/cableCore" + }, + "elements": [ + { + "from": [ 6, 6, 2 ], + "to": [ 10, 10, 14 ], + "faces": { + "down": { "uv": [ 6, 2, 10, 14 ], "texture": "#side" }, + "up": { "uv": [ 6, 2, 10, 14 ], "texture": "#side" }, + "north": { "uv": [ 6, 6, 10, 10 ], "texture": "#end" }, + "south": { "uv": [ 6, 6, 10, 10 ], "texture": "#end" }, + "west": { "uv": [ 2, 6, 14, 10 ], "texture": "#side" }, + "east": { "uv": [ 2, 6, 14, 10 ], "texture": "#side" } + } + } + ] +} diff --git a/src/main/resources/assets/computercraft/models/block/command_computer_blinking.json b/src/main/resources/assets/computercraft/models/block/command_computer_blinking.json new file mode 100644 index 0000000000..4585295c73 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/command_computer_blinking.json @@ -0,0 +1,8 @@ +{ + "parent": "block/orientable", + "textures": { + "front": "computercraft:blocks/commandComputerFrontBlink", + "side": "computercraft:blocks/commandComputerSide", + "top": "computercraft:blocks/commandComputerTop" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/command_computer_off.json b/src/main/resources/assets/computercraft/models/block/command_computer_off.json new file mode 100644 index 0000000000..98b96cf827 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/command_computer_off.json @@ -0,0 +1,8 @@ +{ + "parent": "block/orientable", + "textures": { + "front": "computercraft:blocks/commandComputerFront", + "side": "computercraft:blocks/commandComputerSide", + "top": "computercraft:blocks/commandComputerTop" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/command_computer_on.json b/src/main/resources/assets/computercraft/models/block/command_computer_on.json new file mode 100644 index 0000000000..8ca5ad6d81 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/command_computer_on.json @@ -0,0 +1,8 @@ +{ + "parent": "block/orientable", + "textures": { + "front": "computercraft:blocks/commandComputerFrontOn", + "side": "computercraft:blocks/commandComputerSide", + "top": "computercraft:blocks/commandComputerTop" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/computer_blinking.json b/src/main/resources/assets/computercraft/models/block/computer_blinking.json new file mode 100644 index 0000000000..b5341ebb49 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/computer_blinking.json @@ -0,0 +1,8 @@ +{ + "parent": "block/orientable", + "textures": { + "front": "computercraft:blocks/computerFrontBlink", + "side": "computercraft:blocks/computerSide", + "top": "computercraft:blocks/computerTop" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/computer_off.json b/src/main/resources/assets/computercraft/models/block/computer_off.json new file mode 100644 index 0000000000..b9aa5b8295 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/computer_off.json @@ -0,0 +1,8 @@ +{ + "parent": "block/orientable", + "textures": { + "front": "computercraft:blocks/computerFront", + "side": "computercraft:blocks/computerSide", + "top": "computercraft:blocks/computerTop" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/computer_on.json b/src/main/resources/assets/computercraft/models/block/computer_on.json new file mode 100644 index 0000000000..eda62dac19 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/computer_on.json @@ -0,0 +1,8 @@ +{ + "parent": "block/orientable", + "textures": { + "front": "computercraft:blocks/computerFrontOn", + "side": "computercraft:blocks/computerSide", + "top": "computercraft:blocks/computerTop" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/disk_drive_empty.json b/src/main/resources/assets/computercraft/models/block/disk_drive_empty.json new file mode 100644 index 0000000000..6737de8f86 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/disk_drive_empty.json @@ -0,0 +1,8 @@ +{ + "parent": "block/orientable", + "textures": { + "front": "computercraft:blocks/diskDriveFront", + "side": "computercraft:blocks/diskDriveSide", + "top": "computercraft:blocks/diskDriveTop" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/disk_drive_full.json b/src/main/resources/assets/computercraft/models/block/disk_drive_full.json new file mode 100644 index 0000000000..c7b8b76ec1 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/disk_drive_full.json @@ -0,0 +1,8 @@ +{ + "parent": "block/orientable", + "textures": { + "front": "computercraft:blocks/diskDriveFrontAccepted", + "side": "computercraft:blocks/diskDriveSide", + "top": "computercraft:blocks/diskDriveTop" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/disk_drive_invalid.json b/src/main/resources/assets/computercraft/models/block/disk_drive_invalid.json new file mode 100644 index 0000000000..07ed3a1e26 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/disk_drive_invalid.json @@ -0,0 +1,8 @@ +{ + "parent": "block/orientable", + "textures": { + "front": "computercraft:blocks/diskDriveFrontRejected", + "side": "computercraft:blocks/diskDriveSide", + "top": "computercraft:blocks/diskDriveTop" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/modem.json b/src/main/resources/assets/computercraft/models/block/modem.json new file mode 100644 index 0000000000..ecfc3d4881 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/modem.json @@ -0,0 +1,19 @@ +{ + "textures": { + "particle": "#front" + }, + "elements": [ + { + "from": [ 2, 2, 0 ], + "to": [ 14, 14, 3 ], + "faces": { + "down": { "uv": [ 2, 13, 14, 16 ], "texture": "#front" }, + "up": { "uv": [ 2, 0, 14, 3 ], "texture": "#front" }, + "north": { "uv": [ 2, 2, 14, 14 ], "texture": "#back" }, + "south": { "uv": [ 2, 2, 14, 14 ], "texture": "#front" }, + "west": { "uv": [ 0, 2, 3, 14 ], "texture": "#front" }, + "east": { "uv": [ 13, 2, 16, 14 ], "texture": "#front" } + } + } + ] +} diff --git a/src/main/resources/assets/computercraft/models/block/monitor.json b/src/main/resources/assets/computercraft/models/block/monitor.json new file mode 100644 index 0000000000..6a01fce693 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/monitor.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/monitor16", + "side": "computercraft:blocks/monitor4", + "top": "computercraft:blocks/monitor0", + "back": "computercraft:blocks/monitor4" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/monitor_base.json b/src/main/resources/assets/computercraft/models/block/monitor_base.json new file mode 100644 index 0000000000..726cb2f87f --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/monitor_base.json @@ -0,0 +1,12 @@ +{ + "parent": "block/cube", + "textures": { + "particle": "#front", + "down": "#top", + "up": "#top", + "north": "#front", + "east": "#side", + "south": "#back", + "west": "#side" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/monitor_d.json b/src/main/resources/assets/computercraft/models/block/monitor_d.json new file mode 100644 index 0000000000..098491b1b9 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/monitor_d.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/monitor20", + "side": "computercraft:blocks/monitor36", + "top": "computercraft:blocks/monitor0", + "back": "computercraft:blocks/monitor36" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/monitor_item.json b/src/main/resources/assets/computercraft/models/block/monitor_item.json new file mode 100644 index 0000000000..5c7818a8c7 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/monitor_item.json @@ -0,0 +1,8 @@ +{ + "parent": "block/orientable", + "textures": { + "front": "computercraft:blocks/monitor15", + "side": "computercraft:blocks/monitor4", + "top": "computercraft:blocks/monitor0" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/monitor_l.json b/src/main/resources/assets/computercraft/models/block/monitor_l.json new file mode 100644 index 0000000000..1a8fc4efed --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/monitor_l.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/monitor19", + "side": "computercraft:blocks/monitor4", + "top": "computercraft:blocks/monitor1", + "back": "computercraft:blocks/monitor33" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/monitor_ld.json b/src/main/resources/assets/computercraft/models/block/monitor_ld.json new file mode 100644 index 0000000000..b3e0fb4af1 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/monitor_ld.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/monitor31", + "side": "computercraft:blocks/monitor7", + "top": "computercraft:blocks/monitor1", + "back": "computercraft:blocks/monitor45" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/monitor_lr.json b/src/main/resources/assets/computercraft/models/block/monitor_lr.json new file mode 100644 index 0000000000..36ebb5a0c6 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/monitor_lr.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/monitor18", + "side": "computercraft:blocks/monitor4", + "top": "computercraft:blocks/monitor2", + "back": "computercraft:blocks/monitor34" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/monitor_lrd.json b/src/main/resources/assets/computercraft/models/block/monitor_lrd.json new file mode 100644 index 0000000000..d8a0b0f684 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/monitor_lrd.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/monitor30", + "side": "computercraft:blocks/monitor7", + "top": "computercraft:blocks/monitor2", + "back": "computercraft:blocks/monitor46" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/monitor_lru.json b/src/main/resources/assets/computercraft/models/block/monitor_lru.json new file mode 100644 index 0000000000..f175842b4b --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/monitor_lru.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/monitor24", + "side": "computercraft:blocks/monitor38", + "top": "computercraft:blocks/monitor2", + "back": "computercraft:blocks/monitor40" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/monitor_lrud.json b/src/main/resources/assets/computercraft/models/block/monitor_lrud.json new file mode 100644 index 0000000000..03a0f1e130 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/monitor_lrud.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/monitor27", + "side": "computercraft:blocks/monitor37", + "top": "computercraft:blocks/monitor2", + "back": "computercraft:blocks/monitor43" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/monitor_lu.json b/src/main/resources/assets/computercraft/models/block/monitor_lu.json new file mode 100644 index 0000000000..9e2ca965e9 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/monitor_lu.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/monitor25", + "side": "computercraft:blocks/monitor38", + "top": "computercraft:blocks/monitor1", + "back": "computercraft:blocks/monitor39" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/monitor_lud.json b/src/main/resources/assets/computercraft/models/block/monitor_lud.json new file mode 100644 index 0000000000..d5b59ecc20 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/monitor_lud.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/monitor28", + "side": "computercraft:blocks/monitor37", + "top": "computercraft:blocks/monitor1", + "back": "computercraft:blocks/monitor42" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/monitor_r.json b/src/main/resources/assets/computercraft/models/block/monitor_r.json new file mode 100644 index 0000000000..2205b51234 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/monitor_r.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/monitor17", + "side": "computercraft:blocks/monitor4", + "top": "computercraft:blocks/monitor3", + "back": "computercraft:blocks/monitor35" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/monitor_rd.json b/src/main/resources/assets/computercraft/models/block/monitor_rd.json new file mode 100644 index 0000000000..4022ecd65f --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/monitor_rd.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/monitor29", + "side": "computercraft:blocks/monitor7", + "top": "computercraft:blocks/monitor3", + "back": "computercraft:blocks/monitor47" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/monitor_ru.json b/src/main/resources/assets/computercraft/models/block/monitor_ru.json new file mode 100644 index 0000000000..2ec567e240 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/monitor_ru.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/monitor23", + "side": "computercraft:blocks/monitor38", + "top": "computercraft:blocks/monitor3", + "back": "computercraft:blocks/monitor41" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/monitor_rud.json b/src/main/resources/assets/computercraft/models/block/monitor_rud.json new file mode 100644 index 0000000000..d6fe964820 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/monitor_rud.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/monitor26", + "side": "computercraft:blocks/monitor37", + "top": "computercraft:blocks/monitor3", + "back": "computercraft:blocks/monitor44" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/monitor_u.json b/src/main/resources/assets/computercraft/models/block/monitor_u.json new file mode 100644 index 0000000000..24c2a904b3 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/monitor_u.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/monitor22", + "side": "computercraft:blocks/monitor38", + "top": "computercraft:blocks/monitor0", + "back": "computercraft:blocks/monitor38" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/monitor_ud.json b/src/main/resources/assets/computercraft/models/block/monitor_ud.json new file mode 100644 index 0000000000..771db2f18e --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/monitor_ud.json @@ -0,0 +1,9 @@ +{ + "parent": "computercraft:block/monitor_base", + "textures": { + "front": "computercraft:blocks/monitor21", + "side": "computercraft:blocks/monitor37", + "top": "computercraft:blocks/monitor0", + "back": "computercraft:blocks/monitor37" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/printer_both_full.json b/src/main/resources/assets/computercraft/models/block/printer_both_full.json new file mode 100644 index 0000000000..8904ba5099 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/printer_both_full.json @@ -0,0 +1,8 @@ +{ + "parent": "block/orientable", + "textures": { + "front": "computercraft:blocks/printerFrontBothTrays", + "side": "computercraft:blocks/printerSide", + "top": "computercraft:blocks/printerTop" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/printer_bottom_full.json b/src/main/resources/assets/computercraft/models/block/printer_bottom_full.json new file mode 100644 index 0000000000..8fafa91d58 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/printer_bottom_full.json @@ -0,0 +1,8 @@ +{ + "parent": "block/orientable", + "textures": { + "front": "computercraft:blocks/printerFrontBottomTray", + "side": "computercraft:blocks/printerSide", + "top": "computercraft:blocks/printerTop" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/printer_empty.json b/src/main/resources/assets/computercraft/models/block/printer_empty.json new file mode 100644 index 0000000000..1219ac2d4f --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/printer_empty.json @@ -0,0 +1,8 @@ +{ + "parent": "block/orientable", + "textures": { + "front": "computercraft:blocks/printerFrontEmpty", + "side": "computercraft:blocks/printerSide", + "top": "computercraft:blocks/printerTop" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/printer_top_full.json b/src/main/resources/assets/computercraft/models/block/printer_top_full.json new file mode 100644 index 0000000000..de2fafae5f --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/printer_top_full.json @@ -0,0 +1,8 @@ +{ + "parent": "block/orientable", + "textures": { + "front": "computercraft:blocks/printerFrontTopTray", + "side": "computercraft:blocks/printerSide", + "top": "computercraft:blocks/printerTop" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle.json b/src/main/resources/assets/computercraft/models/block/turtle.json new file mode 100644 index 0000000000..b0be215517 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_base", + "textures": { + "texture": "computercraft:blocks/turtle" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_base.json b/src/main/resources/assets/computercraft/models/block/turtle_base.json new file mode 100644 index 0000000000..0806a29f63 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_base.json @@ -0,0 +1,30 @@ +{ + "textures": { + "particle": "#texture" + }, + "elements": [ + { + "from": [ 2, 2, 2 ], + "to": [ 14, 14, 13 ], + "faces": { + "down": { "uv": [ 2.75, 0, 5.75, 2.75 ], "texture": "#texture" }, + "up": { "uv": [ 5.75, 0, 8.75, 2.75 ], "texture": "#texture" }, + "north": { "uv": [ 8.5, 5.75, 11.5, 2.75 ], "texture": "#texture" }, + "south": { "uv": [ 2.75, 5.75, 5.75, 2.75 ], "texture": "#texture" }, + "west": { "uv": [ 0, 5.75, 2.75, 2.75 ], "texture": "#texture" }, + "east": { "uv": [ 5.75, 5.75, 8.5, 2.75 ], "texture": "#texture" } + } + }, + { + "from": [ 3, 6, 13 ], + "to": [ 13, 13, 15 ], + "faces": { + "down": { "uv": [ 9.25, 0, 11.75, 0.5 ], "texture": "#texture" }, + "up": { "uv": [ 11.75, 0, 14.25, 0.5 ], "texture": "#texture" }, + "south": { "uv": [ 9.25, 2.25, 11.75, 0.5 ], "texture": "#texture" }, + "west": { "uv": [ 8.75, 2.25, 9.25, 0.5 ], "texture": "#texture" }, + "east": { "uv": [ 11.75, 2.25, 12.25, 0.5 ], "texture": "#texture" } + } + } + ] +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_black.json b/src/main/resources/assets/computercraft/models/block/turtle_black.json new file mode 100644 index 0000000000..7566f4735a --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_black.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_base", + "textures": { + "texture": "computercraft:blocks/turtle_black" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_blue.json b/src/main/resources/assets/computercraft/models/block/turtle_blue.json new file mode 100644 index 0000000000..8b1eb82ebb --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_blue.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_base", + "textures": { + "texture": "computercraft:blocks/turtle_blue" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_brown.json b/src/main/resources/assets/computercraft/models/block/turtle_brown.json new file mode 100644 index 0000000000..3d26bf56f3 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_brown.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_base", + "textures": { + "texture": "computercraft:blocks/turtle_brown" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_crafting_table_left.json b/src/main/resources/assets/computercraft/models/block/turtle_crafting_table_left.json new file mode 100644 index 0000000000..0a210e19b0 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_crafting_table_left.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_upgrade_base_left", + "textures": { + "texture": "computercraft:blocks/craftyUpgrade" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_crafting_table_right.json b/src/main/resources/assets/computercraft/models/block/turtle_crafting_table_right.json new file mode 100644 index 0000000000..209b0ca9de --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_crafting_table_right.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_upgrade_base_right", + "textures": { + "texture": "computercraft:blocks/craftyUpgrade" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_cyan.json b/src/main/resources/assets/computercraft/models/block/turtle_cyan.json new file mode 100644 index 0000000000..b06fc173f2 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_cyan.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_base", + "textures": { + "texture": "computercraft:blocks/turtle_cyan" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_elf_overlay.json b/src/main/resources/assets/computercraft/models/block/turtle_elf_overlay.json new file mode 100644 index 0000000000..48a769c791 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_elf_overlay.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_overlay", + "textures": { + "texture": "computercraft:blocks/turtle_elf_overlay" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_green.json b/src/main/resources/assets/computercraft/models/block/turtle_green.json new file mode 100644 index 0000000000..81d1ecdc90 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_green.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_base", + "textures": { + "texture": "computercraft:blocks/turtle_green" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_grey.json b/src/main/resources/assets/computercraft/models/block/turtle_grey.json new file mode 100644 index 0000000000..9ce78eb333 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_grey.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_base", + "textures": { + "texture": "computercraft:blocks/turtle_grey" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_lightBlue.json b/src/main/resources/assets/computercraft/models/block/turtle_lightBlue.json new file mode 100644 index 0000000000..1694ee61c4 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_lightBlue.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_base", + "textures": { + "texture": "computercraft:blocks/turtle_lightBlue" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_lightGrey.json b/src/main/resources/assets/computercraft/models/block/turtle_lightGrey.json new file mode 100644 index 0000000000..7ba39bc38d --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_lightGrey.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_base", + "textures": { + "texture": "computercraft:blocks/turtle_lightGrey" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_lime.json b/src/main/resources/assets/computercraft/models/block/turtle_lime.json new file mode 100644 index 0000000000..2225efb8e7 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_lime.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_base", + "textures": { + "texture": "computercraft:blocks/turtle_lime" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_magenta.json b/src/main/resources/assets/computercraft/models/block/turtle_magenta.json new file mode 100644 index 0000000000..624a175ee2 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_magenta.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_base", + "textures": { + "texture": "computercraft:blocks/turtle_magenta" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_modem_off_left.json b/src/main/resources/assets/computercraft/models/block/turtle_modem_off_left.json new file mode 100644 index 0000000000..71f26257bb --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_modem_off_left.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_upgrade_base_left", + "textures": { + "texture": "computercraft:blocks/wirelessModemFace" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_modem_off_right.json b/src/main/resources/assets/computercraft/models/block/turtle_modem_off_right.json new file mode 100644 index 0000000000..c7226547a5 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_modem_off_right.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_upgrade_base_right", + "textures": { + "texture": "computercraft:blocks/wirelessModemFace" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_modem_on_left.json b/src/main/resources/assets/computercraft/models/block/turtle_modem_on_left.json new file mode 100644 index 0000000000..4ced138f48 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_modem_on_left.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_upgrade_base_left", + "textures": { + "texture": "computercraft:blocks/wirelessModemFaceOn" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_modem_on_right.json b/src/main/resources/assets/computercraft/models/block/turtle_modem_on_right.json new file mode 100644 index 0000000000..ada1a6d8cf --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_modem_on_right.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_upgrade_base_right", + "textures": { + "texture": "computercraft:blocks/wirelessModemFaceOn" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_orange.json b/src/main/resources/assets/computercraft/models/block/turtle_orange.json new file mode 100644 index 0000000000..511805d73f --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_orange.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_base", + "textures": { + "texture": "computercraft:blocks/turtle_orange" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_overlay.json b/src/main/resources/assets/computercraft/models/block/turtle_overlay.json new file mode 100644 index 0000000000..3d5f528513 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_overlay.json @@ -0,0 +1,42 @@ +{ + "textures": { + "particle": "#texture" + }, + "elements": [ + { + "from": [ 2, 2, 2 ], + "to": [ 14, 14, 13 ], + "faces": { + "down": { "uv": [ 2.75, 0, 5.75, 2.75 ], "texture": "#texture" }, + "up": { "uv": [ 5.75, 0, 8.75, 2.75 ], "texture": "#texture" }, + "north": { "uv": [ 8.5, 5.75, 11.5, 2.75 ], "texture": "#texture" }, + "south": { "uv": [ 2.75, 5.75, 5.75, 2.75 ], "texture": "#texture" }, + "west": { "uv": [ 0, 5.75, 2.75, 2.75 ], "texture": "#texture" }, + "east": { "uv": [ 5.75, 5.75, 8.5, 2.75 ], "texture": "#texture" } + } + }, + { + "from": [ 3, 6, 13 ], + "to": [ 13, 13, 15 ], + "faces": { + "down": { "uv": [ 9.25, 0, 11.75, 0.5 ], "texture": "#texture" }, + "up": { "uv": [ 11.75, 0, 14.25, 0.5 ], "texture": "#texture" }, + "south": { "uv": [ 9.25, 2.25, 11.75, 0.5 ], "texture": "#texture" }, + "west": { "uv": [ 8.75, 2.25, 9.25, 0.5 ], "texture": "#texture" }, + "east": { "uv": [ 11.75, 2.25, 12.25, 0.5 ], "texture": "#texture" } + } + }, + { + "from": [ 1.5, 1.5, 1.5 ], + "to": [ 14.5, 14.5, 13.5 ], + "faces": { + "down": { "uv": [ 2.75, 8, 5.75, 10.75 ], "texture": "#texture" }, + "up": { "uv": [ 5.75, 8, 8.75, 10.75 ], "texture": "#texture" }, + "north": { "uv": [ 8.5, 13.75, 11.5, 10.75 ], "texture": "#texture" }, + "south": { "uv": [ 2.75, 13.75, 5.75, 10.75 ], "texture": "#texture" }, + "west": { "uv": [ 0, 13.75, 2.75, 10.75 ], "texture": "#texture" }, + "east": { "uv": [ 5.75, 13.75, 8.5, 10.75 ], "texture": "#texture" } + } + } + ] +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_pink.json b/src/main/resources/assets/computercraft/models/block/turtle_pink.json new file mode 100644 index 0000000000..de81ce1fb5 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_pink.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_base", + "textures": { + "texture": "computercraft:blocks/turtle_pink" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_purple.json b/src/main/resources/assets/computercraft/models/block/turtle_purple.json new file mode 100644 index 0000000000..52bc838b1e --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_purple.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_base", + "textures": { + "texture": "computercraft:blocks/turtle_purple" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_red.json b/src/main/resources/assets/computercraft/models/block/turtle_red.json new file mode 100644 index 0000000000..410e67c099 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_red.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_base", + "textures": { + "texture": "computercraft:blocks/turtle_red" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_upgrade_base_left.json b/src/main/resources/assets/computercraft/models/block/turtle_upgrade_base_left.json new file mode 100644 index 0000000000..7880d2f308 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_upgrade_base_left.json @@ -0,0 +1,18 @@ +{ + "textures": { + "particle": "#texture" + }, + "elements": [ + { + "from": [ 0.5, 4.5, 3.5 ], + "to": [ 2, 12.5, 11.5 ], + "faces": { + "down": { "uv": [ 13, 2, 16, 14 ], "texture": "#texture" }, + "up": { "uv": [ 13, 2, 16, 14 ], "texture": "#texture" }, + "north": { "uv": [ 0, 2, 3, 14 ], "texture": "#texture" }, + "south": { "uv": [ 13, 2, 16, 14 ], "texture": "#texture" }, + "west": { "uv": [ 2, 2, 14, 14 ], "texture": "#texture" } + } + } + ] +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_upgrade_base_right.json b/src/main/resources/assets/computercraft/models/block/turtle_upgrade_base_right.json new file mode 100644 index 0000000000..fa16f81100 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_upgrade_base_right.json @@ -0,0 +1,18 @@ +{ + "textures": { + "particle": "#texture" + }, + "elements": [ + { + "from": [ 14, 4.5, 3.5 ], + "to": [ 15.5, 12.5, 11.5 ], + "faces": { + "down": { "uv": [ 0, 2, 3, 14 ], "texture": "#texture" }, + "up": { "uv": [ 0, 2, 3, 14 ], "texture": "#texture" }, + "north": { "uv": [ 13, 2, 16, 14 ], "texture": "#texture" }, + "south": { "uv": [ 0, 2, 3, 14 ], "texture": "#texture" }, + "east": { "uv": [ 2, 2, 14, 14 ], "texture": "#texture" } + } + } + ] +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_white.json b/src/main/resources/assets/computercraft/models/block/turtle_white.json new file mode 100644 index 0000000000..41d5bcd478 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_white.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_base", + "textures": { + "texture": "computercraft:blocks/turtle_white" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/turtle_yellow.json b/src/main/resources/assets/computercraft/models/block/turtle_yellow.json new file mode 100644 index 0000000000..107df628c0 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/turtle_yellow.json @@ -0,0 +1,6 @@ +{ + "parent": "computercraft:block/turtle_base", + "textures": { + "texture": "computercraft:blocks/turtle_yellow" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/wired_modem_off.json b/src/main/resources/assets/computercraft/models/block/wired_modem_off.json new file mode 100644 index 0000000000..e6b34751ac --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/wired_modem_off.json @@ -0,0 +1,7 @@ +{ + "parent": "computercraft:block/modem", + "textures": { + "front": "computercraft:blocks/wiredModemFace", + "back": "computercraft:blocks/modemBack" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/wired_modem_off_peripheral.json b/src/main/resources/assets/computercraft/models/block/wired_modem_off_peripheral.json new file mode 100644 index 0000000000..be544bf267 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/wired_modem_off_peripheral.json @@ -0,0 +1,7 @@ +{ + "parent": "computercraft:block/modem", + "textures": { + "front": "computercraft:blocks/wiredModemFacePeripheral", + "back": "computercraft:blocks/modemBack" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/wired_modem_on.json b/src/main/resources/assets/computercraft/models/block/wired_modem_on.json new file mode 100644 index 0000000000..9ad2a5d54e --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/wired_modem_on.json @@ -0,0 +1,7 @@ +{ + "parent": "computercraft:block/modem", + "textures": { + "front": "computercraft:blocks/wiredModemFaceOn", + "back": "computercraft:blocks/modemBack" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/wired_modem_on_peripheral.json b/src/main/resources/assets/computercraft/models/block/wired_modem_on_peripheral.json new file mode 100644 index 0000000000..f7b8ecb605 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/wired_modem_on_peripheral.json @@ -0,0 +1,7 @@ +{ + "parent": "computercraft:block/modem", + "textures": { + "front": "computercraft:blocks/wiredModemFacePeripheralOn", + "back": "computercraft:blocks/modemBack" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/wireless_modem_off.json b/src/main/resources/assets/computercraft/models/block/wireless_modem_off.json new file mode 100644 index 0000000000..5b3df5bc02 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/wireless_modem_off.json @@ -0,0 +1,7 @@ +{ + "parent": "computercraft:block/modem", + "textures": { + "front": "computercraft:blocks/wirelessModemFace", + "back": "computercraft:blocks/modemBack" + } +} diff --git a/src/main/resources/assets/computercraft/models/block/wireless_modem_on.json b/src/main/resources/assets/computercraft/models/block/wireless_modem_on.json new file mode 100644 index 0000000000..2a460ce95d --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/wireless_modem_on.json @@ -0,0 +1,7 @@ +{ + "parent": "computercraft:block/modem", + "textures": { + "front": "computercraft:blocks/wirelessModemFaceOn", + "back": "computercraft:blocks/modemBack" + } +} diff --git a/src/main/resources/assets/computercraft/models/item/CC-Cable.json b/src/main/resources/assets/computercraft/models/item/CC-Cable.json new file mode 100644 index 0000000000..95f0c5bb6e --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/CC-Cable.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/cable_item", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale" : [ 1.33, 1.33, 1.33 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/CC-Computer.json b/src/main/resources/assets/computercraft/models/item/CC-Computer.json new file mode 100644 index 0000000000..a11d077666 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/CC-Computer.json @@ -0,0 +1,13 @@ +{ + "parent": "computercraft:block/computer_blinking", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/CC-Peripheral.json b/src/main/resources/assets/computercraft/models/item/CC-Peripheral.json new file mode 100644 index 0000000000..6ea7b50e72 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/CC-Peripheral.json @@ -0,0 +1,13 @@ +{ + "parent": "computercraft:block/disk_drive_empty", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/CC-Turtle.json b/src/main/resources/assets/computercraft/models/item/CC-Turtle.json new file mode 100644 index 0000000000..4485468d96 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/CC-Turtle.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/turtle", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale": [ 1.14, 1.14, 1.14 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/CC-TurtleAdvanced.json b/src/main/resources/assets/computercraft/models/item/CC-TurtleAdvanced.json new file mode 100644 index 0000000000..b939de6061 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/CC-TurtleAdvanced.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/advanced_turtle", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale": [ 1.14, 1.14, 1.14 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/CC-TurtleExpanded.json b/src/main/resources/assets/computercraft/models/item/CC-TurtleExpanded.json new file mode 100644 index 0000000000..4485468d96 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/CC-TurtleExpanded.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/turtle", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale": [ 1.14, 1.14, 1.14 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/advanced_computer.json b/src/main/resources/assets/computercraft/models/item/advanced_computer.json new file mode 100644 index 0000000000..dd39ab06e0 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/advanced_computer.json @@ -0,0 +1,13 @@ +{ + "parent": "computercraft:block/advanced_computer_blinking", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/advanced_modem.json b/src/main/resources/assets/computercraft/models/item/advanced_modem.json new file mode 100644 index 0000000000..d6ac16afa4 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/advanced_modem.json @@ -0,0 +1,20 @@ +{ + "parent": "computercraft:block/advanced_modem_off", + "display": { + "thirdperson": { + "rotation": [ -10, 180, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "firstperson": { + "rotation": [ 0, 0, 0 ], + "translation": [ 3.2, 0, 0 ], + "scale" : [ 1.33, 1.33, 1.33 ] + }, + "gui": { + "rotation": [ 0, 90, 0 ], + "translation": [ 3.2, 0, 0 ], + "scale" : [ 1.33, 1.33, 1.33 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/advanced_monitor.json b/src/main/resources/assets/computercraft/models/item/advanced_monitor.json new file mode 100644 index 0000000000..45c79c6ece --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/advanced_monitor.json @@ -0,0 +1,13 @@ +{ + "parent": "computercraft:block/advanced_monitor_item", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/advanced_pocket_computer_blinking.json b/src/main/resources/assets/computercraft/models/item/advanced_pocket_computer_blinking.json new file mode 100644 index 0000000000..88ed3c15d7 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/advanced_pocket_computer_blinking.json @@ -0,0 +1,18 @@ +{ + "parent": "builtin/generated", + "textures": { + "layer0": "computercraft:items/pocketComputerBlinkAdvanced" + }, + "display": { + "thirdperson": { + "rotation": [ -90, 0, 0 ], + "translation": [ 0, 1, -3 ], + "scale": [ 0.55, 0.55, 0.55 ] + }, + "firstperson": { + "rotation": [ 0, -135, 25 ], + "translation": [ 0, 4, 2 ], + "scale": [ 1.7, 1.7, 1.7 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/advanced_pocket_computer_blinking_modem_on.json b/src/main/resources/assets/computercraft/models/item/advanced_pocket_computer_blinking_modem_on.json new file mode 100644 index 0000000000..6805779f46 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/advanced_pocket_computer_blinking_modem_on.json @@ -0,0 +1,19 @@ +{ + "parent": "builtin/generated", + "textures": { + "layer0": "computercraft:items/pocketComputerBlinkAdvanced", + "layer1": "computercraft:items/pocketComputerModemLight" + }, + "display": { + "thirdperson": { + "rotation": [ -90, 0, 0 ], + "translation": [ 0, 1, -3 ], + "scale": [ 0.55, 0.55, 0.55 ] + }, + "firstperson": { + "rotation": [ 0, -135, 25 ], + "translation": [ 0, 4, 2 ], + "scale": [ 1.7, 1.7, 1.7 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/advanced_pocket_computer_off.json b/src/main/resources/assets/computercraft/models/item/advanced_pocket_computer_off.json new file mode 100644 index 0000000000..ceb3ff8f0c --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/advanced_pocket_computer_off.json @@ -0,0 +1,18 @@ +{ + "parent": "builtin/generated", + "textures": { + "layer0": "computercraft:items/pocketComputerAdvanced" + }, + "display": { + "thirdperson": { + "rotation": [ -90, 0, 0 ], + "translation": [ 0, 1, -3 ], + "scale": [ 0.55, 0.55, 0.55 ] + }, + "firstperson": { + "rotation": [ 0, -135, 25 ], + "translation": [ 0, 4, 2 ], + "scale": [ 1.7, 1.7, 1.7 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/advanced_pocket_computer_on.json b/src/main/resources/assets/computercraft/models/item/advanced_pocket_computer_on.json new file mode 100644 index 0000000000..7e18538e5a --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/advanced_pocket_computer_on.json @@ -0,0 +1,18 @@ +{ + "parent": "builtin/generated", + "textures": { + "layer0": "computercraft:items/pocketComputerOnAdvanced" + }, + "display": { + "thirdperson": { + "rotation": [ -90, 0, 0 ], + "translation": [ 0, 1, -3 ], + "scale": [ 0.55, 0.55, 0.55 ] + }, + "firstperson": { + "rotation": [ 0, -135, 25 ], + "translation": [ 0, 4, 2 ], + "scale": [ 1.7, 1.7, 1.7 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/advanced_pocket_computer_on_modem_on.json b/src/main/resources/assets/computercraft/models/item/advanced_pocket_computer_on_modem_on.json new file mode 100644 index 0000000000..e7c5093c19 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/advanced_pocket_computer_on_modem_on.json @@ -0,0 +1,19 @@ +{ + "parent": "builtin/generated", + "textures": { + "layer0": "computercraft:items/pocketComputerOnAdvanced", + "layer1": "computercraft:items/pocketComputerModemLight" + }, + "display": { + "thirdperson": { + "rotation": [ -90, 0, 0 ], + "translation": [ 0, 1, -3 ], + "scale": [ 0.55, 0.55, 0.55 ] + }, + "firstperson": { + "rotation": [ 0, -135, 25 ], + "translation": [ 0, 4, 2 ], + "scale": [ 1.7, 1.7, 1.7 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/book.json b/src/main/resources/assets/computercraft/models/item/book.json new file mode 100644 index 0000000000..153af56e94 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/book.json @@ -0,0 +1,18 @@ +{ + "parent": "builtin/generated", + "textures": { + "layer0": "computercraft:items/book" + }, + "display": { + "thirdperson": { + "rotation": [ -90, 0, 0 ], + "translation": [ 0, 1, -3 ], + "scale": [ 0.55, 0.55, 0.55 ] + }, + "firstperson": { + "rotation": [ 0, -135, 25 ], + "translation": [ 0, 4, 2 ], + "scale": [ 1.7, 1.7, 1.7 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/command_computer.json b/src/main/resources/assets/computercraft/models/item/command_computer.json new file mode 100644 index 0000000000..34dcbb0719 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/command_computer.json @@ -0,0 +1,13 @@ +{ + "parent": "computercraft:block/command_computer_blinking", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/disk.json b/src/main/resources/assets/computercraft/models/item/disk.json new file mode 100644 index 0000000000..122f4117d9 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/disk.json @@ -0,0 +1,19 @@ +{ + "parent": "builtin/generated", + "textures": { + "layer0": "computercraft:items/diskFrame", + "layer1": "computercraft:items/diskColour" + }, + "display": { + "thirdperson": { + "rotation": [ -90, 0, 0 ], + "translation": [ 0, 1, -3 ], + "scale": [ 0.55, 0.55, 0.55 ] + }, + "firstperson": { + "rotation": [ 0, -135, 25 ], + "translation": [ 0, 4, 2 ], + "scale": [ 1.7, 1.7, 1.7 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/diskExpanded.json b/src/main/resources/assets/computercraft/models/item/diskExpanded.json new file mode 100644 index 0000000000..122f4117d9 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/diskExpanded.json @@ -0,0 +1,19 @@ +{ + "parent": "builtin/generated", + "textures": { + "layer0": "computercraft:items/diskFrame", + "layer1": "computercraft:items/diskColour" + }, + "display": { + "thirdperson": { + "rotation": [ -90, 0, 0 ], + "translation": [ 0, 1, -3 ], + "scale": [ 0.55, 0.55, 0.55 ] + }, + "firstperson": { + "rotation": [ 0, -135, 25 ], + "translation": [ 0, 4, 2 ], + "scale": [ 1.7, 1.7, 1.7 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/monitor.json b/src/main/resources/assets/computercraft/models/item/monitor.json new file mode 100644 index 0000000000..2292e5e685 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/monitor.json @@ -0,0 +1,13 @@ +{ + "parent": "computercraft:block/monitor_item", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/pages.json b/src/main/resources/assets/computercraft/models/item/pages.json new file mode 100644 index 0000000000..4dd6fb18f6 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/pages.json @@ -0,0 +1,18 @@ +{ + "parent": "builtin/generated", + "textures": { + "layer0": "computercraft:items/pageBundle" + }, + "display": { + "thirdperson": { + "rotation": [ -90, 0, 0 ], + "translation": [ 0, 1, -3 ], + "scale": [ 0.55, 0.55, 0.55 ] + }, + "firstperson": { + "rotation": [ 0, -135, 25 ], + "translation": [ 0, 4, 2 ], + "scale": [ 1.7, 1.7, 1.7 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/pocketComputer.json b/src/main/resources/assets/computercraft/models/item/pocketComputer.json new file mode 100644 index 0000000000..b6b5ada954 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/pocketComputer.json @@ -0,0 +1,18 @@ +{ + "parent": "builtin/generated", + "textures": { + "layer0": "computercraft:items/pocketComputer" + }, + "display": { + "thirdperson": { + "rotation": [ -90, 0, 0 ], + "translation": [ 0, 1, -3 ], + "scale": [ 0.55, 0.55, 0.55 ] + }, + "firstperson": { + "rotation": [ 0, -135, 25 ], + "translation": [ 0, 4, 2 ], + "scale": [ 1.7, 1.7, 1.7 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/pocket_computer_blinking.json b/src/main/resources/assets/computercraft/models/item/pocket_computer_blinking.json new file mode 100644 index 0000000000..b4ad32af5e --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/pocket_computer_blinking.json @@ -0,0 +1,18 @@ +{ + "parent": "builtin/generated", + "textures": { + "layer0": "computercraft:items/pocketComputerBlink" + }, + "display": { + "thirdperson": { + "rotation": [ -90, 0, 0 ], + "translation": [ 0, 1, -3 ], + "scale": [ 0.55, 0.55, 0.55 ] + }, + "firstperson": { + "rotation": [ 0, -135, 25 ], + "translation": [ 0, 4, 2 ], + "scale": [ 1.7, 1.7, 1.7 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/pocket_computer_blinking_modem_on.json b/src/main/resources/assets/computercraft/models/item/pocket_computer_blinking_modem_on.json new file mode 100644 index 0000000000..4eed00f41b --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/pocket_computer_blinking_modem_on.json @@ -0,0 +1,19 @@ +{ + "parent": "builtin/generated", + "textures": { + "layer0": "computercraft:items/pocketComputerBlink", + "layer1": "computercraft:items/pocketComputerModemLight" + }, + "display": { + "thirdperson": { + "rotation": [ -90, 0, 0 ], + "translation": [ 0, 1, -3 ], + "scale": [ 0.55, 0.55, 0.55 ] + }, + "firstperson": { + "rotation": [ 0, -135, 25 ], + "translation": [ 0, 4, 2 ], + "scale": [ 1.7, 1.7, 1.7 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/pocket_computer_on.json b/src/main/resources/assets/computercraft/models/item/pocket_computer_on.json new file mode 100644 index 0000000000..6fc014eef8 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/pocket_computer_on.json @@ -0,0 +1,18 @@ +{ + "parent": "builtin/generated", + "textures": { + "layer0": "computercraft:items/pocketComputerOn" + }, + "display": { + "thirdperson": { + "rotation": [ -90, 0, 0 ], + "translation": [ 0, 1, -3 ], + "scale": [ 0.55, 0.55, 0.55 ] + }, + "firstperson": { + "rotation": [ 0, -135, 25 ], + "translation": [ 0, 4, 2 ], + "scale": [ 1.7, 1.7, 1.7 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/pocket_computer_on_modem_on.json b/src/main/resources/assets/computercraft/models/item/pocket_computer_on_modem_on.json new file mode 100644 index 0000000000..b60d8ad738 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/pocket_computer_on_modem_on.json @@ -0,0 +1,19 @@ +{ + "parent": "builtin/generated", + "textures": { + "layer0": "computercraft:items/pocketComputerOn", + "layer1": "computercraft:items/pocketComputerModemLight" + }, + "display": { + "thirdperson": { + "rotation": [ -90, 0, 0 ], + "translation": [ 0, 1, -3 ], + "scale": [ 0.55, 0.55, 0.55 ] + }, + "firstperson": { + "rotation": [ 0, -135, 25 ], + "translation": [ 0, 4, 2 ], + "scale": [ 1.7, 1.7, 1.7 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/printer.json b/src/main/resources/assets/computercraft/models/item/printer.json new file mode 100644 index 0000000000..e0a75113ac --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/printer.json @@ -0,0 +1,13 @@ +{ + "parent": "computercraft:block/printer_empty", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/printout.json b/src/main/resources/assets/computercraft/models/item/printout.json new file mode 100644 index 0000000000..d3fdfbd40f --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/printout.json @@ -0,0 +1,18 @@ +{ + "parent": "builtin/generated", + "textures": { + "layer0": "computercraft:items/page" + }, + "display": { + "thirdperson": { + "rotation": [ -90, 0, 0 ], + "translation": [ 0, 1, -3 ], + "scale": [ 0.55, 0.55, 0.55 ] + }, + "firstperson": { + "rotation": [ 0, -135, 25 ], + "translation": [ 0, 4, 2 ], + "scale": [ 1.7, 1.7, 1.7 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/treasureDisk.json b/src/main/resources/assets/computercraft/models/item/treasureDisk.json new file mode 100644 index 0000000000..122f4117d9 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/treasureDisk.json @@ -0,0 +1,19 @@ +{ + "parent": "builtin/generated", + "textures": { + "layer0": "computercraft:items/diskFrame", + "layer1": "computercraft:items/diskColour" + }, + "display": { + "thirdperson": { + "rotation": [ -90, 0, 0 ], + "translation": [ 0, 1, -3 ], + "scale": [ 0.55, 0.55, 0.55 ] + }, + "firstperson": { + "rotation": [ 0, -135, 25 ], + "translation": [ 0, 4, 2 ], + "scale": [ 1.7, 1.7, 1.7 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/turtle_black.json b/src/main/resources/assets/computercraft/models/item/turtle_black.json new file mode 100644 index 0000000000..20415dfe80 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/turtle_black.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/turtle_black", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale": [ 1.14, 1.14, 1.14 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/turtle_blue.json b/src/main/resources/assets/computercraft/models/item/turtle_blue.json new file mode 100644 index 0000000000..9feae2e617 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/turtle_blue.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/turtle_blue", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale": [ 1.14, 1.14, 1.14 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/turtle_brown.json b/src/main/resources/assets/computercraft/models/item/turtle_brown.json new file mode 100644 index 0000000000..979e6845f7 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/turtle_brown.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/turtle_brown", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale": [ 1.14, 1.14, 1.14 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/turtle_cyan.json b/src/main/resources/assets/computercraft/models/item/turtle_cyan.json new file mode 100644 index 0000000000..4df971e883 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/turtle_cyan.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/turtle_cyan", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale": [ 1.14, 1.14, 1.14 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/turtle_elf_overlay.json b/src/main/resources/assets/computercraft/models/item/turtle_elf_overlay.json new file mode 100644 index 0000000000..1d3f3c775b --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/turtle_elf_overlay.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/turtle_elf_overlay", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale": [ 1.14, 1.14, 1.14 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/turtle_green.json b/src/main/resources/assets/computercraft/models/item/turtle_green.json new file mode 100644 index 0000000000..ce01272e0e --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/turtle_green.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/turtle_green", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale": [ 1.14, 1.14, 1.14 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/turtle_grey.json b/src/main/resources/assets/computercraft/models/item/turtle_grey.json new file mode 100644 index 0000000000..1ca4389812 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/turtle_grey.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/turtle_grey", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale": [ 1.14, 1.14, 1.14 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/turtle_lightBlue.json b/src/main/resources/assets/computercraft/models/item/turtle_lightBlue.json new file mode 100644 index 0000000000..3526386b0b --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/turtle_lightBlue.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/turtle_lightBlue", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale": [ 1.14, 1.14, 1.14 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/turtle_lightGrey.json b/src/main/resources/assets/computercraft/models/item/turtle_lightGrey.json new file mode 100644 index 0000000000..7f7de52d34 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/turtle_lightGrey.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/turtle_lightGrey", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale": [ 1.14, 1.14, 1.14 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/turtle_lime.json b/src/main/resources/assets/computercraft/models/item/turtle_lime.json new file mode 100644 index 0000000000..77205b1410 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/turtle_lime.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/turtle_lime", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale": [ 1.14, 1.14, 1.14 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/turtle_magenta.json b/src/main/resources/assets/computercraft/models/item/turtle_magenta.json new file mode 100644 index 0000000000..2ea6cda974 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/turtle_magenta.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/turtle_magenta", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale": [ 1.14, 1.14, 1.14 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/turtle_orange.json b/src/main/resources/assets/computercraft/models/item/turtle_orange.json new file mode 100644 index 0000000000..b5e8b60dc3 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/turtle_orange.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/turtle_orange", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale": [ 1.14, 1.14, 1.14 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/turtle_pink.json b/src/main/resources/assets/computercraft/models/item/turtle_pink.json new file mode 100644 index 0000000000..c1530495d8 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/turtle_pink.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/turtle_pink", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale": [ 1.14, 1.14, 1.14 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/turtle_purple.json b/src/main/resources/assets/computercraft/models/item/turtle_purple.json new file mode 100644 index 0000000000..fbf89e80a5 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/turtle_purple.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/turtle_purple", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale": [ 1.14, 1.14, 1.14 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/turtle_red.json b/src/main/resources/assets/computercraft/models/item/turtle_red.json new file mode 100644 index 0000000000..a68cfafb3b --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/turtle_red.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/turtle_red", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale": [ 1.14, 1.14, 1.14 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/turtle_white.json b/src/main/resources/assets/computercraft/models/item/turtle_white.json new file mode 100644 index 0000000000..ccef31777f --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/turtle_white.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/turtle_white", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale": [ 1.14, 1.14, 1.14 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/turtle_yellow.json b/src/main/resources/assets/computercraft/models/item/turtle_yellow.json new file mode 100644 index 0000000000..a83e2c0b5a --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/turtle_yellow.json @@ -0,0 +1,14 @@ +{ + "parent": "computercraft:block/turtle_yellow", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "gui": { + "rotation": [ 0, 270, 0 ], + "scale": [ 1.14, 1.14, 1.14 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/wired_modem.json b/src/main/resources/assets/computercraft/models/item/wired_modem.json new file mode 100644 index 0000000000..ff0007218e --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/wired_modem.json @@ -0,0 +1,20 @@ +{ + "parent": "computercraft:block/wired_modem_off", + "display": { + "thirdperson": { + "rotation": [ -10, 180, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "firstperson": { + "rotation": [ 0, 0, 0 ], + "translation": [ 3.2, 0, 0 ], + "scale" : [ 1.33, 1.33, 1.33 ] + }, + "gui": { + "rotation": [ 0, 90, 0 ], + "translation": [ 3.2, 0, 0 ], + "scale" : [ 1.33, 1.33, 1.33 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/models/item/wireless_modem.json b/src/main/resources/assets/computercraft/models/item/wireless_modem.json new file mode 100644 index 0000000000..a315183614 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/item/wireless_modem.json @@ -0,0 +1,20 @@ +{ + "parent": "computercraft:block/wireless_modem_off", + "display": { + "thirdperson": { + "rotation": [ -10, 180, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "firstperson": { + "rotation": [ 0, 0, 0 ], + "translation": [ 3.2, 0, 0 ], + "scale" : [ 1.33, 1.33, 1.33 ] + }, + "gui": { + "rotation": [ 0, 90, 0 ], + "translation": [ 3.2, 0, 0 ], + "scale" : [ 1.33, 1.33, 1.33 ] + } + } +} diff --git a/src/main/resources/assets/computercraft/textures/blocks/advModemFace.png b/src/main/resources/assets/computercraft/textures/blocks/advModemFace.png new file mode 100644 index 0000000000000000000000000000000000000000..fc458b2ef07886838e59fbc177c5cc166970b233 GIT binary patch literal 620 zcmV-y0+aoTP)UIJyMj{P;!Nvqu+{!E82bHkwMa4uI#w z;eXx0vdukgShuX08D+EC;C-_UKt38^h1KU*2;+gOFAsa9adUHnmr{`Q7!qwbJDxK? zyhJ`hK4Ecq!RpH{jGhp5Pi(YN4`svZWS7OkSMbW|*&D)JB2Q1=Aq(cq?@ipU1*z|Q z%6h#ehLFzWz;sexgrwHueoWI|xLI@JHc9q1gSA)Nx8G%ySyEQMLu zY#firAS2|IafdRoNF)KmJduf%NK1-2AhL?-bc+4&cm4|_7E8`cI?KNR0000AvnH8I#i2|kZ&Rz8Q?LaR|h9>TY9M?y>t(tqx8 zF@Gr`GMkyXGxyv(=bX_AnE#BMe*OjQJcwTd&-(oUVEXeNRz*}80whGX8yVOpBCuFKIo|^{vKF&fOpeaUvKFjyb*F+Pf&f50 zvO6<*djY^=w%g9MQNdZ+xdZT^Ne94oe|cjMWm`v8zpvQ$I*3)zB;Xj{S!DU~B}N;k ztp*$W^jZgi?Ttx%%h_zq`1k_H7LF|@$LB0R?ZfaMK#2{2hASA{vYhWTIr>Jht*8g*N?n)>a3AhShn6MoV&*x(QgUu2Kr+932YPyX za%KWhRb(c%sVV^8-rl%guVf~f$@}{|+qQAJTo_}}0e=4YhLwnf1)v~i0xGagL}1TC zWC4Tc@4x6TFE98@f(NFMOo`(J4ikoApfKd1G$005Men^M?r;Q^238=6swC8K0WFaS zGzba^?)N+Wd_F@!c_3+a;ldJ49q_DdK8}Y_7yG``Z?_vs5EATza6yZCBWC2}0GdS> zc+A=lL0vEQ(0LcV^3uz|pnTaHVz$N4cHG}jpArly6vVzFMm0Yja zsZs7z9ROc}-$(}g5swq1i@><%u1KP9+eYk%GIiV*$ORqLeCUyY-3MqxiPzWHsc`}- zaEI7%tng0)VPwNnQ)zW*{?w>t$DS-o0|-iBi$Ih`kP}`cD8c^J=r}qk17iY2L^Y%~ zyODuB#%Uk#zOE~Y2sga{Ap&SI0g8`3C~*v9R7Pr3o`rq&T7r>ZHH)JnE>C}^4!kvEjDckAMiRvY2Noo`Y62vhBn0h1Tc9q+ z+uIusVH?dN(^w4+wExyGL=cOnjU>kHcB2+caHDB700F5ry~PZGBAB4YQ+Nbp-*>RU z3EKe&c-ARoLB8gS#&nw`VHnelszOTQ)LU@@-#HasR2CcZw3fW$`c2?vW6r=zq!4d)RT(+{WkB&*{f%;DS%Fran7^}(0sqlei zY-5B&&{yO{6bKSCxM06*%;SXH5Vb7JbGnVT2PmL|=taxifF^FY8x`O%(5UOYgOre$ zwZ?96V>ZyhBpONV`wkN21)l;P2ZdIko)gc5;=r5eJo6GOeB*MttUVx5CMZxJB(+#+ mMJg=ZCUY&+$prmxoc{pg#6O^A4k!cw0000svO(K|E^dtQpTGW7l6-IQ!d$v*_Fl6W@po>jm#u zPrjPv>av^lU2)jP*k`;diqS9c|H8_%jxGvD=I_g;zSR1^+Qs*g`MrF-zs|R?%fxhHM$ay>ud%?8WbkzLb6Mw< G&;$Vgb)}mC literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/advMonitor16.png b/src/main/resources/assets/computercraft/textures/blocks/advMonitor16.png new file mode 100644 index 0000000000000000000000000000000000000000..48b308c0c253386450d61a85cdd5f8b667de5662 GIT binary patch literal 418 zcmV;T0bTxyP)cV0WV2J zK~y-)os%(6BS8>FU)A(rBnK7&8Ujm1NF2eL4?s>z%0Up9-~fA%J;VlF0g};3wr9Gl zilD7s32oB+tb%&_Rr+6cyIq(W0Pc>N5fQjM0LSBzVHhwo%#73N#Ih`GHXBMQB!FLU z4}=&hP9!5F5D7q`a?Uyr=0M@`={IQ{N4PB9-M9O;~6uDk9jO_ROn5OA(o&W3BjIQgxb)mlR3*uUu-|bGk4FCWD M07*qoM6N<$f*H1}3;+NC literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/advMonitor17.png b/src/main/resources/assets/computercraft/textures/blocks/advMonitor17.png new file mode 100644 index 0000000000000000000000000000000000000000..bfa10c504f0467f2f8c4bb37edde30267b97d939 GIT binary patch literal 342 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP~3loXLX*le-dDD@$3HHttuR1wC-E*wy^Pi_P^A8)es4(1-^>kr* z$9Ldm$)f@b1x`<&%SUX^zxiH0Ep;Kop1pR0YLhGjT_O_19Gb2cKdYI@%>AOR$VTpA z)x(D$Z)PY=4N^F}Wzw#7%!^|KvRxeWuj3nsr%;+S3&TzGKaTgm-??`;-`io= zEsY5AO|cJZwsR{nZC;<|c+xWY-^t^@y=SavHR5*Kzc^ODbE}^vV_#*$#EpeAi?3C! j{9Ny$^t{IM|0m`MzN`}4kK9*)-evG~^>bP0l+XkKbd`rD literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/advMonitor18.png b/src/main/resources/assets/computercraft/textures/blocks/advMonitor18.png new file mode 100644 index 0000000000000000000000000000000000000000..0d496d70fe30031d460e36f50ae402e5aa8ec02a GIT binary patch literal 263 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP~3lo>6sNC%iKU`#QBG;N9Y-QcSuhDlQUG3({l&js9^K>~IRyhf6TdBn`Ej3ZbT}838H1_7U z-b9HT-{p!sm})O%dcK=(0ty85}Sb4q9e E08B?6s)f=vE1=LjPZ!4!i_=Rd8~Pn~5OBS}=Ixf1 z6JG9cI#sfhRae*j0o$E!=Oqp?4NXd2EpPA6{V6i7qh-al%Qcx@%h&%;e^X(z>RQ)K zLBSo?@BGfqyqkC2#JA`1kKOa1&zxiY`|rFc?Qey36QA-i1TDD7I3dhbdWY|tM~oqI z^Y3NM`~G<|Uwd3?RasD|UVhhF^z`kcYj)z4*}Q$iB}uOyR( literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/advMonitor2.png b/src/main/resources/assets/computercraft/textures/blocks/advMonitor2.png new file mode 100644 index 0000000000000000000000000000000000000000..ec6e9db78b3ac699aeb6050ac4bfaec98cd4b61d GIT binary patch literal 508 zcmVY28u>8-S0G4=$Gr-A#9MyWP0o@4UUevDQNGzkbG9L_zffA*7H5^YZI*B|KMiQ zXawq&QwEL@#<~MW$+qJglnxFYC`}=WvKSIpL!ca_K@z3~D99iMSXfXgk_TM?MRD4&4h~XHnLtBU$ZC>C-afp5o1*!| zN!kLig`GuqMuBDlg#|IBZq#XHM%W=ft&K*3l5;Ww?NdRM+DxC!_~i`1NI~9ro+h71 zhe3j}Ne{%rHBkhFL{Iz-13lIL3RJduBHJniK?&tM$===xhOr<29oSVIKMQ+NW3M^G zkV1&k*fV`5Qh+-eB4?$8sJd^y@$$7?UQ930Fm$0js1j-Lx>2*}5h{iju&6_(HVRCQ yttNuxv1d(@0cIgUDi{;_aV8a@5rzKuJO2UyVM-NOqTVI|0000(?@ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/advMonitor20.png b/src/main/resources/assets/computercraft/textures/blocks/advMonitor20.png new file mode 100644 index 0000000000000000000000000000000000000000..3f24c6e380b90c432786e1a218c4335e418691dc GIT binary patch literal 365 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP~3loMJ{2XV zhSy(DS@i9&es}I|+2gwX#TGIvwoYQ)x8G00lCzyjAc5CGVv>RJk}wYb1)skCbDsBH z($-pk{rpbepTGYGxFlGn3vov$r|Fz-di%ZFz$$6Y>#kTm@jcB7yu6!lznyR?&A}_{ zaA|qaExv$Q$>SS$sz2=$i%PVX>%Vc!@Nk9F^E*5$x$Hd0Y|i(Kd9^o%o_Uj)@al$B zR=EP_^7LNjr6M^JY%g{+uh=R%=Y0B_y${To%e^%JFuNVCS!*WJ2ns(2Pgg&ebxsLQ E05}zit^fc4 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/advMonitor21.png b/src/main/resources/assets/computercraft/textures/blocks/advMonitor21.png new file mode 100644 index 0000000000000000000000000000000000000000..ee37cc2a3eb97d3fbfbd24e744527d141feb9a00 GIT binary patch literal 306 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP~3lo=>h||TVhk-)-JzX3_EKbjzv~l8L10EJ}g-lj0 zht5?2OE&Fenf^j@d0tb{C#hKn*nhDdIK5FqW?Jq2zn`nD4%XbW-O+aA4;;?zzt;!xiWGWb@jdpL~wvL7(4c7CH8c_dBd_RlBPk z-JcLYE!C0nQut$4r4Ei=>$H!UI;c!6epX*P=YiIhsQiZIW*7D^TxGuC^$E_R>Id%> ynDa{(PH9>;rOh^D?ZV@Q3#RO7Oq&w)gV{UBchiA9sWzZj7(8A5T-G@yGywojZFV96 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/advMonitor22.png b/src/main/resources/assets/computercraft/textures/blocks/advMonitor22.png new file mode 100644 index 0000000000000000000000000000000000000000..d5d175a0ee83448e2e2c348a6307f413b2ae9f31 GIT binary patch literal 357 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP~3lo=>sxbf4pFp8co-U3d7N?g^HuPh5i*q-R$%es%P$?N*I&LZ z`CF&|eE!qJ1_%D$xg+t?$>o7%`iJb_Dd&AIx2zA--cVL@cF~lk{>L7B4|0{>b-MK3 zHpseZYLm*IYhAzZ^8P!Yvprhofb(0;GmSGJ?!Mdiwd%6YhRO<+=X(SS4s*>qYQS@! z=}B4RdCu~9mZnSZ5__NWsU(`2epeTdy*@G6D`L*iiu#GI499&|{JYcE+VOej60a$e zo=2W~X|h_&^-CQu>{NS{e=EvU^Y5?Lqxo literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/advMonitor23.png b/src/main/resources/assets/computercraft/textures/blocks/advMonitor23.png new file mode 100644 index 0000000000000000000000000000000000000000..7d55f994148c5eb95c0a40fd354d4eb2d21221e4 GIT binary patch literal 282 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP~3lo=>MFD500#InVr;B5V#p$J!ZMm2nd0O|YG;8N9 zox6ekX5RX=r$22P%rB%#3j8^FB#BFKO>M6m8<3C_GxUI;&5m}YNXQhnD(dj^WXK&{2O&$>OQ+v XwPobP0l+XkKlLBa9 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/advMonitor24.png b/src/main/resources/assets/computercraft/textures/blocks/advMonitor24.png new file mode 100644 index 0000000000000000000000000000000000000000..f7569e2276dd5bab877b9017405274829dd39ae2 GIT binary patch literal 194 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP~3lo<$-?A0DKY&91o-U3d7N_5yT_||OL4f&SWNyOr zyX{#iWfiKA*B3FcT`xFspit(1!1u4*MpF;z9+<++!MlT(BTA*2NnuieXx7@Pd(9cP i#p@e8m;X2QWUzUMLRFoDIZ$Yor;B5V#p$J!H}W2G5McTK?!UK# z+G2L|2h(0OF?nV-G#uEJQgN={`vC)|;NM)v#aGYCUYL3N>zP8Cl^n~YAG~BOf6u-m z?Ml>d#ycFw+zeiwxe93toeizLhYeVCa`*&avdi?TKbey(_NwJDT$4hZ}=t& zEfslk{I8RSgTNz}1pMp};wYqd=i@PZ!4!i_=Rl9Tap@nSvBR_Z_jW4?9zL^0DmuG~+5FiYFYeCW+JZi}9j6Kk-r`%rZ!@{$0jpxF_OXPQ Sx7&esGkCiCxvXX7l{d zrQ4qhWhO>j7s#+XvK#O)uVC)rI1^;eFrjNZ^XW|vOY@uL4l+*p_p9MUpQuV>=^VqQ jSH83V-uHNqDYJjHs=uDmk0X3Q=QDV^`njxgN@xNA9_MLv literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/advMonitor3.png b/src/main/resources/assets/computercraft/textures/blocks/advMonitor3.png new file mode 100644 index 0000000000000000000000000000000000000000..286b5bada3e1e176016f1dced04edd1b11784c6c GIT binary patch literal 518 zcmV+h0{Q)kP)ML=y*GO+q=A$5-9ppyf)ufPK-@i6LZ36r-iG5|#2iNl{1oL581vPkyEaeKvK!VHVLN{Mt1;rJ&6Pl9Gw=T47v%M$@Ld(XcPlX3m z!|_a{pumx+46RKTv{>gSIlDO5~)f za0tgom~7K&p!|aXDWG*!2jt>Rf&&G(ifG^hXR&P?`rq&T7Ye^HyoSOU9RL6T07*qo IM6N<$f`Am(t^fc4 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/advMonitor30.png b/src/main/resources/assets/computercraft/textures/blocks/advMonitor30.png new file mode 100644 index 0000000000000000000000000000000000000000..6b7be748df859366c161b5740e17ee6412470808 GIT binary patch literal 210 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP~3llekrrjmkIY6O!PZ!4!i_>q~6=(sx=j2sZ9k?(ASlhzbk^SY zd@IRz?(-YQm@Kvzm&1$|76o}_vP-nhEM<6e%z#JM-s9LN9a~)%&872%*W|NLnpphq hwqtmch~v4L^&Qh<-yQqBs}tyW22WQ%mvv4FO#rJ1YK;H@ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/advMonitor32.png b/src/main/resources/assets/computercraft/textures/blocks/advMonitor32.png new file mode 100644 index 0000000000000000000000000000000000000000..b8a86a0525e72573b26b9e61d64526f72db97d3e GIT binary patch literal 580 zcmV-K0=xZ*P)95D<<->0;;0T+ggU>hIAoe$tXZ4Q-EaAEId6uF~*<+eEa&2m4piS#4?hB zfSG5D?UDryK7aX6Kb=nSFc1S%I81sMm}mkZJVo}3Wr#sl(R=R@3y6tM5+Ni}Wdzs) z22x@d(FJsFw;TQO@eu@71ESGf6Wyj&Kp1%<*+y!3OwZPJrJv7d(t)B8%VmrmlvL&KS2akp!Q7W3KWtlG|w>wm7>)^ zHogCtgGAg-*f@fVh(=+MiEVhQ7Fvi1@F<*v)9JJ&*z;^P7l~wS6T~zt4zMoNx}cGG ztVG0A7Ax}Z_N>_?vMC!mp%#3-;bp-TD$hBX!*QebmKkIr*l?3_;oDDG2eEZ30uF}* zy|sqw7lBdD1(J+Y>?_gA)RHt8wT^9DCxPDH-h4iv|E%->A~R{N{q+_x9s3R0vOC_! S{7|g`0000Boq1Oal8>~eq}u?Oh&8W^ZkTjX@1@82%UjYtaO48@^d zUte8S0CYE1g>AYUfb;px)6)}GMOE?f@xkSC;qmd2IVS_)$M`uSGZj7^l;Ta-c}!a$d|c{`TAf1TBC-EjS1a zk{I{*_t>IaL`Om*v9mZD(C*KqpFaEd|e0v`G(%$1`8c>`E2a8+8Y4bTV`d^ zwXkYOk&Nct0)qy)v4ZjP^1_#|&vXd+C(RLgQI|}k1`&jaz~=&|3ipav~BrDJ^u{1c7ZJ!NxkEFg;DgVHIeuyI@+2swrgCHgcgh z9uI3rHc}RhC63>;Z&{FqfC%s`+Kn?XXJW*@Xf}+@MEz^2uf2`ZxWsKGWFxPrGZ2m1 rtL?Y9H=jycy00000NkvXXu0mjfr?BeR literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/advMonitor34.png b/src/main/resources/assets/computercraft/textures/blocks/advMonitor34.png new file mode 100644 index 0000000000000000000000000000000000000000..ab57fd2fea30c029c7b16d77044323ea961d06cc GIT binary patch literal 542 zcmV+(0^$9MP)&H5NFeYqSmb*>N~<=XomIVtqkTO?{&NEGLfdV70I zRRPf5R250+ZU8Qq3+MBhs-miRe}CtCy>dF8*!La%`uQVPlUYPT3Se0M$7$GBjS6_g zJ;~UZ`mzz4I8<&8!9xHzO;Yf9B^7uu&PE5~V^kcP!fwV`C>9ccop=KpPjH|JupnnJm{H8gfczu{ZkZ+5IifKR5ZOj#0B+rMX22AS((O6^6)OihA z>0#1?=?B=Zv`o7{4MU2mm4RC(4wG5ZnHhZ? z;%s>ObBPiVO=JSt_d5bN>8JJ&aN~#`Ml|ZRP%h}vYq>B=;bU@gME>>lH2_t`7~{Wo g-tHuk+-u4^P)DRnMr0c#^7{1ak*SLpU*Gz>-EYQgS)#s=A7u)k8jp!01$>bMxld7UiiF#lghbfE{NJeD@*a9X} zVi(Z`bZ)mBy-^@zPpn3B0Rc9x0>a2XWErX9x#aEpPN%@$2?^Z>Rzizc%@sgU0ti%s zO)PHE6Vr46wg9&U6ySQX&zd+uf>yws*rqocNfHjgYgN4g*P^}&`Pq{Kiu3tQhoHf_ z5d$aS%G;8J=F1`MqGln9{^8SS=G`P)?$=BcNOqw_(adzeZaqIg zJ2L^ODl!w>R22ZPudkfXXEKw_4`=->?#qFaQc-EuaG1L4gl{^K|Oa=GBo37(ijG9~s493~9KL}AEDX+lh@ir#xi++YutCRQMcswC8K0WFay zGzba^Znqo#;o$)S$`eUTg$qkGb-?Sg`FNf}T^z?je|dQ!2||Kn5-w=5e#Dww96;;H zfOnt$bUI;+>BeXWb|Gy)DsW+o43JC!xRBP;o|#A@2wXyLP-{rGZ^t*%I-KRrDW$Bs-Lw*fiOrsf@w1RUO=4JCT-OThwE z;0|%eaf1IA2qPOttw^gwGndO{TNnrSVo{nvPy$;7qAY@3@FGD8yPZoxYz1XtE`W%r zhSZiC8OUv?0l9i$n?!^gKK>E`v{(SeM-NJDGe%{k#u$U%S_6x8&_6X?g|apmqbMv> zHl?B~08`UT!S#A27^^e|(pTWR%e11Dq1gmMbZ}0TFvj2?_arjF()V&Mz&aphd(05S!7g^6-rnB) z2-AJNX;6NeTd29nRYNMg;j^^=rFrJ^EaR}RJ z6`96rC;%fR5Zj%07PgQEb56#`#|MRu%|^>;91#pGY*Ddu3B28$V8`ut0}GsRO_<ORUx-Ld$ZVm{P2@2E`>fB5nw87m(f*V}DNqm2QC%8bp+t3Y|$LeQo jCVGeJ5@He!*LCq5{xlDj0(3tD00000NkvXXu0mjfZ@b(O literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/advMonitor38.png b/src/main/resources/assets/computercraft/textures/blocks/advMonitor38.png new file mode 100644 index 0000000000000000000000000000000000000000..7700b3dc8f70d7b2b08d4d3066014773a33aeb8f GIT binary patch literal 566 zcmV-60?GY}P)EPBUoIDT z7>I!>9438Sn`ry*p1;}~mLUdJMen^ste`2cNFszJs*E^V7)Xg-L>JJx-EQ>9$43xU z4Twf_P3bnR0>a4NTQE|?BLUd9jefmeNe7BXtiPu67JCZ?6+los6O~{QQycXA`+ICr zC1Nl1Fj^YCfo2UH6KE@73~bXglZZPsUO_IK{CN ztxT;+b5Yxzf9(o%KA(NPUUyLcZyP{n(pvlHEMgM-4ILvP?Y0BdlK=n!07*qoM6N<$ Eg2v|PrvLx| literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/advMonitor39.png b/src/main/resources/assets/computercraft/textures/blocks/advMonitor39.png new file mode 100644 index 0000000000000000000000000000000000000000..7197dda33e9fcf232592a5269249fc2b7770bd1b GIT binary patch literal 535 zcmV+y0_gpTP)5OuK zOe)N*%Tq-m0#v+<->^YLC}+kP1L_?FNidTtAqhKZGlTn(;1+`1QZHy9tZNn8n*-;z`Fngr4fzN zOfB>z6h#uCAt5@U3O+*BX%#THyJ4(FHB6M?1Z5(Jj5D_RBo)C}=J95D<<->0;;0T+ggU>hIAoe$tXZ4Q-EaAEId6uF~*<+eEa&2m4piS#4?hB zfSG5D?UDryK7aX6Kb=nSFc1S%I81sMm}mkZJVo}3Wr#sl(R=R@3y6tM5+Ni}Wdzs) z22x@d(FJsFw;TQO@eu@71ESGf6Wyj&Kp1%<*+y!3OwZPJrJv7d(t)B8%VmrmlvL&KS2akp!Q7W3KWtlG|w>wm7>)^ zHogCtgGAg-*f@fVh(=+MiEVhQ7Fvi1@F<*v)9JJ&*z;^P7l~wS6T~zt4zMoNx}cGG ztVG0A7Ax}Z_N>_?vMC!mp%#3-;bp-TD$hBX!*QebmKkIr*l?3_;oDDG2eEZ30uF}* zy|sqw7lBdD1(J+Y>?_gA)RHt8wT^9DCxPDH-h4iv|E%->A~R{N{q+_x9s3R0vOC_! S{7|g`0000igP)@z#;$)1|P8s1|&if+7}ZUQb&c@=h+C9K~O4G0*j&;a+hDsOa*CzzzWK5 z6AjunG;V-5vVty#Kym?In9?nAC>D~DM3pfj5uOljs0vR(dOfof-{Qq9Pz(walwuT! z0DA)oNQ3Ml`@%7$9VjM%YC#qFwn*+N7IwR{^n@s^_DAVU4K}>mf*Qs7Ta|^6$w`ocuGedxpPw7rIpMEZYca<7SL(yP$B)}c;%*$9l_?<*zJd7mz+xH((-ar-j zJ8JKk^8k#LbB#u|3Oq&gKncBnqnlT>x?5uF0x?w$6HqADDE3Y(Q3V+$bMW~1NSC(d zCvHwQW+E+b6t!U02FH$%ec5^(RMlc&4wM`1HFKCK!3oL)@8tPP_MKqlEFUC4sVaP< z9#Dkflsj=uu0P-ylz?ffVB0o&^YbZxSr?X#GsP*2=HPwOVtlOq`&6L&`};gSJ)NM; jzhcfwYweG_szvMySw5@Fn;17u+d$w zG2JFf7{)ZCs*sYsIH9NW)P)(b zyO_;*ettf|IGq)25dbfsG1vV!7o`u>@3e0WtusAw-o~C--ozmsg1#XqqCk+C!3Dd{ z1bL&)c8)(tLRlzl!*qPWv4M&PDsVr5-WpUuT&}1Kdf`aaASI4KHgb8M__Vu-K} z66L_2P@p*}M0dlVh1aB*_z<0IgA~x+jLh5|5GWHAs3%EnT?Jsm0-nhF4NT|&#CUsq uBRJs1SGsP80$9L6(gs0WSVG88*u`HFNg88nKz$AX0000tQ%bqtO=J5))bOR9+;34LRbrI;0|8Qq|pe}C(y`)Fd6g(9Ti)K^R;@0As-g=HciTxhOLfJCT5c_9rD48lGpSqurQAy5v|APLg~ z6l9PBEG(!L$%8I{q6lDQ9UP>ZGJ%Gykkur;9bXN6fSaOu;v@k(HGo-UPZVetP*@N{ z>P8(QGr|t>kv19yO3s-Gw9f`jYBN2V@du^tiIg3+!#pBiM~6XzvPlob!ZlF@ghVg= z3?5;-nCwGOa*jNK<0ML_3FqHy8 zX*^D&5ke4TkQyjKEkMIIJtfLU3Sg38eSi{4qZATAK@REy1en|HMwf%6J+qLYWS9U! zYCu7N{Voww=YGG_nS-=Xz&p|;BdG5o1Q;Y@7Jw+S)NHVQHbK2ngkZ#S0t%SWp4u?M zKut&{N$6EzjDdE~R;fLGnFHXkrUTN%(_AhWdS;#ls0Hjlr}Ak0(6iX}^6x@?hIO&6 z0uP>$rMbS(K!V;oJ)E8e)lbsSXdz#BU1-~uWUnMBalKyYYWk<}4sN8fL2AXhCUT(p z*{rJQFjk0~*T3LNcIF#9`xJi?UD=o`2Ofi*J`3Rl}sV-l;JoIegXHk1+(s@ RnREaE002ovPDHLkV1iKJ+qD1y literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/advMonitor45.png b/src/main/resources/assets/computercraft/textures/blocks/advMonitor45.png new file mode 100644 index 0000000000000000000000000000000000000000..3b36d38aa404b8986879944c708641bdbdd76932 GIT binary patch literal 563 zcmV-30?hr1P)p8!-%pzXxz7&A4#s#s~2ga!gk_pRJi#(h_(nxJp5_lm}JnoQMKJVg@JdS`?i70kqM4HD%Ap91YWg;t>+6VIJu$D8Op`Vy;rBQsYH2$Ts5)H_KnR$7$`3%AK! zfjXElzQ4Z-HaOxdoq>e}CNPi$Z3MW4*ogvi@E7L>C@6(C2EPCR002ovPDHLkV1j4D B>`DLt literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/advMonitor46.png b/src/main/resources/assets/computercraft/textures/blocks/advMonitor46.png new file mode 100644 index 0000000000000000000000000000000000000000..6c27a8526cbd2c4886be6bd1039d4481ae7da688 GIT binary patch literal 524 zcmV+n0`vWeP)w3MWy8*CG zcasF$0DOFWaJgLQZn~S>?Z*9n=l%ViwHEsG`&XPr6jVPELJCPx-hc(QHo^M)A8sa% zMxfp}ZQuxDtUF+o?0vjK>EOVD(iDh(1j<1gBw<>Bf(%lCg$0!&dC&z=6lV48|dCW?TN=!u_Upr_hj7nLoZ$leu#poH>+WT$t6VeH4>FLoE_oQ1upv186K zq!6Mswx`cR3UEh52|=c!UwcNM1Er zlvnNdAMbQ1s{KL3pu%~;(J4eARI3S|I3}`DGtj6iy2Gf9x&T2Nl!Zc+8xddw`cg;n z@$o@d8A%&(AVH`gHvzRp$-u6&h13~i(8-D0H{gzxcpCLRgvHwy82}>iLgUq}XA{JY zz?fQ+&D=sJv?n$SQ$QrxYg;`6ilTrvyisaT2WmfNO$Vf;vN)g5bf=#Qh$Yy6BK&Cl zz_YaLQJ)Fd3D(D671ZP@vXt8#6A60nbo25|D6Y7j(2{)pb)mgB+nbUg#N~3KtLaPP z4%Kix94RPpBq~FzXS0Z)!(29Pg(O^w18mdai?ugBH6R&d5H%;+PE4KF0VQY*+V+4d zk&~*zAsnA(I*x-*1La=?NCB;*8jzba2@VwCDx!f4oVA=7`)rLijTc~SsCwRH)Y^(u eh(Qz_$H6~58y6>y0mDf| zK~y-)Ws@;-6hRC{-&gn8u5#pn+QbKOwkandEPBUoIDT z7>I!>9438Sn`ry*p1;}~mLUdJMen^ste`2cNFszJs*E^V7)Xg-L>JJx-EQ>9$43xU z4Twf_P3bnR0>a4NTQE|?BLUd9jefmeNe7BXtiPu67JCZ?6+los6O~{QQycXA`+ICr zC1Nl1Fj^YCfo2UH6KE@73~bXglZZPsUO_IK{CN ztxT;+b5Yxzf9(o%KA(NPUUyLcZyP{n(pvlHEMgM-4ILvP?Y0BdlK=n!07*qoM6N<$ Eg0vXuod5s; literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/advMonitor6.png b/src/main/resources/assets/computercraft/textures/blocks/advMonitor6.png new file mode 100644 index 0000000000000000000000000000000000000000..cc82a98b7be919643e0c875054283f05ba266055 GIT binary patch literal 545 zcmV++0^a?JP)&Mz&aphd(05S!7g^6-rnB) z2-AJNX;6NeTd29nRYNMg;j^^=rFrJ^EaR}RJ z6`96rC;%fR5Zj%07PgQEb56#`#|MRu%|^>;91#pGY*Ddu3B28$V8`ut0}GsRO_<ORUx-Ld$ZVm{P2@2E`>fB5nw87m(f*V}DNqm2QC%8bp+t3Y|$LeQo jCVGeJ5@He!*LCq5{xlDj0(3tD00000NkvXXu0mjf1L)lH literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/advMonitor7.png b/src/main/resources/assets/computercraft/textures/blocks/advMonitor7.png new file mode 100644 index 0000000000000000000000000000000000000000..b19014caae910b9439f6ca3f9b34c192451b4c61 GIT binary patch literal 569 zcmV-90>=G`P)?$=BcNOqw_(adzeZaqIg zJ2L^ODl!w>R22ZPudkfXXEKw_4`=->?#qFaQc-EuaG1L4gl{^K|Oa=GBo37(ijG9~s493~9KL}AEDX+lh@ir#xi++YutCRQMcswC8K0WFay zGzba^Znqo#;o$)S$`eUTg$qkGb-?Sg`FNf}T^z?je|dQ!2||Kn5-w=5e#Dww96;;H zfOnt$bUI;+>BeXWb|Gy)DsW+o43JC!xRBP;o|#A@2wXyLP-{rGZ^t*%I-KRrDW$Bs-Lw*fiOrsf@w1RUO=4JCT-OThwE z;0|%eaf1IA2qPOttw^gwGndO{TNnrSVo{nvPy$;7qAY@3@FGD8yPZoxYz1XtE`W%r zhSZiC8OUv?0l9i$n?!^gKK>E`v{(SeM-NJDGe%{k#u$U%S_6x8&_6X?g|apmqbMv> zHl?B~08`UT!S#A27^^e|(pTWR%e11Dq1gmMbZ}0TFvj2?_arjF()V+#4K0c}xx@bK|MQTLoOyu3Yfw gK$Ws#Ma2Gp15>Ye;b3(^b literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/cableSide.png b/src/main/resources/assets/computercraft/textures/blocks/cableSide.png new file mode 100644 index 0000000000000000000000000000000000000000..b9411ce0656453fa44ac102e2a6f21324cf40c7e GIT binary patch literal 222 zcmV<403rX0P)G)$Fz4Jws4%e(8!r@ZIo)8@aVVpk zdWAiMYRWD@B0fHnPMqzl>Mer4fV1yvNuG#5@BjIcaJkBiD9%~@`L5jXaG*-nupDvj YPd^-c$aQP~J^%m!07*qoM6N<$f=h^E0RR91 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/commandComputerFront.png b/src/main/resources/assets/computercraft/textures/blocks/commandComputerFront.png new file mode 100644 index 0000000000000000000000000000000000000000..6d0a9971f4baf96734264338026c2b4ac00c687f GIT binary patch literal 484 zcmVm5e z1l0tI#G>$6E`cUB)DRQ|hrpn4glj<2^xNGz=ge>k?BgGLbMZ`=m!2oacgJ-$jl^Uc zklr0!dZbd02on}z1?ckPIn;z{^X9EpE75$O=N1@aj7SyQHm^l)KisH@xclYncle)A zZ(kj(Fe9Z-*g(-8|^U?;S z>kc<&!cztHlCcH>vz!9JjfQnXmTUlu`71{Wfq;v>LIcRFFnR#{n^X2VtWwapmq>*%L z)EW)nHl0d%lmps|=*p6%USB0000&C|b literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/commandComputerFrontBlink.png b/src/main/resources/assets/computercraft/textures/blocks/commandComputerFrontBlink.png new file mode 100644 index 0000000000000000000000000000000000000000..874750a52febefe8eb3754777d29f437b33846f7 GIT binary patch literal 615 zcmV-t0+{`YP))F}L!pUl6$cj1iSurB>TtE`DIU1a1Mvg*^f|W7j*#;C2EX}p{u_OlFb6SnauhaYoGPoaAnV#7 zri}%iI76S2okiy3`_~%_K7Dvgn`fld#@$<68w+mVyg|Sbb3;`(7MLg=1Z}OcE{zut z@3B4PU+0O6ctZt76G{WcNJ&Y#<8-|yVgxrNX=0EWqH?k>XwLKzLQKp=LQE{w(XPYY zIXL{xqoc2=K(&At4>S*K=RmE2RwgFxNmj75fI5QBs6;$<93I@kYTk|XF&A9?rX zI}(*>l^?5-oIBhN2uOf%_PR-x5Fl7Z&Q33A~GF)HSUrcCvK zITVkWLrUqo2N(6=Qo&gd1zN literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/commandComputerFrontBlink.png.mcmeta b/src/main/resources/assets/computercraft/textures/blocks/commandComputerFrontBlink.png.mcmeta new file mode 100644 index 0000000000..536517bf5b --- /dev/null +++ b/src/main/resources/assets/computercraft/textures/blocks/commandComputerFrontBlink.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "frametime": 8, + "frames": [ 0, 1 ] + } +} diff --git a/src/main/resources/assets/computercraft/textures/blocks/commandComputerFrontOn.png b/src/main/resources/assets/computercraft/textures/blocks/commandComputerFrontOn.png new file mode 100644 index 0000000000000000000000000000000000000000..50ab20db4d9944fadd32cae19265d6bd2c3a1ecd GIT binary patch literal 507 zcmVS0000TX;fHrLvL+uWo~o;00000Lvm$d zbY)~9cWHEJAV*0}P-HG;2LJ#8aY;l$R4C7l&OK`tK@`UE=e*3!?jNy(#nv#yJu$3u}FX2fB)lo==JF{VV+tXWWL?a zV^$9gSsl`vfm8EPite6;MOXnkJADq#!n9bmT1!q|Z5+qy=)HFj6q(Ue_y_R1yC~Sx#l!#r002ovPDHLkV1iz=)vy2n literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/commandComputerSide.png b/src/main/resources/assets/computercraft/textures/blocks/commandComputerSide.png new file mode 100644 index 0000000000000000000000000000000000000000..551b042650037f539211301b10c73845acaaf02d GIT binary patch literal 643 zcmV-}0(||6P)(YSE8i79&U-5wiB>cqYYniiNTu|MA}qoR z(9a)#ffixvV~#m%v6y4qwi$4Dk5r-FM>YBK>t_~`F~*$Zb)K1Fh;f}Mc8&Qw-ZCTm zivTkvU@xYOl-h`RcnYZO4~&t-MHv79Y5NRRGa?3yjeXh#6wRTUB%tgAAA?6W;y!$-w!Pj(%#pt!QIVX#pV<9}; zg<%vjUVF9U-*1(3YenDh<&WRKP7k$0^ST|aZM1F{3HNisgoH4Iin6bzWBQLjd{DFF z?A5+cpF-%d8|4Z##q{(DZI3njU;jKgGF0{1<54vts!2~ZVF1P%5CV-#7XF&%aqzV!oYsDK#?yVgdnUxv3I? dVzL;3{{ZSGRmg>)p349L002ovPDHLkV1iD87H0)+jEP){EoMQF0Vyo` zN`MJa8OYHSX9nowAF9GXetcu1+v{QUy!vjE1;PEyBduT0&K-~ynjT?MieagL}s%8|hp_px$>pilXX;dAX zzV5p!ea`do*qhPkVdt@XArbcX@3GbdHDL!H#k2Uau^^o1NuuE{bH%t`fM#2Ju26!4 zEMjE@C|@IUA*l+@`-xDLmB7XX*X#K(1`2aJ7NH0Xo zv827{f_Rx(_!v=b(^$h0u#!}?nfAFNGYamp5UDA*NDIktx4L%
Ii)&6X)bdLLUdy vG~E_h**ojxJ5L=jNl1vH+=;~hFhgbFNbUMl10f-3P9Z5t40Mj(l_dV{8yK}i*SeAvu;lR4C6o8K( zULbQ)3Y3LRmp{zx_rTh5_9;cX#h;;p>-|LO*%S|<4=l1~o`22>h>nJ&AOczW6SBD|w24)yw5vT@P&i7BR xkc3Y&wN~tWK5HDuzw7)z+?|~BgS(Wr%0JjEz%FnE`{4ip002ovPDHLkV1nF@!^Qvr literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/computerFrontBlink.png b/src/main/resources/assets/computercraft/textures/blocks/computerFrontBlink.png new file mode 100644 index 0000000000000000000000000000000000000000..7689310eaa1a67fa9452dfbbcdb0dc4197769da1 GIT binary patch literal 467 zcmV;^0WAKBP)H8jaxm@tx=LqV$&g1XIoO1w}@pzmcY1sVl_z`7Ul2Ss6 z2qA=*!v2#G0##L^fTt<^4r2_X(FnCzELbj=ZwsteD~vJs2$WK93xp78+m`ot{=yi8 zQtDpHF-G?L{lkSrhK5uRc<=9ZkW$KvthI;;N~wG;?>*johK6gJhNfw-)>0G&Mr%z7 z0i_h)d$iWM6XEy!42K*J2V#slg3)HPNtero;VO?15wzBS%?-k;>pHa7`2$EP<^I23 zugqpMCX)$8Q6M5X=W^|Q{NNiu_=&*})H6T$iH{$A{NTU(!50QsKQxdeO%ebA002ov JPDHLkV1js+(1QQ~ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/computerFrontBlink.png.mcmeta b/src/main/resources/assets/computercraft/textures/blocks/computerFrontBlink.png.mcmeta new file mode 100644 index 0000000000..536517bf5b --- /dev/null +++ b/src/main/resources/assets/computercraft/textures/blocks/computerFrontBlink.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "frametime": 8, + "frames": [ 0, 1 ] + } +} diff --git a/src/main/resources/assets/computercraft/textures/blocks/computerFrontBlinkAdvanced.png b/src/main/resources/assets/computercraft/textures/blocks/computerFrontBlinkAdvanced.png new file mode 100644 index 0000000000000000000000000000000000000000..58bdb26bd67dbf07395ad5799c01b942233b37cc GIT binary patch literal 534 zcmV+x0_pvUP)?AW>9DG*hm$Czl<-Z{ptwmvRaMje9GQgxKwK;qn7K*8uWHW0jnndZ zgps*06Uws80}F2UeIyCaIsA6Jm= z;oIH2(cT|68%`860~9A6CW+zH1B!`|QX=LLdK4M&hs4SUII2!K%)(7|D(g&A5_^*BN Y9V*jr?)qJY3;+NC07*qoM6N<$f+Hd6^#A|> literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/computerFrontBlinkAdvanced.png.mcmeta b/src/main/resources/assets/computercraft/textures/blocks/computerFrontBlinkAdvanced.png.mcmeta new file mode 100644 index 0000000000..536517bf5b --- /dev/null +++ b/src/main/resources/assets/computercraft/textures/blocks/computerFrontBlinkAdvanced.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "frametime": 8, + "frames": [ 0, 1 ] + } +} diff --git a/src/main/resources/assets/computercraft/textures/blocks/computerFrontOn.png b/src/main/resources/assets/computercraft/textures/blocks/computerFrontOn.png new file mode 100644 index 0000000000000000000000000000000000000000..ba657ff3afe05732a2a405636fcf470810047735 GIT binary patch literal 304 zcmV-00nh%4P)z=csi~?;ilR{E zc`j+1N|GcJ$Fa)yeQBCTY#y;72&61a$+Aog8}mHNvMiUHrs>c7IF6c+6cC1?2A_|I zlK|k>U-r72 z>wx(%ec#KrZO(w>IHYacH(=j)X8<)i2X_HD&`GpM_$Ct3)gD7=x~}^qu&(Q>j?g)o zI4c(keH;wKa9Lnw_pFn1o;skDkPuC|5{ds~w&n%a9Ne~5(#XmH0000KyK_377{`(AcFQzP z6o3!!pCfZp3Y3LRmMrzxZ+uJ9L0gsy9czPzJGenYPF)| zoH3m+1)Ld%kQaA-(Sx8e{pwm&j0jMnl1kTd3(t& TLh?3f00000NkvXXu0mjfrmMnN|fJG^5FaCc1EMIcX>FiJu`FW%ve)Z6%|Fn$n%`iG^Hd- zD2`)>@B7p=4M`rjAPA@|OUkm03q|iYqPMNPfcIhgzNdZPoj8tzwr%4R(6RG8scqX!06`EsD0c{G4iG_p z2O^-m=(}B{Iev*>BiL?i;1Qax>+S@cZ!^m%+66lphQV2&7io|3aDYuh3BXcZK%&h_ Z%@6XhcqWvM-X{P6002ovPDHLkV1nY3ks$y8 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/computerSideAdvanced.png b/src/main/resources/assets/computercraft/textures/blocks/computerSideAdvanced.png new file mode 100644 index 0000000000000000000000000000000000000000..ed03e6b15a19583de1a1a132640fdb783b8c271d GIT binary patch literal 584 zcmV-O0=NB%P)uaph$^fM4(n{;^t#-JR*Gn=iQ&j+*&u0#Y1DQ!?a=Bbs*OiBd2gVq5fbZWvV4wr%v&=|s9in6_OfdAwR! zAp;0X^FU=-`c4J?_VyOrxI~ND=`?D3GdQpc2T0Hg$boHoW)g9O#tH(ekboT=F;kPCJVVVnYK+N#1^(VXPEVVhjdwr%L;<;ADd>CZaoYPDx omWA4ACFB;FN?|VE#(%E!3+mWJZ^xVuNB{r;07*qoM6N<$f|#sJ%=P)ryFFKtxx6y_!d6XV1h_9zsd5VzZAg;fnIg9 z`jIT^`T5yZ1weOGRoJGx0eF3V<#akxRa6ykZ*SagHy$4!nR7A#etiE6tB7cv#xjyY z0ZaRcUZ)zE{Qd1G<9t5jFNIXt6U(1+Ok@HOp1{N|tb&+yH)D)}atC^$Q%FJ*ZX=8> zU>=_|xe3^~UayRYhXrXN#CUpog4X~Q=qrqWfj=Pns30&V1h#=j zzC$?~V=N=_<+iXrX+iTJe&iBqb`-V7t->zO=kp0kwHg+-%BNE&&Ywbb2ixdvwD6r6Mu-Ueak(mU! z2J9=+1H?ao`P2%$7h@A(x_7AMM7_Mc_;R^?tn>dxRguS1eKhwl-7gG~B4Gs3m@5DP N002ovPDHLkV1nW<@r(cf literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/craftyUpgrade.png b/src/main/resources/assets/computercraft/textures/blocks/craftyUpgrade.png new file mode 100644 index 0000000000000000000000000000000000000000..1627782468fde2779b39830b04ad178aea787d5f GIT binary patch literal 312 zcmV-80muG{P)!fKKsq0#* zs#2tBD)T%G>yXQ`Oom~Qwr$1X;<_%m?>ma~JiYJZIJ6#6f;`VPi9*1}Y{tnZ{tPG7 zI!I!oD2i7gIexAqP@cUEV_U-*`*CGiekI}(rzNm?#vD}%u!vtrpn@bx#No+8_Sgtv zjQVMs9)fT_7Fy!i4&V>BZJWpb_7y;|EXzZ{x3!mcS)l?dQy-AP?!az7Y_eqP#D7Ns zU_!U9tLJ&^b!%x_+}c?c?E4;VAZ!Eu;wiu;!31C_F`zKavF8H^Ob3qUq0e#v0000< KMNUMnLSTXcl!&kZ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/diskDriveFront.png b/src/main/resources/assets/computercraft/textures/blocks/diskDriveFront.png new file mode 100644 index 0000000000000000000000000000000000000000..bf6c711f969d12cb824be8ba2b00e304008276cf GIT binary patch literal 327 zcmV-N0l5B&P)_7<46Di002ovPDHLkV1m%wirD}F literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/diskDriveFrontAccepted.png b/src/main/resources/assets/computercraft/textures/blocks/diskDriveFrontAccepted.png new file mode 100644 index 0000000000000000000000000000000000000000..7b3d0d1fe6fc8e0162f3debd1b28c38588b970a0 GIT binary patch literal 332 zcmV-S0ki&zP)@pa%C>D@EX(rsp66NP0TqbjSV^e<0|=m7 zgO;F75?~eZF2&(=ATBad>f_r|kQ#7O;KSbxGg%9|1T)*iOD7U~>Qk z^&e2cu42F4B(uI0;PfXxjo^0U0-w+f!*B<{{+gMi@Qil{(=>S#>_xhxe06|LLJ7c9 ed_bVfG3O0Mr%I5uLbRm-0000>vEWnyi=gT^Ku!<@VsJ8F zWgDpGa)@u+_AOwah^M3I(~0pv%s7s69ETU@dCI=;Y607KU6=HI{}zA~gze-T0yYOw zQ2zl1>?-!#P5S%&QGnB*_%wpsjSGB2GYrEW0Q=v}9EE4RJD8@)n_w@}9p$3~Y!XTU fmf`~fU5+^~QcOrfH@u_Z00000NkvXXu0mjfR)UX8 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/diskDriveSide.png b/src/main/resources/assets/computercraft/textures/blocks/diskDriveSide.png new file mode 100644 index 0000000000000000000000000000000000000000..9aed498a5a68de337cab7531e87123bfb60e6cfa GIT binary patch literal 327 zcmV-N0l5B&P)nN|fJG^5FaCc1EMIcX>FiJu`FW%ve)Z6%|Fn$n%`iG^Hd- zD2`)>@B7p=4M`rjAPA@|OUkm03q|iYqPMNPfcIhgzNdZPoj8tzwr%4R(6RG8scqX!06`EsD0c{G4iG_p z2O^-m=(}B{Iev*>BiL?i;1Qax>+S@cZ!^m%+66lphQV2&7io|3aDYuh3BXcZK%&h_ Z%@6XhcqWvM-X{P6002ovPDHLkV1nY3ks$y8 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/diskDriveTop.png b/src/main/resources/assets/computercraft/textures/blocks/diskDriveTop.png new file mode 100644 index 0000000000000000000000000000000000000000..88e2ade7823cbe47332790382d3f7d2b5e6e223e GIT binary patch literal 290 zcmV+-0p0$IP)oYPDx omWA4ACFB;FN?|VE#(%E!3+mWJZ^xVuNB{r;07*qoM6N<$f|#sQK=Rp)uiaU2;CyRIu>-}mtT z;we1RggZb?zahvR{0jmIT5DyVXBo#)j4?6{LqO9svTd6z%Mv(a4`u&(RV#2NwI3M*HYnOP4L>g$nKoTwjvE4q)sD X!l>#7Tumv500000NkvXXu0mjfZ@p%z literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor0.png b/src/main/resources/assets/computercraft/textures/blocks/monitor0.png new file mode 100644 index 0000000000000000000000000000000000000000..88e2ade7823cbe47332790382d3f7d2b5e6e223e GIT binary patch literal 290 zcmV+-0p0$IP)oYPDx omWA4ACFB;FN?|VE#(%E!3+mWJZ^xVuNB{r;07*qoM6N<$f|#szKc9PGn;q!6idy?eNa;MR3b($28&yR7S~Se8YmX_9dqWf%rU z(=>7%hcFMZwryqGHks#H0uHY0lALoDF~-OKJWtIBa2C3*(;zm0UGp-&yhJjt10>l1 zKo%RfMF}kc3s$a&nmrJOzVBZWOP10%t*Qcal2TJjcM@4_;j-DP03-Y6v({LvSPR&S zUe`V77(HgsKP}#4Bum+GE8ntOb@xlOEH(MH*kg>p=I=fvj*-cpXId#$JS=!DrIpuH c{^xi80H<712dPWLV%C>ElM+!)iL=Qhf;3NRJ zHCTe|3cwkU>j*voddSD5X{t0=0AnkFAbcH!VJL=QMj$>RwrzU>d>ybKW*kS^_uUzA zo~QJEe*uo;a0bw$d*BPefo`Jj2=uUoW*7#gc{`Y3XpStg8K)-eBfFvOyLU|K~ c&$GMd3khVdV;R}^N&o-=07*qoM6N<$f=VoJ!vFvP literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor16.png b/src/main/resources/assets/computercraft/textures/blocks/monitor16.png new file mode 100644 index 0000000000000000000000000000000000000000..4b1c67dafcf3862bb1c6fcf412becc0ec190a05b GIT binary patch literal 273 zcmV+s0q*{ZP)mLR(V zaK^`N1RnrBQH9k3rVj-&4T?hH83Q~SQZ z0LO7S1L(0m@CD$&HqmzkdRRgkhC!iuJD8@)MnF*Cy6L4 XTMzG~)_ssE00000NkvXXu0mjfakO?K literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor17.png b/src/main/resources/assets/computercraft/textures/blocks/monitor17.png new file mode 100644 index 0000000000000000000000000000000000000000..e7f90c3c95389af146ef0871ad669cd95c670c64 GIT binary patch literal 238 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`TRmMILn>|^oqUk1RYAb@uY{tC zlcvzZ*56Cyxt6rbtLXmPS9zzBV{gXNZuL2>#*a(a86C28|7>G?*<_+&+m>r4Jj}{V zm!w9nxT1KiR5mg@Q^sA$L*}@n=F;$_9{b<5_jk%Es80!!5!uSE>$o$DL2MSwuYLck zR>oGGT*mhywc?^$<1#)cjw!`?!WQR0pJ(zFyH>jN^{!W}+j5h+8Rpt(TE;NFE6urE meLk7f;8cD>+`NrN&zQeu?Q4%cy6_Fq0}P(7elF{r5}E)nUtH4w literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor18.png b/src/main/resources/assets/computercraft/textures/blocks/monitor18.png new file mode 100644 index 0000000000000000000000000000000000000000..1425de96546c9b37e2163366b7cdaf43c8fb11d3 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`m7Xq+Ar-gYPPXQ1QRHc{?MYDW zTEroC&s%_-Uqx(Q{&cvhmb)~U z3M97_^DX+$m(=soBl~Uk`mIg%CxpYp!}Hf}J#fbIe?tEI+8<{w>Ue1`pT-jUlXKOF c_r3LTg*&_JUaWcG0CWU{r>mdKI;Vst0R4qVu>b%7 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor19.png b/src/main/resources/assets/computercraft/textures/blocks/monitor19.png new file mode 100644 index 0000000000000000000000000000000000000000..59ff8bedbf212aed2161cf90c2fcf67ae1b150ea GIT binary patch literal 233 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`8$4YcLn>}9o$SbURDs8(TD$Gd7s>wdnugwbb zGI>>CcHX%1{YgvrV9nMAQLmR5ovZ)-*(UQ#2}3y}!}c78Il8A0u|Kdp(a!52rojaNvjc=pa%>ZwL1fHe+p)x=~7rV~h_%2)u0@d+*sf_rMs# zIcG+laMoHrj)V7oXDX$zpw>FYbzR;1JWs|M*?SrYDGPyq$6h)# ziEH~>Rl6gt0F{~j8P|sR%l*H8NGM)qMwHRT>ov}zbPoRgoj-w2Ug-SVgTDX(002ov JPDHLkV1fu;aWMb@ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor20.png b/src/main/resources/assets/computercraft/textures/blocks/monitor20.png new file mode 100644 index 0000000000000000000000000000000000000000..96844dc38e7aff424026a08423eb6e92ebec86ca GIT binary patch literal 250 zcmVS5Jl%-6eJ=FLy26tH~Jw#T=e1dxD!2i@HR~_i$*=(dz)z6HVz?3t?SCmvhY05 zJWZ37wU$##{Om)|ImaE#0e)Dk3t{1yOZ zxLhn~062quXdFlJ`4#}%0zeR21;!XAd@=;0331=|8=zHy`Jm%CR2cw}bG`vu3o-{< z02Ih1YAxUlhLB1r>JUZ2d7df@Uj;}~W8wK5KOQr(=XgfXssI2007*qoM6N<$f>Bsv AO#lD@ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor21.png b/src/main/resources/assets/computercraft/textures/blocks/monitor21.png new file mode 100644 index 0000000000000000000000000000000000000000..953663a9c8db556c263d90e5680d52c879bc1dba GIT binary patch literal 208 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`(>+}rLn>~~oovYGDk$ReJ}$$h zWkrjVe~yO|7x#Ys>!<(!mHsPZoE+fQc|FQUzCR~~on*+>Y9Qe9UGG+l z0-LsBYi*M_SBr>cz=jVszh{a*R5puDlsdcT%o^|4yNb@uT=}^%JyJ}K!AtWlLj_Ah z&%-H`xE{<&p0%tqd+jQ&9Wh!N3?F(PpGa97$}6~)wZSn%nCI{Tlk=N@>F3-oW8T8K z=ev)gTi)7I=5?`xXI{1! q|L3S2P;qQBn4mt7+H4^M(ChvJ1fpJgTlMF}ccRA#S#DDWb3 q`=aXioc)|e$7;C#KegTd{m!X(ZIR#n^NJW3ssI20 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor25.png b/src/main/resources/assets/computercraft/textures/blocks/monitor25.png new file mode 100644 index 0000000000000000000000000000000000000000..ffea7b8e0dc1cd068f5429b4ee409454e482bd5d GIT binary patch literal 191 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`ZJsWUAr-gQPBP?TP~>6x+ifP+ z6p{6CKg-4sj!6%HD^)AV6onQYGE=k8ahj5}FG{;rpyPG;T2spd)#uq0Sh98HFI1~1 z^T-EyO=O(lkgXe?)Dt*OVd)X}HCr{FpJ6{^nOfe!vdCK|c|!5Kc9t1WIj%%6XJh{I ou39KzvVvp8sp%Ig{>z?c3)gQ66bpQYW literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor26.png b/src/main/resources/assets/computercraft/textures/blocks/monitor26.png new file mode 100644 index 0000000000000000000000000000000000000000..9d047e8d0a6100f76befc1e03d5d71eea9cfbb57 GIT binary patch literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`NuDl_Ar-gQPCUrTV93F8xz9u3 z)2He6N7|Sa`$gU*a=(i_u))|Yw71xA%PZ9f_oCSa0^jU?-EgmZ&vye>jss^Rju^6S zb8y+9ufh~qooLAAqR8W7+oPbg zNTVwuaealNqmE6*v>iDgABLwf2hV76PfO8M%=pZwWPK5Un)UIuk*12U_WSXXkaU8{aFMZ!j*L4wf zUCX+zf;^2iO(XL>%PXX&Oj4O zQ@5c1hkIi#`G>`{MzG`)XZg&Gnz%-00E;Exip4FwS;*DoNDcU(FL{O)R`F?#mKB`E d%k=Mc{sF|wQBW8anu-7b002ovPDHLkV1gF5dHw(Z literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor30.png b/src/main/resources/assets/computercraft/textures/blocks/monitor30.png new file mode 100644 index 0000000000000000000000000000000000000000..45eb7903f07580dbfa812f2d22df34a0870ddce9 GIT binary patch literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`5uPrNAr-gYb{ldrDDtp;p3yK> zL(uuae9okYhrb7Gu-L&KGqF)~({4p$=e1uWyd2L-YN{TQ=s(kQP3m1R3|U|Y|{^^%X8G9`xqWuE5Ky={6v)Zu^GCWs#l|4-Z?xo zs4K|p$=>DZ=R7Y&y$&FA1-ls22WQ%mvv4FO#o^-PNDz+ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor32.png b/src/main/resources/assets/computercraft/textures/blocks/monitor32.png new file mode 100644 index 0000000000000000000000000000000000000000..9aed498a5a68de337cab7531e87123bfb60e6cfa GIT binary patch literal 327 zcmV-N0l5B&P)nN|fJG^5FaCc1EMIcX>FiJu`FW%ve)Z6%|Fn$n%`iG^Hd- zD2`)>@B7p=4M`rjAPA@|OUkm03q|iYqPMNPfcIhgzNdZPoj8tzwr%4R(6RG8scqX!06`EsD0c{G4iG_p z2O^-m=(}B{Iev*>BiL?i;1Qax>+S@cZ!^m%+66lphQV2&7io|3aDYuh3BXcZK%&h_ Z%@6XhcqWvM-X{P6002ovPDHLkV1nY3ks$y8 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor33.png b/src/main/resources/assets/computercraft/textures/blocks/monitor33.png new file mode 100644 index 0000000000000000000000000000000000000000..0aa2c7a9dad829038eb39c91e5aff57fb7606ba7 GIT binary patch literal 314 zcmV-A0mc4_P) z&pFF7K@>&Ybsg(DaB&=S(==R`B@;H*b>)5ET`bG;RnPM*=K<_dk|aW+0PI?u@zo|B zrfY&FO8`2>@>WzK0*GMkzQK!!L6oNHkHv6Gm|LTY1Kgxq-L~yHq*JVLc-i6rzwBR5 z?_#ZE5wMDHxBdni$C1zTba7o5AIBkI!0z4mEu08o0m5!-4FSt(qv8>;Q*7-uDF^Yt z5kfa!L>h+SIiRXuW{ncMplO=i20JB;^5vlKdwG@sp0WqLmypw*4<=EFo$cs%p8x;= M07*qoM6N<$f&^5DK>z>% literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor34.png b/src/main/resources/assets/computercraft/textures/blocks/monitor34.png new file mode 100644 index 0000000000000000000000000000000000000000..1c45f99fcef6012d5ca0188e6bcc03014e2f5ea3 GIT binary patch literal 290 zcmV+-0p0$IP)ICPCOFV+dG|jfB_^b)Q0m4IitlvhzA&-1SUJG~(`9`@sypboT99qAo7FF-Y1uIqXyDId;HBuVo97vAQKEtbxP zVR-HUiEmqv0q?_|=V`}rM1i|~-+c`8uIsXCn*Id<5PHco1e60<7}yMaub? z_-lmFO$dA!PVFPU&CF5M#qA(gpop z5V~bq9y1@y%qZ4{I@q@D^%+A^9uCk+Unw?3J~1480Dxjsz{M9?)Bpeg07*qoM6N<$ Ef_`>|hX4Qo literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor37.png b/src/main/resources/assets/computercraft/textures/blocks/monitor37.png new file mode 100644 index 0000000000000000000000000000000000000000..5b0ed965cb90ef684397260ac75dacb4865e77e3 GIT binary patch literal 286 zcmV+(0pb3MP)kU_xed7e)bR4lO{c2N{eZQFk4j0Ov5!!X`JQM;OPEX<3%6 zaxOn2PSbP~K*dko+PBIe)I9)!Rf+6JHQmIo2;Pl{EFsPF{Mz|kW<;?r)WN#0pU)UY kc{z|tdZpYFd17(!1ClCWccus&@Bjb+07*qoM6N<$f@J)9K>z>% literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor38.png b/src/main/resources/assets/computercraft/textures/blocks/monitor38.png new file mode 100644 index 0000000000000000000000000000000000000000..b2f798b9b39632b63bc9d17d01ea7c3078836e66 GIT binary patch literal 310 zcmV-60m=S}P)(Svuz4+)~+cLed^`)0{3BiY&R9ztz8lO|(B(=@Uy%LmqVm3`k8 z^E~Sc&ezp-Edc`D;DJKkLlE_V3S?QPq^a_^HJdAgIjX8kLQxbCVX#}6_x1r?t`XSo zFT~=dX(}Pl^Dm2jpq!hdssILIR<~_?itH8^_QOt+L_%4Xe{;qLYtGuXeGB-19-Dd$ zUDrt%$5GDnjN-a3IgUeDfY0vxmcH-b0yqT0hqi|RbASozJ1_yhh4;RRIem%$B6v3* zc!XgXhNl4Qugn&OU8sX;nxYLnNFU|H0VWA007HoZg`TsX7X*id-L-vn#sB~S07*qo IM6N<$g69&2B>(^b literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor39.png b/src/main/resources/assets/computercraft/textures/blocks/monitor39.png new file mode 100644 index 0000000000000000000000000000000000000000..1be067a7e4b4313bb6c86b65d58ed89159e6baf2 GIT binary patch literal 287 zcmV+)0pR|LP)i4BPLB48@Z-?}|Sph=RW(hzGxKj}$VxzUm>&Wo?>F4SnCIbzKW=+m?>w5G>0g zD>$z%KtMNGpiu82h$+Ur_npr3loilt z&+`Z;0(bzS54nec=GaJN0X;?Uy(V%H|BPVWcoD-mj=6xUUS>wIF2X#|ZiAj;qZAH? lVMzFxfVOR2;D50kdw#0KmOF|_!`}b^002ovPDHLkV1l!?ea!#> literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor4.png b/src/main/resources/assets/computercraft/textures/blocks/monitor4.png new file mode 100644 index 0000000000000000000000000000000000000000..9aed498a5a68de337cab7531e87123bfb60e6cfa GIT binary patch literal 327 zcmV-N0l5B&P)nN|fJG^5FaCc1EMIcX>FiJu`FW%ve)Z6%|Fn$n%`iG^Hd- zD2`)>@B7p=4M`rjAPA@|OUkm03q|iYqPMNPfcIhgzNdZPoj8tzwr%4R(6RG8scqX!06`EsD0c{G4iG_p z2O^-m=(}B{Iev*>BiL?i;1Qax>+S@cZ!^m%+66lphQV2&7io|3aDYuh3BXcZK%&h_ Z%@6XhcqWvM-X{P6002ovPDHLkV1nY3ks$y8 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor40.png b/src/main/resources/assets/computercraft/textures/blocks/monitor40.png new file mode 100644 index 0000000000000000000000000000000000000000..b1fcbf6a8add1ffca90a01bd9f4ed8e2ef12941a GIT binary patch literal 258 zcmV+d0sa1oP)wd;8N0YIlWbJqVdji`3MS=ExbRA-JyVTco_- ze{!%=R``ci#}@tb=+#%S-uv5H3xQm%b)3HLd7i-;lOQz77z31JBVnpQ6^)}Na_IfL zf_D?GXlkERqn){mcVXUsq~ceZ9Hf-q<2VNPeGjp1+YiT{52l!OV07*qo IM6N<$fCOaK4? literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor41.png b/src/main/resources/assets/computercraft/textures/blocks/monitor41.png new file mode 100644 index 0000000000000000000000000000000000000000..f1defab7558f8ccc3802b8da73fc0d1afe16af1b GIT binary patch literal 288 zcmV+*0pI?KP)i4BNlx#e*Oo-NFA7M8V$?#KXRCk4&Pm)OQGTX`7~ zUf=gQAfN>nNYpz7S#t}3q^f?in69)L&aUe&0TKkeC~xfpP18IA?DPe1yt=M)(8YP( z)RD%(6#=RtxUTD+q`aM2`~ZY*UTJ6UEB`50$rpX m<>dgIgc5+IctE1%Sn~q_Ta-7e$`vyJ0000ujP)5QITy)>!4-qu(th{(^L?MJ1qII#k z5mgA*b?vCvb@d^*Xkoi-AxJ5G=JXb;iABKvb8qXjqMY;8d6pj$g@6U%VmGewwX3G< z0@}sH_jIfxX7{1l7~|@_hw$85Ye#Es|EoIl4`0aPg}iq_-0`yw z;7OqJ8kfPwWLR5H05IpX{9u9QR-x=UkujQLV?}(1oB_=@bIzxT^Vxq;P%(4l#cV>!N(&y`M=WDUN#HGpw)spZpKkYkx9hqlh^^Mzah_*?YH=~f zwuyriR!AU!3n6j_ff&Kc??{F!E+)_8I9>u6090Z7DqrBe{|HdYg4W)??``A3Y1LQ} z`^44>z$VV;c}5W1*Zu+L+_wd*Pi?SJmQtE$fSqeo*N}6539QOi|7fw4G9S`9ahA`O zk<;&hE1-%dU$c!%{Ad4~FNE+75y4i^XoXcwKa-_IYh_ZP?c6$|l~@$~0KPtL2meck Q0ssI207*qoM6N<$g7#W;F#rGn literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor45.png b/src/main/resources/assets/computercraft/textures/blocks/monitor45.png new file mode 100644 index 0000000000000000000000000000000000000000..30770c4fee1d50dd130f39fb62471a157b13bb09 GIT binary patch literal 290 zcmV+-0p0$IP)M zfo6=l9s!nR36-P#5|JGcfvDJyYx`PNySoXrif7-eaTC8HSU2t<&GY=2`6#nQu`Xa; o*T3UxqdXi;)AUk`hR7rS0gNJHn)6lRivR!s07*qoM6N<$f~wMfQvd(} literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor46.png b/src/main/resources/assets/computercraft/textures/blocks/monitor46.png new file mode 100644 index 0000000000000000000000000000000000000000..97c9fd35ebc298070be710b6b16572cece161d61 GIT binary patch literal 261 zcmV+g0s8)lP)T|DO*D#a_>7WlZsTjaDmN0_)DbM`Q`#SYvHfId3|g00000 LNkvXXu0mjfthICk literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor47.png b/src/main/resources/assets/computercraft/textures/blocks/monitor47.png new file mode 100644 index 0000000000000000000000000000000000000000..d4b11c7f32e2ff5a7773e10ed1549cd7b409737e GIT binary patch literal 287 zcmV+)0pR|LP)uU6at*R=Urpfxgw{V`P0r!2oIF2Lv-}l`Z^CW-~j(~nM7$<{Bh7)Ro8VIte zU6T@ZU4IjhDF?4S^e50k6=+TZmPMNxdGkgL;cER`+GlJ)?O zxvqP_euQ7lx%ye+wr%Mmy*sY*m6tY~nxj_wMj6g35pIx;F_`kvyiH l60ej*fj9Hq61@{c!3RvEUwb7W7UKW_002ovPDHLkV1gsOe)|9b literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor5.png b/src/main/resources/assets/computercraft/textures/blocks/monitor5.png new file mode 100644 index 0000000000000000000000000000000000000000..b2f798b9b39632b63bc9d17d01ea7c3078836e66 GIT binary patch literal 310 zcmV-60m=S}P)(Svuz4+)~+cLed^`)0{3BiY&R9ztz8lO|(B(=@Uy%LmqVm3`k8 z^E~Sc&ezp-Edc`D;DJKkLlE_V3S?QPq^a_^HJdAgIjX8kLQxbCVX#}6_x1r?t`XSo zFT~=dX(}Pl^Dm2jpq!hdssILIR<~_?itH8^_QOt+L_%4Xe{;qLYtGuXeGB-19-Dd$ zUDrt%$5GDnjN-a3IgUeDfY0vxmcH-b0yqT0hqi|RbASozJ1_yhh4;RRIem%$B6v3* zc!XgXhNl4Qugn&OU8sX;nxYLnNFU|H0VWA007HoZg`TsX7X*id-L-vn#sB~S07*qo IM6N<$g69&2B>(^b literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor6.png b/src/main/resources/assets/computercraft/textures/blocks/monitor6.png new file mode 100644 index 0000000000000000000000000000000000000000..5b0ed965cb90ef684397260ac75dacb4865e77e3 GIT binary patch literal 286 zcmV+(0pb3MP)kU_xed7e)bR4lO{c2N{eZQFk4j0Ov5!!X`JQM;OPEX<3%6 zaxOn2PSbP~K*dko+PBIe)I9)!Rf+6JHQmIo2;Pl{EFsPF{Mz|kW<;?r)WN#0pU)UY kc{z|tdZpYFd17(!1ClCWccus&@Bjb+07*qoM6N<$f@J)9K>z>% literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/monitor7.png b/src/main/resources/assets/computercraft/textures/blocks/monitor7.png new file mode 100644 index 0000000000000000000000000000000000000000..34dd9ecb28d845d4ccca443abe975a5d56ebb105 GIT binary patch literal 306 zcmV-20nPr2P)p z5V~bq9y1@y%qZ4{I@q@D^%+A^9uCk+Unw?3J~1480Dxjsz{M9?)Bpeg07*qoM6N<$ Ef_`>|hX4Qo literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/printerFrontBothTrays.png b/src/main/resources/assets/computercraft/textures/blocks/printerFrontBothTrays.png new file mode 100644 index 0000000000000000000000000000000000000000..28cff888e80dcc98df1acd3e687969f7dbe1e5ba GIT binary patch literal 327 zcmV-N0l5B&P)JuOU zw+5D=%p%||sIvwq1ie^sxsE^q6p!Qh7xrRBJ|+l)Q}qdOsR9UsR;Ot??J_iuK(2v0 zjw1%Y3>&|MSeE5m;F^IA*!>Ip9oAA@2JwbzQ#&wrzVn0?z0=pa6lJ z>o;x!wwk^~j_?<3w(a2&nx<*a2CU1n+}sef~ z<5`3Pj$@z}C-!4J&)Ze+0GBF&MbPRn47*)+;|S#F z#Ih_g_+?1^XNh^9KL!5U0qnjm5qI!DOkLM9&+|Ulwr#({X6w32S(ZE5BDyA=yBm4x5uX1>VrmCvF0OvGKCpQFf?ut852TjvlULaSaoE%`2Py$%W jk*|+;2k+#ElqkQWn(GK8xF$Vu9Rs;I;g1P|;ADLRs8j+NL8;R;opRZYBM?_5j^l{I zm*L?b6U(wZ2!440xla>OgZ(gV+seAG=Un{zZ?f5J-*>6&`XJc0?ez$#(LEpm0X5e< zIsvwrZX!qc1}59yu!N>*nll0CvMe_>1mg6H9;kw@>#PNYZIqh=I0+^Irr3bQXN)x; X0&^`~za1Ps00000NkvXXu0mjfzWjy| literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/printerFrontTopTray.png b/src/main/resources/assets/computercraft/textures/blocks/printerFrontTopTray.png new file mode 100644 index 0000000000000000000000000000000000000000..d8c0f611535d214cd8fade77fabfe7e8c479d56a GIT binary patch literal 330 zcmV-Q0k!^#P)D#aa~ucsuK30=6Rmvc`iwkh{47ei9f1NU9>?($_F_doCJ2I4^$BpP0tkXur)fIvGBl1ru7Ns^ zBL=?=8~=n@mgQUEnt=`2{R|Oj@IFl2wz974IT!!^H`}~y-*>6&`Yo_++v5>%M&AJi z2;5x1aTBoB^d)kHZ?M_6hev3dra2q1F3WOrLr`Z{%s?G*V*mgE07*qoM6N<$g4-d9n*aa+ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/printerSide.png b/src/main/resources/assets/computercraft/textures/blocks/printerSide.png new file mode 100644 index 0000000000000000000000000000000000000000..9aed498a5a68de337cab7531e87123bfb60e6cfa GIT binary patch literal 327 zcmV-N0l5B&P)nN|fJG^5FaCc1EMIcX>FiJu`FW%ve)Z6%|Fn$n%`iG^Hd- zD2`)>@B7p=4M`rjAPA@|OUkm03q|iYqPMNPfcIhgzNdZPoj8tzwr%4R(6RG8scqX!06`EsD0c{G4iG_p z2O^-m=(}B{Iev*>BiL?i;1Qax>+S@cZ!^m%+66lphQV2&7io|3aDYuh3BXcZK%&h_ Z%@6XhcqWvM-X{P6002ovPDHLkV1nY3ks$y8 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/printerTop.png b/src/main/resources/assets/computercraft/textures/blocks/printerTop.png new file mode 100644 index 0000000000000000000000000000000000000000..88e2ade7823cbe47332790382d3f7d2b5e6e223e GIT binary patch literal 290 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/turtle_blue.png b/src/main/resources/assets/computercraft/textures/blocks/turtle_blue.png new file mode 100644 index 0000000000000000000000000000000000000000..13b4b78d4759d0f2dc7edb60f1f8beb7467779a0 GIT binary patch literal 2064 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/turtle_cyan.png b/src/main/resources/assets/computercraft/textures/blocks/turtle_cyan.png new file mode 100644 index 0000000000000000000000000000000000000000..af25d879ce7411ccdc5f5518a09702f7eedbbb16 GIT binary patch literal 2027 zcmchY`#%#58^$+>RO8h;jF_;LCvAB>M9yTawSz-gL^&0Y?P)YQW+N5V8y!%Y)5s%_ zL*&$yIrb`T)$oSZ4W$3W2eqe005wYK85t! z@|0iNzHRGvIRt;$vTY$46cVucYl~aUA8nBxQK$SU003yuF9890`Py4hEe4HqRTHQy z0kn*#`gS3>bZr%pcF%>k93m+1K0FgT(#UoiBEDTj^UF>UPpngDl*xtAqjf zX&|xNP11Lo9k{J|9SSTlV(l7SF_k(gX};b;QzB#&HGN|4ouE(WUE-Spu=l9gk0}wkwCG zVu!g)%5NGLg9bt?ojJL0Tx65e*Z2{Vqinakq}9OI3vBY3-LJi*d%VuXX*2DzZif-(k>_* zu5R9yh>c+-H0qjJ>!(p=kMYZOfP}Jf*3deE?|5KhX_1HH_8#$DF?OMbeDnolykAz8SVV5WIYqrc0K<(+Fl zD(mDPZ`m03PWVZcXFijnYh4G&PfM+BZRr}ID3RE#C$?w$NfJZ3)|9Pv$A*o$S9r5{ zgiH(I?j3olm}t-;1>3#X;rU02{G1Ix=tH62X19x`Y}PZ{+I|x6FJ-cl{vCoKVLGF6 zb!Yp0)dz@D7jgrF0&(h5no&($Uwit|@@TWz5LRML;QZA*VaEss)HGsD$>R_-+vrOy zyaU33{EgH8r;4|kcfUzM(4?}P+`mj5+uQ|pAuRQgI)84E&Zb;_oz=}BcrEIK(iXe5 z>NeYw6qT9W!=Lu^_7=zbs7>9;Q}^lLt>1LDOPt;s%N4b7YiH{v**lnVMv-whzF!Fp zKlNNKN^gpl#?)%`Z_N!}6t=is3Q5VK$EnRKvMBS5=Zm)UHWFB&jiQ-qwUEZZPNiM; z$*b8J8Mpi>+3p&S@t&1B;OO{sD;*#oT((za(bHx(Z~>W`wm}Mxp@55SzRSC~KhF-o zr*ubaD9|nLz-XF53lb{A#6e-EkKJ)yPU&%gYKDnFEAH#FN0yUqKX9kb8OO672{JXk zdBL}#)uD=timC4M3a4d!!%3QnQDIget?Cv)D`f0z4a(H41)*#GE;;)6yJ?PFt4)YnLgFt#x71W{eo z6L3VhJkX}W74^r-7h!x-Ni`)4HCIE4QA;b+Se5;ZONFe}ij zWL}lT%DhLjfvG&V-*Sge5!60@wmgSlcesq5g~4I%{)pIBiUKa~45%0VxiL#hB}gq0 z%^e97rFWmc1f>4=V3s5T6r>edqDqfPG=+a0BTnncspIYCiG>O0^UD`JEes(?1m^JE zOuiO^5OY)233C4`C`eRyuattGVLnYvBIXi}AW!IcFUAUc`4#g}(ed2SR15h{hS%r# zCbE{VqDG|D!p~BTfgCK?=l;sFz05lw;~Su%k&NP*)BsT~mKsYUSFqlV@rah{=cPTXplP z3RkOg1mbj7M^7|wQa>!SZuVCea{G?w;plT~Wf>y|=Nx+A(8kxj7oJeDZ-;uLYJ=Z} zGi@r-O#Ns`y8~ynrDqD1Wf)VS`n(VS6H7Mb*roPPK!V=h+2`*Pa(uwEOS`bXM{dJW zZ7@zjmXJ{LHJ~fk~S2ptzVKXaMWPW#5(AJauKg=9fp-g3r#;ELvul|ZdyW){GCxfp4 E52)D0mjD0& literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/turtle_elf_overlay.png b/src/main/resources/assets/computercraft/textures/blocks/turtle_elf_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..49a191ac61106c108e4c77343fe31b05f01adaa5 GIT binary patch literal 1941 zcmcJQ`#;nB1IOPpoBN$|>A2*3l!}_v<~nmJluK@9Npp!7Ddv{T@j0an!@ASKD05I9 znz3juE47^>bE=ceFd}jvVrJp!kN7@bkJsz03|n9XP?c6 zep(i}nQitV?VE)RJ#yF?Z2VMdbH$xaB6ra>kOY8&#!th*A4S@mP$u5Z!$n4*D5WGT z72_UQu}QYOIph42`(}#TJ@t-n091>%PPOBy*IZK(f;UD@%g8= z__K)11AYVF-4>+$S?-Sxx!(GcsSS^?h2};+z7glWykTjSk9;M%)73-ehm8Gb-8eJ0 zO=bLU0R1d5%nAbzDIqVbd-!k=FG&Xu#0VtldOHpSZU+@W<@Xc-<;=kWlldG5azoXC z&}Cby?~WfZB=CO5#c}lw8rkOQ24fOMz?LM)3Rhe?iNuER)P1_W<@sZYaMsbq)C@op z-5waNFe7mE_29GU+V{8zGh#72_0Ckm<%TXAFRG0tkpM`1P76HyC%RAHLjjM+OM$wi zL;!k+yYRlZ0a#X1o?Z@-1qJ1o_r$YylxF8GLuGjGgG>=;OoBZFsx zo7vV5bu0z2v+H@jfk$V!8Ai9Z)1mOKbxEgosii`EP+m!~vlvr)l}8Wlj#S(?v`V*Y zNm_FVguE4nebMwksnp_nD0L>Mu`65IP3xwM(^>)2 zk(JW?oJn%dY7%k6>5$m;v)sZx`6-Yn$)w|~y;sGt7zAr^5kUT;rVTNvaGVi3es1I1eJu9{d&{C|`|f0?7_66|-ijWn{cfYz= zsVqX3|E{wBqgoM^WGtPG|Bxd3ZJn8lT{nwtQl0BT$TmWv>_EH)P$gx05-o2ltP})6 z#%}6x;6=5Cfv45gkGRKcDId%=JEAp>hNC{}pKj|6x0uw9q{Hj*W^iyR?=49sfulHy zFRB{B%#L*jffo4;8fTij*T6r^PiES-)dVgQ=-0 zB)FfS4+Bc>2^}FlHDuQC@s;#ZlcTnShAp3ZzqUV^O6z5Ch(m+SX7q(YKN+i(X1!d_ zr^OXZ0X2R83jz>?**be12P=)VO50GE#Bsgu7_FD@yCxz!FB+2`cSuRK3=|5_pF$_j zYUHghojU;7<~ASpa6i=#`Ka?l+!P`e@2iegzQ7vsYZ>y*&-*B&n?_Rv zRo`ON^n6S|%L~yHM&bRVZWrvDfB40c4nF0Tg1)eUll!W?oY&CX5ODl2#D$nXcx*s* z0Y8#hWfRSn;wL$f3y0^^sMz+e?R^Tn0-W>X9-v;IF2ara;*%-HSJy*qYJ5%Q$z6q*E%vPPSu{eK5)_;mT67yV9Ko=cM*4wN+j literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/turtle_green.png b/src/main/resources/assets/computercraft/textures/blocks/turtle_green.png new file mode 100644 index 0000000000000000000000000000000000000000..3cd361f256b6dbb4f9f8c7d909308ccbbccfd29b GIT binary patch literal 1980 zcmcJQ`#;kQ1INF!90{$5m0O{c%8}`)CC)~Yo?LPXW1363Cu8M0V_SLXAgx?lLrJ;C zqFv|-8%`X{y%mMB^W-wxvB|Jz!_gn{ygskb=kt2KfBgLN$?@_yr?tai2LJ$CF3wKg zTTTAq?LTehYx~Q6TlG_@+c_s-^M@XDY6`cAI?g#D0RS{~ei#Ill<93jwL};9vuXlO z6=3&qo=G)-i@3Nro%T%~UnmpALs8J4cGg5P#?{9{&jJROSD4!GQimvyY;@FGnVCjI zyT2d)j`D@Iru--?K}$8(Z>N}rg(}-$arA;5|JWSe*Em$j1UaPr~wu*SVf^IgquEgggKH&_ zlws?m-&+ke<=6Q6khVqqH|QGLA@`FOZQ8?l-dhzQm)1xQ677?sj{|?L4zY3;nvK(L z9BTDLIxyxibW92eAlR2On_HJwu-KK+vgNhzC0QX|@>+@(34SguGcG7LVE5aS2+Gtef$_jl_(+MBCkO)YJ}YZ7}>=$|r4; z`Q!c&VlQV8B-nJ?sd;!Zvma@xxJM55N5rJa{tm1+h-!NrYkBe6s$^z72SFQOux~j* zGICf#!2<^S%H#UNe`zFg_vPi!&`%Qp|M~QQq@`KyyU4(4LW6E@i@Rr&h!_5(O;jUx zeC66_#VXFq%1Tcq*9*c~_v;0dpm~t$T?QL%{uO@IisaYPEVDk7Q}z24&aQqY=hn5N zue@T!ozKi$+1ZYJ3^|?A*0?EOec*+Z=M*02fZ<-VD0Y?Sg3`3`^H+q|g`h+WucQkb zE2l$Cb21GQP|6WOlU?$cH^20YG-~DXLf%pCQdlF%0f%nGTfZQ6=V0$jIJ{XGA)P zH(FhWWuSt z-L6Hj3vFf8)umT-g}-^Rmm*0tnq|K!qTZ^I(By6X&XF80Z%Bi#-fufN$swSm4`AmQ zNScmr-aREcvbU1MPgvTxP={6xh|qZj27~=Ei&8WmoiY{cu!&mg~)$bcsKc*$Gw*C_*cF zD^v0$VECH96PH(rCp)*lr75F0U^72ZH26*BLWpyia)lvY1(>HY^o9bSiv4u2h0_aj zOKg1NQiL9VOTdX{0_8*dOIeZPn{jrcppIn#`!k}5&+LS&&RvA;s;AX)5Csh1S>2l% zCb;9LI@k}+j0p|BXAbuj9Z{-S97sylpQ?H& zFMS#MY&Kqy+jCFi)_j*L3TaEdhwA*#F30Wr|L?(ns8r)BGOD@w9pzg;3%H#1aB6V8 Gbn_p{Y{HEI literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/turtle_grey.png b/src/main/resources/assets/computercraft/textures/blocks/turtle_grey.png new file mode 100644 index 0000000000000000000000000000000000000000..9f641e698c6342f4f4e8b1e11562f8d126977cae GIT binary patch literal 1541 zcmb`H`#aMM9LK*oA-*|Ij~bC{MP*b*#c{u1GM;23ml7s(YwnjBPjsA!t|~P)mr%wM z*|cyvbBRsla>itf8BQ)UD|1=x@IRc-`+2`#&-4D_^ZD&_%Ny>Zq^Pb40DzL4tK)@j zX76~9+;-BfLm1nTyXxWM2uOECY^!;&-6&jl^-ll*P-VxvfTwu1?NUC`&C^MqyH^HK z)Am9%V*x<+zMG@n#Z>kZ-o=OKzTcUA+B{G1$qG8TsVe_~G|SJ$CXO(fa`N&Z7j$dau|)q0lEK<9vR2K+KQ;W3E|H@j*@ww^i@u<)t8?Lc{#&6|t#6Ay9V&eWIl$I8R6-Z1q!&S0aten`N0|e<9oldB=i?2s4 z&@%)NZy^t9Q7j@w^$iWxMXcyEM)?)F1Ql(;+FFY`MCW3FJ)g)>%|>9`g1vI%BA?Qz z)b+>J>!vP{YQ%#-AR^z-!s4uz(l{EgA2l3x01G*4c==O`wQWavURe?;9-^}h1_lK^ z?_>7&mz0cu|DIHh#{%Jt6|U;|f!*u)o@DFuzqdM93Nec_GgV8Crgd}98kteMu)ls0 z3Nd$k7W{2OVywbrtaG3$4j@m?KKC+o9(0|CPy{)`* zFhN^STuLI59+m~nKa;(ll@*7|LN-k+HwWGH?!m^hVZKqvwq|LgwkehbeKGp$hKG@@ zrKLM9q|iABk0YN1kPZ$Gl_V=)^_K)u0uO~+apV{H_J+%=fI(AKKd5Dyuvm@0OGx$tYdNYt%5Z_LN@cA!XBL4B;^e39x*@ z_~!9`A9$d8<+@*qNiU7ls9{srSB=Tb%bO?~7KjAP%m2Ir1~aX*?VCxj4C_<{v$Oh* z)2gbf9#$bsKiEyhI3soAG6KP%TPozaOkhN7dT5Ee^Dd`!36TyG7k||#JnVVmnT_vX zwId=#Gf}*|4{qB!+U4#Kn6}G9Z67&j(D&3-c4w*@k6g_yBA>Hv&WBjELlM^=V>ny( zTEJU|3>6byYf$E^#8?2sd?%{>S7nE~kt9NLS*(*uo$9F(Jt}J-dLNA=li1g~uv^hd zw@c<2Qv1T6X=!P_BRWV25xQMaGja4#{6{*SUIOtbX)h=!urG=t7n9{*5<7OL z*RH!4Md2RlhbIlsPHx@ALSmfCc{Wy7ZF9xDvnZm-;_Xb^~Aac(0y#I!3u*XSJIX+_Ay_%8ma3%4X^4 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/turtle_lightBlue.png b/src/main/resources/assets/computercraft/textures/blocks/turtle_lightBlue.png new file mode 100644 index 0000000000000000000000000000000000000000..a93c391503794ea10db368f8e723b61bc28523dc GIT binary patch literal 2038 zcmcJQ`8O2$8^=Fnsi{c|uH}+8M6y&A(^$(+Fin8;@0I>VuPf39M0;O#z8)NT$QFdaF zBv4V5YKcH@le_jdmWbP<+yX|VyoXX}Fq6AD1F+hp>5LIVG(^*k>*I%gs-1{sDVbOZA{!YS;IG*}_5$HW-T? zyU!?`jU#jEWPSnTJRiec#bw@?sg0Vnk_OpR00j3JLBZVIoJAupEX+YyUoivVn=rGI zKvPq*UObH{nw0=gwm0sr1ArXdCkaO0W_|M&uW-ja*F-11>ufH3UKn2AOiN3vO5nNg zJvJC~W?eG;tsDVXa&DTaT{Sx+NH}7D^!6&OeI=SpzzE^q&^vjJzOKB z^UAj|I@mE#SmDz~gCB~t)hF^_XgE9^^usibXO5`xQcBL70pNS?AL829Gd@ZR;5Mhj z)0aIXMcJpubRfC?vq}BMQs4$t6cX6_l2UwUO8%}`cU}mIiWwe^LTN2-FqzB;^%N4x zR#ng;&{eQ0s|yjT`>8+I>l5fFEz1B_XO^m`Pb|LinVM#~`}O4&lw%T9*@#_=U}`~m zV9A=2U6tig!Gxpdg=xbwK}JOqc#=a(&1iHrf^U~%@ZJn-xLDBB)AOL-rzCthHmlY< zry0}K;^}vmnrkGE`wlA$g5Fe>%J(&GF-El>-3+DVDHl%B-76!c0BNh52$Q)u;2Z!c?(MwP2V-HTBaqE{Bx+?s=%I${R$?+V-Lt&$G1L@*YbY95L zPTtda@O}N?%-2ep!r(nmdZ+7NfIFFyuw7tnvfUz}l_;CN10=)FkJK~C31b~U4qAG< z<3+1{)hiU#ttqvX=^BpOblqZBTw#EA{wW%v;Q=ybBaEN%Ns6AnU^64mUQk*=+$?-< zZ`xz+fnPqfb-<3~wBNQiqN~4K*xNn>)zJGY(QbVl3CApUAed1rgG6>kydUeu(rBLk ziOy0JGCC+Quw4@W(Al+ahZFJrNB8{C;RlqPg}oD|$agW1*RPL^&apc(JVJ4+XL1PI zJ|(wL5U+bNiLqi?IrZzyWkoHKypGcXVM0yH=K8Wzr7FhNe@MaqW2&?cEV#GgcG2hb zj4r$6lc$5+CJH7Wp(;}=>(UuiD%H-6o4onVBoc`LUvZYKPDaYHS@NZQikxTyRC!A& zVUiq#%t4C>Xw6IPb0U(t_nR#G4ob2sF|Dg|fA^(FWLfl=fQ-1k8y=4tVO%(dCFBH4 z*ka*jo9JG3^RKME8WrI)$(v!PJ*GFg0}J2S_UWRj5-8Cxkk zz$&LjG+=+LJ{4>yVa%rtAsqv~5dc&2YF;X{_Ef}5%=gmQ9gqGsq(z-{)z5{Y0`QGk z(p&yJw7g@o0mU1AN>DvuE_V@h&{#xJ zUau}b(YnEQ8IsbvF<-A5vfcK&aIaSjS9y-y2YS zflQs{^mxrnV^$mb#>QJHcxFSguI(&xZ>W&9NDj)Ln<~?X%kX|F+We!b6{S_}fsec}KTD OG_b$uVpDD9pZXtHMdJGa literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/turtle_lightGrey.png b/src/main/resources/assets/computercraft/textures/blocks/turtle_lightGrey.png new file mode 100644 index 0000000000000000000000000000000000000000..2e783448bdc5aeb59c6315a502d8c516c7d16988 GIT binary patch literal 1680 zcmcIlk2li`AO5;%N;bWfA(31gXTdcMK z0APj*M1|{>`V}Ud^epsFkmzL-HaGwUYh@1WAw->c8-$sP_ysCC|UGngMSSZDQDC~<3?)xUf!~EMIch? zw2C0xZQG`2W_E77$>lm-jB~c2-%-P0FgW~>i;E2$&g1d!WUg_;@6l+qGzA=vjjp26 zvWP@F?e*kj^YH2Qv9a3|>lBelq}h11_S42jfj0qtp&7h4EhOrZDYLF_{)~~2bVj3D zh%IJywW8pA;qd0>W~iiw#cEC2W_NiuE;cqo;EhDitQ3|(&)!+5q-&<8l4;5UZW_x~#r6}fSZ|EQECinSEoKeCFv z{pA=b6C#1AeGiX*yxqRUo6rZ+A1sqq%EI@&7^dOZth^X3mElqM3cN`k)$S7LtW!18 z?2xDJ*qU1zWGl{4s#JC1gbKF0tu#-=l?69g|7_;?tx?K*t(9#QFH!#a z&oPZg^Xn~1(xaJ40~ape@t4Fz+hO4bAua4WY){;$-ie3h&hnvjvJHe-9o>dtIXgHk ze^#he)j{l!Q-kk%=jSu?N!0%S{-WNSOd_zbfP#Oxo9nA}b8{g|Lj6o8uhUz<>>E%F4Go=h^=Y}}4|zJ00|j=_(HkzZ!@Q;AJY ze)H_nYyLyZ8~PTF;&*}R=!zTmQ27V#McAB9rBoucWx_&%#i_~pFiH2bXQ}ihQSA1& zv(WhDuX%>9?l(ro1|(Q`c2c!>bJdV&0*( zZADKD(ih+K<8-fwgeP|v%OIs!rvzbn772!yJeOn`B^0tHzAnB+Fx zdI7L@TW2}El-}woxj@@o z#;Y57gO>5SA?A_C5OSgL_>Ufa2W>J3q~E0oE(*H4>*s-eMbL)GV6$GzVk{{_VCSJL zr20=6d-oY0PLUB}bAa7mK-!D?2A!$za$6zUQwh&AidpObb9C^dtXe=p-SW8YxJ4}ikAHH2Y3^sT_t*bBef)!9 Yaol9C=lIGe{qF!U=#wa}U;O2N0WiiWd;kCd literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/turtle_lime.png b/src/main/resources/assets/computercraft/textures/blocks/turtle_lime.png new file mode 100644 index 0000000000000000000000000000000000000000..833f3c26e802833828b4918d3fecf3174775a80d GIT binary patch literal 1971 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/turtle_magenta.png b/src/main/resources/assets/computercraft/textures/blocks/turtle_magenta.png new file mode 100644 index 0000000000000000000000000000000000000000..ddcfb62c26adf4bae78e89089e7665ba1c8d0aea GIT binary patch literal 2057 zcmcJQ`8U*y8^=FLBpM`JOzQGAS(-#-vV|=9$`Z+)X^2qSvo*#taV=w~Yh(z~7$p00 z?7Eg>jIkuQ85-9e5vGyBV3_&pkNBSFyx;HVyncMnd7lUCc-vY+Oi>H~00~{?qL9M^7JnW0Qh40BPbGXYkyOOE-nZt zUjE#;Mm!=oTgw|R|_iPzgnGgJ#W?c&#GgFaVNpnfnP=Ub*QV5k*%t??L!lqx| z+iNia6oioi13pqZisIrBp%b8osxSHnayFD*S_)Gh{O()XwYonM5j5L#AI|x&g#(Ar znX0aV6Kmd%8*+-nSlS|2z1}AXiveOufCx3=3)(+``9H8i0A{wX`wZ;|SH17` z$hZt>Vrohdkf&q|0ps=8m8n7G4)V)z_3gI#aRZsHlKG5o_yo?>Z@d^k$65ciJWOiG0E+w#KDUdOb;4O}L8#qc?B4sOQaSFyTXgtfQ55^*!!(?(i3#!r7w6wm z=MTxt(it4slhxwdL#5_Zu1C|ZHYF!Z2nMD>O$wFWI4*A>0?ntERqNi!W3T`wfEGBHRyr1tX`E!i)(a zyFX(gySNL?%^;Ic{;4UU`SA!>x9O%t^IZDOjO(AQj@QdrH?ipQUc2jQt=ah^q=#ur zh7N7lVKBVr@ke?Lf;!V522x@Chd)r1$Qo+<(iaW|7MP}AvjaKX6{V~4W>1*fw{_BX zMmO2vItj{lE9(Tu)Q^1f0dIFSIHE|qAW{&>dIw?BqEYHb1apo2%T1Zd9Kdh3SUk3j zQo_>R;ZxBUwhkoZ_E*2+Eft=~l#Xi&=cN69G5&5Y6t332uG{mWm72O_M|U5+Vx(EQ zQPUYbLL!XkaKw^hm;wjUf82{zLK&P>)IGMOXD{ABiQ=$SJGl-3&{Y@f*#0?et6In> z%^I|ztFP~SuicXUUJmLFAXTPtu}9mo1|hukqPIl8Y-Cdp)6zxBxiB}N(Q%~7W7oJdK(SULpmWzMJn#mJ zYQ8l4m}4!iUdgGS>qborU0X1B3)M7d5AZ! zt97?L0K4eZXF2c`F?`6H@A7LYhZlxwoJkzv!^`3i!9GF3P(f7}yYz4(+mTR#dTR;NUADS9$)JVa_0}cr09X~le zp`QM1Uja(-{KEjZD<85y-4j?>(4Umeb|i&Lnv`6^$@uPtHu*e5UYt%ihNUu1+NZde z2seD&R5YJy6r7Ex@2q&;L1B){miRd46&h1D*<2-M|8E)E z9$I(3o?qKzcP``ZQ+`Y{3t@R2Vl0@t$lMbxQK(3@F8&EtDLPxILyh%2KEEc!2AX&X z!b^)Nbpz>_UoO0j7(=n!k}8!4rA|g|i!1f9TD~pWwUjVy6F5fo=sH|*Ha$Hh_m+o# zk^Q03Sis=cF|}+*`ebmWLM^sLWmxEM54`BwT2n`E-q5p>&^e@TfnJgRXw$<*>p#`L zUq!`@dCe;1G3dQq5cmhGs+NM|6PBTtT9-1B?ZG37hMMk-PfxVH$;M`F&uf?Ijav3! zcK~B!V*t~~`kFPf@&@9;dL2K>S4)+VdCxA|w)=sc7D@DVwbvq-}dj_%;Id2UOr z%tp9OV(>*v+<9z0E(Spdn|&tIGy|q~M)ap6o=ksWvRqYdphnXE1QSydNQ94PwC zWn;7ak79(DBqBt(3J#Ja6wbu?IqW;%Zwxc4AQi8UDs#EOV~RtbW(0utainUg*~aw@ z17m`CCBJ|EO46u$E$u^F+hB%1`~ENC)gc+)D9WX^FNQK=Mr83z`vyUC3$>o+qUZmR f{J&eZ15czf#9QjT_3(wGrw!QNylq)$?wRmEt&rnY literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/turtle_orange.png b/src/main/resources/assets/computercraft/textures/blocks/turtle_orange.png new file mode 100644 index 0000000000000000000000000000000000000000..c0f5d5e5bb1582e7ffa9ff6f6ad1b726f574a5c7 GIT binary patch literal 2114 zcmcJQ`!~~%AIINwX{fQnhxkwlVJ^p1k}uB$Bq2R`@*>W)2nMJvC*BPLi;`jBdh z{h9mB$U~=1R}L~v+|~+IzXd%4duKrHB*0ETRL&!_K< z=key?&-1fKho^b1u{nZ570fJ_{yEVhc zYhhismvaU=w`f*IUz{muBH1XJ4-1<-uR>^H7f0s#lEAx;m9wm(-1&rN ztER|2%JVhhB(3VZ=;w^3S>}|Msa)-PfVzRwN5a<6sQCDRHj`DYZT;gG=5@{X03fR>2|x&2kz(&YZi;7G z##uQ^-f<;F{SjLw7VbAms; zvG%#c^gyksRa2M0ee+R%ULMDprqi4{Gj^`Xe!SL|Y-HJe_D#zPJNf<6Zp)Ry-Mj7> z=cH!3B6L$p*TOE9qqhj%!qa8k*O>M%HQrRzEuUR|l1^;~BV?t&f>Fhs5596g1fOLx zdJBDY|5HF?Rx!t392u49Zg(K4R_L0L{0OnaDR5Qf7kb}edsFCDizp*49(S6W_yv?d zsY1eT3PmzDQgsYv8~VqAV0IC{bD$nf0+1~gk2)XRVc`bd#RoO%+R%WLQs%l!TZM&% zC;wnjJTI7UN_<2q$Bo_=V2~%vjfw(gMeQjjz z-*D@_Zw#gKruIEowZU?frx6Qq51gHBcVI{RQM~byY-CRDhVObJ@)zOzn2Koz)0>-n z-L@`8hX)dkDSrFZzYbnj=l|l~##~IO5mzzw5+$sN-b4GMC#TX2k~pW=xb4>B8$qG> zXIW!q(C^=8B8CG0=w=o79z^55_JE|?!q<(=lAWHLvWFq;O>n!UOz9_=fThgzDv$UO z*NKRwG7-e9cbUIi?$jF4n841D-yPkUAJ2yiRKhBKQZWZwdX)8sRn0KfF9&nj)r6gs z44Hiu3Xu=}yZ+?#4w|^EdVW}Xg5#jV<098 z*>7GM>7ifJ&q>D1IyaKHX@u=&FyIkhDAAKM=#TaSZXAf+_>!=Fd8lDYcY2_{X`tcS zX!#IUkrkrD%+w1^bv`2nl|bowe?Y#3)xh__l7C!_ZJuW0LBJ`VwZD%4wR!H5By6XrRYj z{l0rkE;&z0rV7jCGfSzJ>rWaY)veVVj*5hiwTc}+!C}336!$D{sD4~U8zCDQ>o0zc zWW@)kISDFjO3G-uC`unMZea_BxKtaGoFEUe+(grxBCbNOCMdPD=OIaD^2$~Y%7$t?2jhw~!kTo99|8Y{3mSo3ZB;tGNaW_Mkp zGZZV z!Po+NG>jVQZGuJZ3oG-m+-fL;!n!Kl(mkq^p17c@&JS|R zb$(SvSv{o2QBW)3_u2EZelbLPj;`=O^4sJ4F^2TF+PFR8lRAavJiy8SHkSyt!J zeitSUZ`q-k=4)2_Z@e{b+xG8!ucMED+wii;ukwxCAIAk@(_O=!^(NrvWwR0QR%cla z_oi44HoobTkcGO-eJ!vf<#QsMKGs;D9gnn8b<2Ee^0J*qS!^1h@=DJ(S6*(z$6*7v zZ^0_i=(JjSo1guX_lrknrxETPYJigeoBGq%RFc0o%76$jG0wRCmX1ssW;`KAP_N%+XqU#Fiq@~nu4cr(W`OdZ*#~!43 zZc(Rbj;*`1G|8@^N#_P04=q4PaB}_qJvH84lRlq94c*i_<6y@5yxzQm*!J7MjG_Tt znCG}*ah{Nn0?Lx!bK+C>v1{Jv?R1#8Hos5>d^p|Jax;$-vX@JZ?3`hUb^KK`1gO?n oQpH`_L;pZ+W&Yn$gxoq%dlwY6wyNs1^X&m=2Y35w+n~Gu1AAEgc>n+a literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/turtle_pink.png b/src/main/resources/assets/computercraft/textures/blocks/turtle_pink.png new file mode 100644 index 0000000000000000000000000000000000000000..364269df05cb0ad127f9c3cc6464291e995b0f7f GIT binary patch literal 2073 zcmcJQ`#;l*AICpy-_aq>Y*}?WoF++bIYsWb<~k}Vmv9u(1zo1F#*A849h7@ol!V+S zM$K*IHmq4En)@bNBV%kX&GqPy_`cqc*X#9oJb!ur__}}cxTBK7ZUq1Ul$@Q=r#74T z%Uk6(v&HH>YqR76F^*_p6oi2wja_%DNi9Lmm3D1X!0&0e0rZ40o| zJmSpB@=a3cjJ7=;JvdF_UqhThFgYUCLA$4c`{t}?Gn}@5bxx8q8iN}dHreEt+uLk; zlifwlw0kOdB|)x|RPryf?Etj>C-H$wpwlQwWgP;)Q&yu{PBX8Lh|R{&bW@%M)K51@ z3RiFwkz$@{#KrHF2oBx4J>Trjjd2Hi^f#03Fj!4Z4GiXv!6?dDNF)+0XbXHyCUYzN zF=(_@DvcM%P^Rk8=z??<3dO1-lP`TKIfF)D7&6uqtVW4>HLHEq!7SB<1Dt^A1%6ZP zP>H})u=PSt=Iy*u?8dvIN&6E$JG9H`bs*U}xazch`PVR?zj64|i?-%k$@03wYJbQ3 z-O+ltEjR>N@|cU zqqMYCe|knF+BPo>lLbTb?ezYtN@3sV3!7xvvf`v77z$N)WBlHi(+bK9m20iqq`c4; zkJp?J3UGmoo}%Z56N0FIxBR7NZ8mi=I`(IB#GS%_G|r+>Ubu}oI=*8{%7MCf>fvBj z(>qx{-rmKSdb-}LQ`*m+hV{9n4Oiu}wAywF!ffOE`dWRC^~lAi{vnj}_%ehe9C()h z22+#p0iolf;_^C&8ay=7bb5iX(^^eBr z7^KGZ}lTSVu zmb$^gelg65rAFk~$l3+*UKHv_y~$uDH)8U=cdL!E1;A#rA!S36q6hMfOGq&64ddg+ z=)-02SLu_7aTPBHpXSYn^|xftZF@|5M+7NKOX{N zk4aGBeE}HIL4*43OxXmZkpA9lO4Ow3lwH0Dm_Yj}>2eR-Aaq4MOb>#=EUQD!5$9gJ zF8pB#{!{W|MSZ>K8njnbXB*xdj=d@U&hAoAs&2!kv)wJSB944yNE^)TV!np@t->7guk|-eDZrNcilu z!#COQLMQW$W?OlRqLRzUd{YH)S}qkOm^(mXlMA9_7J`igy0 z%Eiy%bW{ijrA|@FF*x!}Pdlt?pJ&tR4>>_ZZnvRLr+-e&RcpL%GB4|(S8ct!B~V2y z!vjy4`yGT2iVvBG>-tt;GngZJPm&+~&im8r<5P?*gb|+%8T&>RpY?jeCTCb;bMvI@ zw51lBFHfsaiIQSD_FxGh4NUHMIYJuPl^vZbKe{HooIq<9xelOe1hX{#xGdEi<3*3< zXr@wkwY0&UMV&v=8U8oFrn@6+02}~Kncty6>Rr;fPWbBnZDzzlGYb-$phcbo1V`OE zp4a-F%zm=ymGg z85N})@S%@9t?+f$V!mP$59b%}b(po{9$qhS8p|;XJ+vLz{Rv$8O7&LnOv#VPe)M$N zSI$|1LuZy)-dkU$o5BPY3@bdOo?0L0fe^2O%J}HiMT32Y|4PpX;Q?NrepG+KbeiUH z-`s;70gtZ1hgSMY1o-7loj75n)r|l9S-_~-JUzdz;7WbvJrCjmcG-d@emHBlB5kIfOPrc^y4;LT0_|H~#wVtpqQzm;huYyI`j+5R}X!tPwce`rwdivR!s literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/turtle_purple.png b/src/main/resources/assets/computercraft/textures/blocks/turtle_purple.png new file mode 100644 index 0000000000000000000000000000000000000000..473b1c126a357f0e1318cbc93077ed24ec6d64c6 GIT binary patch literal 2047 zcmcJQ`#TeQ9LK*?SuC7WLs2NH6tRjf#>kk3(aN1+3So(kVbiv*=!7DdlyTy4T*8dW zopYEw;p8?o%9I#o?uMg3;yj<{{eC~s>zB{-dH?c>w#8v&q?M!r05Vt$G=3`?KebbG z%l|R*Y~Kn=q9q0mHh)e=O-{lVk-BB!bQ=KJo}Yq%)K`1AAoMq^wHcJZO9Cj$zNST) zY>_8ew8_=5Vc{!&Alwe#T*oHeXpcMdXfNM-yI%ao+=qKVqehFO%)>7~dF&x0%{qb> zl>d^M;Q_x4m)~P*rTZAU+_miw4NjI+)N;TX_@56dEq#0nej8uv8d4&O?b?M0; z(kgCG%ygXp!n{3`7G$eVp-|ue{<|44#$cczqpVDROnCO@h%Uzlhm!ykoiCvvB_&0d z)*e(lyA3?wy0|$A01}A=z(5EhO%xX!dtq#o9W1!CKxfkPHtAtugSit%0^`)we&=+L zj5S{@yCyzc{hi~(ULVWCPTyHcVT4`pEvQD*%|PLHuz$6NU;Jtzl;&HiSV7#UUxJEN zPnJAX9_TnfB<;ffI-x%E3wMj zvNo%=OF`~kZ!f+?OoV{q%-Nh4GEY*~yyxY=bwV-`;nI!V-W^&d2n`8&pT&nMXz6kz zSYm0p*H<}+ewO*r=w_6F{@V?0FgickhcneQ9_f@#$bx&43(vh+*?;OdT|GL;`~l~giy*Xx$(0Ht7IJzkGen=iWl=T+-f?eMoPOA>P4m=A55Li(Mdv(a-O zm1#=M*#?oDX>0_ciu~q0vVO4vbE=Gom_G)cFt-K!EO{;lA*so5!?o`}+6*Jhni93& z#q76iSK-QV931*e?q7VyA9Bhw2y6QtiQ`1p41OHLR~i&g`##J`Sp3u}9u1{ZskfUz z%%hR{Qj+x-$b)+ZcTMYVS_H6f{(yk`97T8QfO2vV^n&D5=c@Z^kICXZ;x+@>o*_$? zFZ8H6HFsP_YrQh!Go~K^g3D^+M^50l(=maA{qg%Yt@=tIw*}NJMYg~yMblo~3GEs_ zMx}0QIMWjR?OV%h+pPbHS9MYbiVGg%vCfj-){}|%I?s!TKJSBRFuoiyu)Xk7iQphvb#K8 z$bP8jegQk8KE*I+OQ%XL8$I=P3?3!9T8_)8vC)vmiyGY@MePYM3dYjL-v21uA@GMK zcK65jPLE!rdHa7;S67z>1*#S4(z{tzEn%Oiity5OgOc6eYQhY@UM zt7ZQ>Ao|nwD)c`k?i1^xmFgbCa4U_f%}ncdpl)2r!Ra+sBL=qXS3$qd%-D}1T#TCL zvW}coP+wtPZOf`DnG14iI^Lr7vL)@b4=(GKIcjrsG{aQR_?ynok$&nSM7njmi$)D~ zN$h9(nLll0q#n*{p;NCVBD@3LHoUTtNL+2BG_}jnvr(aHb}igFSV)^SS_%_+LtMI$ zzG7yZ5(@9N_0rst-mDdgtFT6}HD^0g97W9{FN%E!LExtvs)y3o=q7f*)Vjtd#LbaKn`_@=M3aL=4wdmE1xAQ_qFDH@u@A{W(wQ0-$~vw+3V9A+zR92N zQAiEhjiJK%t|S+N#`*S?32=BnTwp1$u`Tu2G7do!gUI^)_8u{b~h>-Hz; zr%vf~DeZs>LPyW_#Va4>(@^zRt%~7zXt5ysJ*0P>KYf%zlxOHawHg+|Zd4b4U0+=U zt1I)o0@lgTS}8G4LP}nHXQz+khN0?rwU+byBKM_M$J0Jc=P)KAd1$6>n{(LXD~zoo zf>ND?)WvIBiL3V#U|K!xioa&YWqqYk2U>#hnNLcf+TPq0bKL_S~5$ RWo^A`fHlLR3om-y`wzC2-u3_h literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/turtle_red.png b/src/main/resources/assets/computercraft/textures/blocks/turtle_red.png new file mode 100644 index 0000000000000000000000000000000000000000..a2dc71220e0d2a1f4a79f81ad5e3b61206a97382 GIT binary patch literal 1882 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 bvHKo$W4z|@g`A6DHx0Nrx;xPAL+|_#58`O+ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/turtle_yellow.png b/src/main/resources/assets/computercraft/textures/blocks/turtle_yellow.png new file mode 100644 index 0000000000000000000000000000000000000000..5a10678953afc30a1a83b4028214ef3e14777a76 GIT binary patch literal 1930 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 DX^?2| literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/wirelessModemFace.png b/src/main/resources/assets/computercraft/textures/blocks/wirelessModemFace.png new file mode 100644 index 0000000000000000000000000000000000000000..678f2ce172e884d65b80daa54ba115bbec311c12 GIT binary patch literal 324 zcmV-K0lWT*P)rhLx$M&dyCLopQJinVVWizhQZPIy|ry?P19Ii z*N!~TZCMs$9b!dM*f@^Xb)5wy?)$dqd6KxU>-B%0r`H2cP?n_!Q3&Wan{l#pu@{N`1i07h_B7OIjq#8#W~c^^ZX?sBiU6=W3dm|kFf9iNUnI_fU|rWQ0iR5hYL=?1p}q$sh|SWa ziA`qAH&L(f*ZXrvVqgiwwr#JS*In0QuDDL-6CB6!@4BY0@|plnf(d{rDWEWpvF8I! WwkN01OCg>B0000 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/blocks/wirelessModemFaceOn.png b/src/main/resources/assets/computercraft/textures/blocks/wirelessModemFaceOn.png new file mode 100644 index 0000000000000000000000000000000000000000..328808350fd002846106b7ad5a69f939be06fb02 GIT binary patch literal 259 zcmV+e0sQ`nP)9hmk2;ub5ZX_rE!GEx&)_S(qT$EBC z|2gNLZ|DWKYq6ju8o1YC`|6OyMuFby9T23#IExCKMqs-!MmO1b<2a7_6ZUISitLdm_3@OJ-tBMV0pmCU!!WIb_qwv6DZc%v*G{6qV}eF0A*AuyLU6VLzv002ov JPDHLkV1nv?aykG2 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/gui/corners.png b/src/main/resources/assets/computercraft/textures/gui/corners.png new file mode 100644 index 0000000000000000000000000000000000000000..7f68611be01e64d8f424ad500589d3d8349b95da GIT binary patch literal 974 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G$6&6EaktaqI2fjk$*$L>eAG z?`X31lWQo|h&XU~M-rpHQ|Aha1G_@sh)i63frT|z=tFJ1dt<8P&+Eo>d?yFZVqOts z>^qskVd*^?rWMzp)!12cB``6tFbFUJ9l;1>L`+TFe?OXoWh>i(po9WWhAS3~JH#1Y zrD_`NU_ntQ>)m*eg(1WeBn<-B)_Q85eQe?8a-_VRO|Jj=ju^d(#d%6fUUii_a*A)h zv*;`TuBw#xjs3^Yv(4{+_qcK9-ahA-@}s(c4fBlUnOeJq4;!@1SANK<)-dJL+1En+ zA}@d2mFM0z(4>0~3SI{=Yl7HnGSHXE_iK~Y>({nReTQjzuU3?P`CdlY4H5cmRxK8!w;Uc zN~t%@DK55<>3VnKYt`45_=<0w53*SnJuv<==g$Wx#)3;uOQ%CD=3oeLWvKbct_BM+ zc+e5USfRl1Zv~4F%qXa5I2bq@oPnN#`;ICMa5z!LB)HQC(8z!@Z<1MrVbKrw7A1k^ pz&N|3=F||H(?D8gCb z5n0T@z%2~Ij105pNB{-dOFVsD+3&M3@ftHFb^MKEU|`Pjba4!+xb^m~tsj%4M8m^; zUh|nJ3|~Bum{P^CqirplS6_l=n6xc3oAC`Lxg=el&M1#7U)i5kT5*|AHvFAdHZykB zlptY;iL2VLwlX*@?DJuqvU>A9oij`kj0{W+91IE!4Gchr%oM*^{j*FWt2T*B#4s_a zu4Ay_W?;R~yaCKbRwxzSc#w-hV`4hUmkbXMglaB*R%O@M(a}GTXU*$WANB7Oi`OYB z-P%*R!}i&?9oIj9Jh##1$n1{{^RNGWbl>#z>cH&g7yRd>)Q$e^TmObRBkbp%tBz;Z zyFGmEaidw(!RzJO=f{`t&gWmWZhB!+mCR+&4u(IUMIBbF+izIT$iTuNz~BH1-GBSf z`OE(J+wE4hciqjlASQv2n?lW%lCEEiJD|!?;Gx~{*4fP=k@3aXUDN(P5Q6DqVbHK* zsGG&}@7(hJY-cRP{~nAqo_+Swvu~GpoHDf=<`kRC@I}jZnEyE>w}v6keZkrCAC^B8 z`HSe?bSsj*skNkbr}SAaRTU2ZlcZoTyy@zu960?F7y8h|4p+QIwBf3=`L)@tHyaMwFdwgJ2*0MaxD=GGJzf1= J);T3K0RSW=;!FSl literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/gui/cornersCommand.png b/src/main/resources/assets/computercraft/textures/gui/cornersCommand.png new file mode 100644 index 0000000000000000000000000000000000000000..fbb1fee6cf3e83e6bf4a19be8e63027014cc012b GIT binary patch literal 992 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G$6&6|H(?D8gCb z5n0T@z%2~Ij105pNB{-dOFVsD+3z!o3R#O^y)k_m0|Rrer;B4q#jUq@ZT*-WB^n;) z^M+qIQe|ar+p_gyR92qjik%InH4OGb}hJ*^th-;88WhHl}7(6ou(BoGNR0vs9s1aQt^MAx9e&;~Z!0hD+^mQaI1 zJ(J)r8aN{t%(%8+@C-)qP!v*LtPdW3P?4Md-Hlo6Gs_Y0>NhP9^A<4xfv2mV%Q~lo FCIBL3=NbS2 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/gui/diskdrive.png b/src/main/resources/assets/computercraft/textures/gui/diskdrive.png new file mode 100644 index 0000000000000000000000000000000000000000..4227597e10befe0f71aff91a94963260d49b88dc GIT binary patch literal 2047 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5Fo{p?&#~tz_78O`%fY(0|PTd zfKP}kP~62^QA&dRf`N&DBm;)v@9e6; zXy+{Oh%9Dc;M)(vj25iHzyM-kFY)wsWxvfS$FD1Qqe(>pC?rwh8c`CQpH@5NoHtR_WXa{6G4l43^q~M-ioV|42fOlpx>Xuvc_LHz`0QIo0N36~DxCoGl+H}L_Hz%qEVu4*VCGW2W*dKUlZn^rgJ+<8IS>E?6-22q+)nXw7ZNZv&hB zE4xMSzV+Sk-%n>gUBJKN&ikKnZ^aoB8p46PS)Q9Yum1Wc+b*PmD}YhUfpx`!8y-D8 z`{IhWNyqdGA9j0Db+K}5d>dm#?!V%*=~4`~4_Fy}3pT6mxb^rJUwqXhwG6ogI5a4A zZ4=xixk>U@?}5DC2d_S}zh1NKJJWh)iSm}P%dMGgKr1$E=UVgam~^LP=iYBBS_x_y zNKnGf4wtXbB~W0YX^)u)Cb$4+#gufYSGx+6=| zpY|U=|M^AbpFh$Cc7nE5VLx*I{QU59LaZR;h0ygi+ax9&-=eL=R&rH)zAoDn!?#@> zjIm!&rFSz{`s`LpatPo1>1L9H+~sv062njV4qN7b46nX?5B+FSCJM}f44$rjF6*2U FngCZ1rvd-~ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/gui/printer.png b/src/main/resources/assets/computercraft/textures/gui/printer.png new file mode 100644 index 0000000000000000000000000000000000000000..7e149088d8db8e3021272408ba8d9e5b95af4129 GIT binary patch literal 1267 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 A0{{R3 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/gui/termBackground.png b/src/main/resources/assets/computercraft/textures/gui/termBackground.png new file mode 100644 index 0000000000000000000000000000000000000000..694d2b25b96a186fffedf045db42cc4fd488de4b GIT binary patch literal 123 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#J`WQ=AD@v@S_)7|%G1R$MB{w&pa1{unKc_a8(j=mC59ZnaFKx_G?!U+zMkkJ PpehDWS3j3^P6 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 R6#P8v>U`R%#xdy5{{VFdcK`qY literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/gui/turtle.png b/src/main/resources/assets/computercraft/textures/gui/turtle.png new file mode 100644 index 0000000000000000000000000000000000000000..a1ec5288bee2b6dbc5a30fedb458a587dc80c635 GIT binary patch literal 2526 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 M4sQ09$57Y*04hAq0{{R3 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/items/book.png b/src/main/resources/assets/computercraft/textures/items/book.png new file mode 100644 index 0000000000000000000000000000000000000000..459892daa6d7fbba22b27a4b10360e8c2e2342a4 GIT binary patch literal 241 zcmVraX>F8)Fs2C!Wn`}VA1QZ$0lei~3tb06RD@I6II)sqF?;U?tb@#H? zuFNIyGrqR;?en~Z;CrYgMF}T5=hhH{2)f3IAS*dmMJVBPO0rFGf(?YZF(=VOy5ZTiURL_Q38k{0!9P?j}l#-5`qY>C(l7k;zT18_a;W*%Dr9jJrB)78&qol`;+01A#7W&i*H literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/items/diskFrame.png b/src/main/resources/assets/computercraft/textures/items/diskFrame.png new file mode 100644 index 0000000000000000000000000000000000000000..951b8b1f1a3f52747eececa7a2eeb0b7c82b8856 GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`(Vi}jAr-fh6Be*dc>MSW|DlT) zFIE&rL`X!)hA}&oI65Az&yh%D?C4!HFNfKHNAeGwLh>HA2~x!pbHdlh{Z(gsZ2I6p vBXfnJBXe6L_X#tG7EVj~w!~K}CrxIwx!AvW(JSW?pfwDhu6{1-oD!M<58g5( literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/items/page.png b/src/main/resources/assets/computercraft/textures/items/page.png new file mode 100644 index 0000000000000000000000000000000000000000..4b83e573b6674c9d0fb60291dff96f805eda0924 GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`sh%#5Ar-gIPPoX~V8G+DJ89Z^ zfk-FIjYVxHZ9f(^F5dEGubk}T@5yP>pSbco)t0PccrC=Ar0c2lVb2`zP2$R&&jmU< z?0s4}B%WjiPCT>Be1iI<4|c7Qhw3-2`JbP0 Hl+XkK9BVoM literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/items/pageBundle.png b/src/main/resources/assets/computercraft/textures/items/pageBundle.png new file mode 100644 index 0000000000000000000000000000000000000000..5ccfb9e660be3d4f53890178d4b6c78c15b5e1d0 GIT binary patch literal 206 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Q$1ZALn>}_y!Y ziN6IF?FCH#bvW%h!@9SIRB)J;t1R^TTN~un`iawS5<{1v&<_2RmgNd}qlIcrj)_bX z2_GkPYD13 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/items/pocketComputer.png b/src/main/resources/assets/computercraft/textures/items/pocketComputer.png new file mode 100644 index 0000000000000000000000000000000000000000..ddff06ab89683df3df221d63415ec96f8188370b GIT binary patch literal 216 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE({w%aE)B=GoT1(fk$L9 z0|U1(2s1Lwnj--eWH0gbb!ETDC@#Qb_?5XEak-aXL9+fq=mw2`w$H|DG2s zo}ZI-V*>)Ql!GTucq}r}kKZSAF3oXzj77d&+}V$wo*Ff3UWXH|Fl0$5BqccoFz=G; zDKV(LWpb-x;f@_MfLOwLPHO~nRdsdd`FN BLeBsI literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/items/pocketComputerAdvanced.png b/src/main/resources/assets/computercraft/textures/items/pocketComputerAdvanced.png new file mode 100644 index 0000000000000000000000000000000000000000..b1e4c5a7f5e4c61faa1d7fd51b8706a66e9980f7 GIT binary patch literal 219 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPqqqqRKp1IdES)fpcr;B5V#p&dP1p)?#B($`&{(D}m zcz#aSjSUFIQV#lN=XP9rBVNODF3oZJmk+mk!$0@suG6Sd^E#Yxg&|8?K}F9wfO(fx zPf5Y69Hrbn3CWwA4jxNmZL{Fs$R=Yc)EGL4^{&`1W(I#w!50@wm;V6T$>8bg=d#Wz Gp$Pzv;Y9QR literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/items/pocketComputerBlink.png b/src/main/resources/assets/computercraft/textures/items/pocketComputerBlink.png new file mode 100644 index 0000000000000000000000000000000000000000..b285d5ee4efe2239045ab30553bb34f0ace1162e GIT binary patch literal 264 zcmeAS@N?(olHy`uVBq!ia0vp^0zj<5!3HFyJAa%3Qfx`y?k)_qAlNl0vl%GDS>O>_ z%)r1c48n{Iv*t(u1=&kHeO=k_F^Y@n={ng;e*y|k^>lFz@i?BGut31zkc5_&)_>27 z70=Jfy0HO)Sjxc@Cp;FJ=*RDqIhW=*J;owmF7E6{Pfv{+wVWIHov9LJz4Tt=E x{amBV2bwQ_YLI)%cvDYe#v7X`Ii9OPXZ5u>O?Vrl5&?7|gQu&X%Q~loCII>sPn-Y% literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/items/pocketComputerBlink.png.mcmeta b/src/main/resources/assets/computercraft/textures/items/pocketComputerBlink.png.mcmeta new file mode 100644 index 0000000000..536517bf5b --- /dev/null +++ b/src/main/resources/assets/computercraft/textures/items/pocketComputerBlink.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "frametime": 8, + "frames": [ 0, 1 ] + } +} diff --git a/src/main/resources/assets/computercraft/textures/items/pocketComputerBlinkAdvanced.png b/src/main/resources/assets/computercraft/textures/items/pocketComputerBlinkAdvanced.png new file mode 100644 index 0000000000000000000000000000000000000000..f957c234a0983fdb86ffcf28dbb6625db0a96ed1 GIT binary patch literal 266 zcmeAS@N?(olHy`uVBq!ia0vp^0zj<5!3HFyJAa%3Qfx`y?k)_qAlNl0vl%GDS>O>_ z%)r1c48n{Iv*t(u1=&kHeO=k_F^Y@nYiRr2vjGZC_jGX#@i?BGut31zkc5_&)_>27 z70=Jfy0HO)Sjs`)?A(q^Z^Ua@&ZRj{|MKBhZ}{iF+;ti?YB^nUc9l+B!Z%1M=qo#K zQM8B!(#+|PjeA(9b8pz#S;nZ@u#1hO^R&Q~hIMSpJbrV1m-LF~nfSP1N(qZWbkzLb6Mw<&;$Sr CY*YaN literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/computercraft/textures/items/pocketComputerBlinkAdvanced.png.mcmeta b/src/main/resources/assets/computercraft/textures/items/pocketComputerBlinkAdvanced.png.mcmeta new file mode 100644 index 0000000000..536517bf5b --- /dev/null +++ b/src/main/resources/assets/computercraft/textures/items/pocketComputerBlinkAdvanced.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "frametime": 8, + "frames": [ 0, 1 ] + } +} diff --git a/src/main/resources/assets/computercraft/textures/items/pocketComputerModemLight.png b/src/main/resources/assets/computercraft/textures/items/pocketComputerModemLight.png new file mode 100644 index 0000000000000000000000000000000000000000..42238aafdb77b6e8d5c6093cfad78564b3ede5a0 GIT binary patch literal 242 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP~4;QZz_g+udBS4{gPZ!4!i_^&o3j_=fNoZ+lsbuac ze$K}X0^FMtQc_d`XHD0S=S$zbz*}#QIsf`+KbEM7*a@4t^3S(Xyrmt%J7M}n#ajY% z^nmojGpr(&jUo=Q%sxIo99a(G%@g_5{AasK>lgg`{r~xw@BjPt&N;1Nylj(lxU(NUJvD07a=PT~DxJ23Z;(>ZS9ac_ zXb}sdXL4(NV$y8b#WrKc41p^R>)4cKedd|7@bjF@bc&YYq4A#obC#>tbY3 X%aJR-<2LCV&>;+-u6{1-oD!MXaGBLEsh*O8S2;?#dlHg2Hyu2d#@c4Vy^&4EQm8R>4(na9 bUCa#eI#MsbDt$Z%bP9u~tDnm{r-UW|-v>;H literal 0 HcmV?d00001 diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info new file mode 100644 index 0000000000..a219b1cfdd --- /dev/null +++ b/src/main/resources/mcmod.info @@ -0,0 +1,20 @@ +[ + { + "modid" : "ComputerCraft", + "name" : "ComputerCraft", + "version" : "${version}", + "mcversion" : "${mcversion}", + "url" : "http://www.computercraft.info", + "credits" : "Created by Daniel Ratcliffe (@DanTwoHundred)", + "authors" : [ + "Daniel Ratcliffe", + "Aaron Mills" + ], + "description" : "ComputerCraft adds Computers, Programming and Robotics to Minecraft.", + "logoFile" : "pack.png", + "updateUrl" : "http://www.computercraft.info", + "parent" : "", + "screenshots": [ + ] + } +] diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta new file mode 100755 index 0000000000..af003a5825 --- /dev/null +++ b/src/main/resources/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "pack_format": 1, + "description": "ComputerCraft" + } +} diff --git a/src/main/resources/pack.png b/src/main/resources/pack.png new file mode 100644 index 0000000000000000000000000000000000000000..9fe740e2f222071935139266e606789c79684f39 GIT binary patch literal 499 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1SD0tpLGH$#^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvI6;>1s;*b3=DjSL74G){)!Z!pj3%#L`iUdT1k0gQ7S_~VrE{6o}X)oLYc9i zsh**M!Iz?iKx30UT^vI)oZrs$h4DN+ZFA-TE(9>zeLA zw`P-9+PyuVvyRC&%x%=&z!rAk(g6_*#%sIgq_Mqet$I|cB(jmZ-T`42QtT=9NT=t(?O;BRcQlz`_x8uft3&PPfw7(eGe$;4HTSzx%OOR zNTq`LJ;Ob}8(3J*IPc}tX)t`wuvt(^eHpXRg>QRher#f#p?l=CZ04oy5K8a-UUPfN7>c`hJ@O+{g~*e<4W1=f@6Oi#Y$vEb}T znJUu}l2I&a^?{Oxb`e0Lh;#f@*2#C51DM9h8L`MRj#f5eXcMQ60{%rMk8 nFOln>J-LB#=@e%9UoSXM3Dz~u?@o*a#tDO`tDnm{r-UW|GHb;% literal 0 HcmV?d00001