初始状态0吧 关注:289贴子:4,873

【Rhino】给那些还想做modpe编辑器的人一点帮助

只看楼主收藏回复

Rhino是mozilla的开源项目,用Java语言编写,并支持在android中使用。本帖教大家如何下载、使用、适配性修改Rhino引擎。


IP属地:上海来自Android客户端1楼2018-08-30 14:06回复
    【获取Rhino源码和二进制文件】
    可到www.mozilla.org/rhino进行下载,也可在github上clone:github.com/mozilla/rhino
    如果要在aide中使用,建议不要从github上下载,因为会报错,而且你也不会改


    IP属地:上海来自Android客户端2楼2018-08-30 14:09
    回复
      如果你从mozilla网站上下载,解压后应该会有这些文件。这里面docs是文档,lib是jar包(js.jar),src是源码。
      这里的源码可以复制到aide里用,不过因为android中没有awt,org.mozilla.javascript.tools包里的一些类会报错。不过,我们可以直接把这个包删掉,这不会影响rhino的运行。


      IP属地:上海来自Android客户端3楼2018-08-30 14:15
      回复
        【基本用法】
        首先,我们需要保证当前线程有Context。
        这个Context是rhino里的Context(org.mozilla.javascript.Context),不是android里的Context(android.content.Context)。创建Context的方法如下:
        Context context = Context.enter();
        调用Context类的静态方法enter(),会在当前线程创建一个Context,并返回。当然,如果当前线程已经创建了Context,那就直接返回。


        IP属地:上海来自Android客户端4楼2018-08-30 14:19
        回复
          创建Context后,我们必须为它进行配置:
          context.setOptimizationLevel(-1);
          虽然不知道它是做什么的,但是不写这句rhino就不能正常运行。


          IP属地:上海来自Android客户端5楼2018-08-30 14:21
          收起回复
            Context就到这里了,现在该创建js的实例了。在js代码中,对象外的this默认就是指向这个实例。
            ScriptableObject script = context.initStandardObjects();
            这样会创建一个标准的js对象。当然,这个js对象目前还是空的,除了标准库里定义的函数外,没有任何函数。
            需要注意的是,标准库里没有定义print函数!


            IP属地:上海来自Android客户端6楼2018-08-30 14:25
            回复
              最后一步,就是把js代码导入进去了。
              context.evaluateString(script, scriptCode, name, 1, null);
              evaluateString方法类似于js里的eval函数,只是传入的参数有点多。
              第一个script是我们刚刚创建的js对象,第二个scriptCode是js代码,第三个name是js的文件名,第四个1是起始行号,最后一个null不用管。


              IP属地:上海来自Android客户端7楼2018-08-30 14:29
              回复
                当然,如果js代码出错,你的程序是会崩溃的。这是因为evaluateString会抛出RhinoException异常。这个异常属于RuntimeException,因此可以不用捕获。
                对于modpe编辑器而言,往往会导入一些有错误的代码,所以我们应该捕获,并给出错误信息。
                try {
                ...
                } catch(RhinoException e) {
                ...
                }


                IP属地:上海来自Android客户端8楼2018-08-30 14:32
                回复
                  然后,我们把之前的
                  ScriptableObject script = context.initStandardObjects();
                  改为
                  ScriptableObject script = context.initStandardObjects(new HostFunction());
                  没错,加了参数,这个类的一个实例。
                  还没完,后面还要再写:
                  script.defineFunctionProperties(new String[] {"print"}, HostFunction.class, ScriptableObject.DONTENUM);
                  这段比较复杂,其实就是调用一个方法。
                  defineFunctionProperties方法定义无前缀函数,其中需要传递三个参数:
                  1. 方法名数组
                  2. 这个类.class
                  3. 标识
                  前两个比较好理解,第三个又是什么呢?
                  在ScriptableObject中有定义,我们可以用这几种标识(多个标识使用位或“|”运算)
                  EMPTY - 默认
                  READONLY - 只读
                  DONTENUM - 不是枚举
                  PERMANENT - 永久
                  只读:不能再次赋值更改
                  不是枚举:不能通过for或Object.keys方法得到
                  永久:不能用delete删除


                  IP属地:上海来自Android客户端10楼2018-08-30 14:58
                  回复
                    【定义有前缀函数】
                    与无前缀函数相比,有前缀的要简单的多。
                    首先我们需要定义一个新类,这次我们要继承ScriptableObject
                    实现抽象方法getClassName,返回前缀名
                    之后在里面写方法,要用public static修饰,且增加@JSStaticFunction注释
                    class JSSystem extends ScriptableObject
                    {
                    @Override
                    public String getClassName() {
                    return "System";
                    }
                    @JSStaticFunction
                    public static void exit() {
                    System.exit(0);
                    }
                    }


                    IP属地:上海来自Android客户端11楼2018-08-30 15:11
                    收起回复
                      之后,我们回到
                      ScriptableObject script = context.initStandardObjects();
                      这里,后面添加:
                      ScriptableObject.defineClass(script, JSSystem.class);
                      这样就完成了!


                      IP属地:上海来自Android客户端12楼2018-08-30 15:13
                      回复
                        来暖贴(话说初始怎么不写一个InnerCore的IDE呢


                        IP属地:北京来自Android客户端14楼2018-08-30 16:06
                        收起回复
                          【调用函数】
                          方法一:
                          直接调用
                          ScriptableObject.callMethod(script, name, params);
                          其中:
                          script是之前我们创建的ScriptableObject
                          name是函数名
                          params是参数(Object[])
                          当然,如果没有这个函数,就会报错。
                          方法二:
                          先得到这个函数,然后再调用
                          Object obj = script.get(name, script);
                          if(obj != null && obj instanceof Function) {
                          Function func = (Function) obj;
                          func.call(context, script, script, params);
                          }
                          参数就不解释了,和方法一一样
                          这个方法加了判断,即便函数不存在也不会报错


                          IP属地:上海来自Android客户端15楼2018-08-30 22:21
                          回复
                            我顶


                            IP属地:福建来自手机贴吧16楼2018-08-31 07:28
                            回复