Security / Android compat / Functional extension

This commit is contained in:
Anuken
2019-12-06 21:57:47 -05:00
parent c85847567d
commit 2b49c300f8
15 changed files with 106 additions and 58 deletions

View File

@@ -28,6 +28,7 @@ dependencies{
implementation project(":core") implementation project(":core")
implementation arcModule("backends:backend-android") implementation arcModule("backends:backend-android")
implementation 'com.faendir.rhino:rhino-android:1.5.2'
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi" natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi"
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a" natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a"
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-arm64-v8a" natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-arm64-v8a"

View File

@@ -9,10 +9,11 @@ import android.os.Build.*;
import android.os.*; import android.os.*;
import android.provider.Settings.*; import android.provider.Settings.*;
import android.telephony.*; import android.telephony.*;
import com.faendir.rhino_android.*;
import io.anuke.arc.*; import io.anuke.arc.*;
import io.anuke.arc.backends.android.surfaceview.*; import io.anuke.arc.backends.android.surfaceview.*;
import io.anuke.arc.files.*; import io.anuke.arc.files.*;
import io.anuke.arc.func.Cons; import io.anuke.arc.func.*;
import io.anuke.arc.scene.ui.layout.*; import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*; import io.anuke.arc.util.*;
import io.anuke.arc.util.serialization.*; import io.anuke.arc.util.serialization.*;
@@ -65,6 +66,11 @@ public class AndroidLauncher extends AndroidApplication{
} }
} }
@Override
public org.mozilla.javascript.Context getScriptContext(){
return new RhinoAndroidHelper(Core.files.local("script-output").file()).enterContext();
}
@Override @Override
public void shareFile(FileHandle file){ public void shareFile(FileHandle file){
} }

View File

@@ -254,6 +254,7 @@ project(":core"){
compileJava.dependsOn(preGen) compileJava.dependsOn(preGen)
compile "org.lz4:lz4-java:1.4.1" compile "org.lz4:lz4-java:1.4.1"
compile "org.javadelight:delight-rhino-sandbox:0.0.10"
compile arcModule("arc-core") compile arcModule("arc-core")
compile arcModule("extensions:freetype") compile arcModule("extensions:freetype")
compile arcModule("extensions:arcnet") compile arcModule("extensions:arcnet")

View File

@@ -26,6 +26,7 @@ load.image = Images
load.content = Content load.content = Content
load.system = System load.system = System
load.mod = Mods load.mod = Mods
load.scripts = Scripts
schematic = Schematic schematic = Schematic
schematic.add = Save Schematic... schematic.add = Save Schematic...

View File

@@ -2,6 +2,6 @@ const print = function(obj){
java.lang.System.out.println(obj ? String(obj) : "null") java.lang.System.out.println(obj ? String(obj) : "null")
} }
const extend = function(classType, params){ const extend = function(classType, name, params){
return new JavaAdapter(classType, params) return new JavaAdapter(classType, params, name)
} }

View File

@@ -4,9 +4,10 @@ const print = function(obj){
java.lang.System.out.println(obj ? String(obj) : "null") java.lang.System.out.println(obj ? String(obj) : "null")
} }
const extend = function(classType, params){ const extend = function(classType, name, params){
return new JavaAdapter(classType, params) return new JavaAdapter(classType, params, name)
} }
const Core = Packages.io.anuke.arc.Core const Core = Packages.io.anuke.arc.Core
const Boolc = Packages.io.anuke.arc.func.Boolc const Boolc = Packages.io.anuke.arc.func.Boolc
const Boolf = Packages.io.anuke.arc.func.Boolf const Boolf = Packages.io.anuke.arc.func.Boolf
@@ -387,7 +388,5 @@ const LiquidModule = Packages.io.anuke.mindustry.world.modules.LiquidModule
const PowerModule = Packages.io.anuke.mindustry.world.modules.PowerModule const PowerModule = Packages.io.anuke.mindustry.world.modules.PowerModule
const Produce = Packages.io.anuke.mindustry.world.producers.Produce const Produce = Packages.io.anuke.mindustry.world.producers.Produce
const ProduceItem = Packages.io.anuke.mindustry.world.producers.ProduceItem const ProduceItem = Packages.io.anuke.mindustry.world.producers.ProduceItem
const PrintStream = Packages.java.io.PrintStream
var r = new JavaAdapter(Block, {}); const System = Packages.java.lang.System
print(r.update)

View File

@@ -1,9 +1,2 @@
this["$SCRIPT_NAME$"] = function(){
$CODE$
};
try{ $CODE$
this["$SCRIPT_NAME$"]();
}catch(e){
print(e)
}

View File

@@ -69,6 +69,11 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform
Musics.load(); Musics.load();
Sounds.load(); Sounds.load();
assets.loadRun("scriptinit", Scripts.class, () -> {}, () -> {
content.createContent(false);
mods.loadScripts();
});
assets.loadRun("contentcreate", Content.class, () -> { assets.loadRun("contentcreate", Content.class, () -> {
content.createContent(); content.createContent();
content.loadColors(); content.loadColors();
@@ -193,7 +198,8 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform
if(assets.getCurrentLoading() != null){ if(assets.getCurrentLoading() != null){
String name = assets.getCurrentLoading().fileName.toLowerCase(); String name = assets.getCurrentLoading().fileName.toLowerCase();
String key = name.contains("content") ? "content" : name.contains("mod") ? "mods" : name.contains("msav") || name.contains("maps") ? "map" : name.contains("ogg") || name.contains("mp3") ? "sound" : name.contains("png") ? "image" : "system"; String key = name.contains("script") ? "scripts" : name.contains("content") ? "content" : name.contains("mod") ? "mods" : name.contains("msav") ||
name.contains("maps") ? "map" : name.contains("ogg") || name.contains("mp3") ? "sound" : name.contains("png") ? "image" : "system";
font.draw(bundle.get("load." + key, ""), graphics.getWidth() / 2f, graphics.getHeight() / 2f - height / 2f - Scl.scl(10f), Align.center); font.draw(bundle.get("load." + key, ""), graphics.getWidth() / 2f, graphics.getHeight() / 2f - height / 2f - Scl.scl(10f), Align.center);
} }
} }

View File

@@ -53,35 +53,45 @@ public class ContentLoader{
/** Creates all content types. */ /** Creates all content types. */
public void createContent(){ public void createContent(){
createContent(true);
}
/** Creates all content types. */
public void createContent(boolean load){
if(loaded){ if(loaded){
Log.info("Content already loaded, skipping."); Log.info("Content already loaded, skipping.");
return; return;
} }
for(ContentType type : ContentType.values()){ if(contentMap[0] == null){
contentMap[type.ordinal()] = new Array<>(); for(ContentType type : ContentType.values()){
contentNameMap[type.ordinal()] = new ObjectMap<>(); contentMap[type.ordinal()] = new Array<>();
} contentNameMap[type.ordinal()] = new ObjectMap<>();
for(ContentList list : content){
list.load();
}
if(mods != null){
mods.loadContent();
}
//check up ID mapping, make sure it's linear
for(Array<Content> arr : contentMap){
for(int i = 0; i < arr.size; i++){
int id = arr.get(i).id;
if(id != i){
throw new IllegalArgumentException("Out-of-order IDs for content '" + arr.get(i) + "' (expected " + i + " but got " + id + ")");
}
} }
} }
loaded = true; if(load){
for(ContentList list : content){
list.load();
}
if(mods != null){
mods.loadContent();
}
//check up ID mapping, make sure it's linear
for(Array<Content> arr : contentMap){
for(int i = 0; i < arr.size; i++){
int id = arr.get(i).id;
if(id != i){
throw new IllegalArgumentException("Out-of-order IDs for content '" + arr.get(i) + "' (expected " + i + " but got " + id + ")");
}
}
}
loaded = true;
}
} }
/** Logs content statistics.*/ /** Logs content statistics.*/

View File

@@ -13,6 +13,7 @@ import io.anuke.mindustry.net.*;
import io.anuke.mindustry.net.Net.*; import io.anuke.mindustry.net.Net.*;
import io.anuke.mindustry.type.*; import io.anuke.mindustry.type.*;
import io.anuke.mindustry.ui.dialogs.*; import io.anuke.mindustry.ui.dialogs.*;
import org.mozilla.javascript.*;
import static io.anuke.mindustry.Vars.mobile; import static io.anuke.mindustry.Vars.mobile;
@@ -51,6 +52,10 @@ public interface Platform{
return new Scripts(); return new Scripts();
} }
default Context getScriptContext(){
return Context.enter();
}
/** Add a text input dialog that should show up after the field is tapped. */ /** Add a text input dialog that should show up after the field is tapped. */
default void addDialog(TextField field){ default void addDialog(TextField field){
addDialog(field, 16); addDialog(field, 16);

File diff suppressed because one or more lines are too long

View File

@@ -30,7 +30,7 @@ import static io.anuke.mindustry.Vars.*;
public class Mods implements Loadable{ public class Mods implements Loadable{
private Json json = new Json(); private Json json = new Json();
private Scripts scripts; private @Nullable Scripts scripts;
private ContentParser parser = new ContentParser(); private ContentParser parser = new ContentParser();
private ObjectMap<String, Array<FileHandle>> bundles = new ObjectMap<>(); private ObjectMap<String, Array<FileHandle>> bundles = new ObjectMap<>();
private ObjectSet<String> specialFolders = ObjectSet.with("bundles", "sprites"); private ObjectSet<String> specialFolders = ObjectSet.with("bundles", "sprites");
@@ -348,6 +348,12 @@ public class Mods implements Loadable{
Sounds.dispose(); Sounds.dispose();
Sounds.load(); Sounds.load();
Core.assets.finishLoading(); Core.assets.finishLoading();
if(scripts != null){
scripts.dispose();
scripts = null;
}
content.createContent(false);
loadScripts();
content.clear(); content.clear();
content.createContent(); content.createContent();
loadAsync(); loadAsync();
@@ -361,9 +367,8 @@ public class Mods implements Loadable{
Events.fire(new ContentReloadEvent()); Events.fire(new ContentReloadEvent());
} }
/** Creates all the content found in mod files. */ /** This must be run on the main thread! */
public void loadContent(){ public void loadScripts(){
Time.mark(); Time.mark();
for(LoadedMod mod : loaded){ for(LoadedMod mod : loaded){
@@ -390,6 +395,10 @@ public class Mods implements Loadable{
} }
Log.info("Time to initialize modded scripts: {0}", Time.elapsed()); Log.info("Time to initialize modded scripts: {0}", Time.elapsed());
}
/** Creates all the content found in mod files. */
public void loadContent(){
class LoadRun implements Comparable<LoadRun>{ class LoadRun implements Comparable<LoadRun>{
final ContentType type; final ContentType type;

View File

@@ -7,10 +7,7 @@ import io.anuke.mindustry.*;
import io.anuke.mindustry.mod.Mods.*; import io.anuke.mindustry.mod.Mods.*;
import org.mozilla.javascript.*; import org.mozilla.javascript.*;
import java.io.*; public class Scripts implements Disposable{
public class Scripts{
private static final Class[] denied = {FileHandle.class, InputStream.class, File.class, Scripts.class, Files.class, ClassAccess.class};
private final Context context; private final Context context;
private final String wrapper; private final String wrapper;
private Scriptable scope; private Scriptable scope;
@@ -18,12 +15,26 @@ public class Scripts{
public Scripts(){ public Scripts(){
Time.mark(); Time.mark();
context = Context.enter(); context = Vars.platform.getScriptContext();
if(Vars.mobile){ context.setClassShutter(type -> ClassAccess.allowedClassNames.contains(type) || type.startsWith("adapter") || type.contains("PrintStream"));
context.setOptimizationLevel(-1); context.setErrorReporter(new ErrorReporter(){
} @Override
public void warning(String message, String sourceName, int line, String lineSource, int lineOffset){
}
@Override
public void error(String message, String sourceName, int line, String lineSource, int lineOffset){
Log.info(message + "@" + sourceName + ":" + line);
}
@Override
public EvaluatorException runtimeError(String message, String sourceName, int line, String lineSource, int lineOffset){
Log.info(message + "@" + sourceName + ":" + line);
return null;
}
});
//context.setClassShutter(ClassAccess.allowedClassNames::contains);
scope = context.initStandardObjects(); scope = context.initStandardObjects();
wrapper = Core.files.internal("scripts/wrapper.js").readString(); wrapper = Core.files.internal("scripts/wrapper.js").readString();
@@ -32,10 +43,15 @@ public class Scripts{
} }
public void run(LoadedMod mod, FileHandle file){ public void run(LoadedMod mod, FileHandle file){
run(wrapper.replace("$SCRIPT_NAME$", mod.name + "_" +file.nameWithoutExtension().replace("-", "_").replace(" ", "_")).replace("$CODE$", file.readString()), file.name()); run(wrapper.replace("$SCRIPT_NAME$", mod.name + "_" + file.nameWithoutExtension().replace("-", "_").replace(" ", "_")).replace("$CODE$", file.readString()), file.name());
} }
private void run(String script, String file){ private void run(String script, String file){
context.evaluateString(scope, script, file, 1, null); context.evaluateString(scope, script, file, 1, null);
}
@Override
public void dispose(){
Context.exit();
} }
} }

View File

@@ -1,3 +1,3 @@
org.gradle.daemon=true org.gradle.daemon=true
org.gradle.jvmargs=-Xms256m -Xmx1024m org.gradle.jvmargs=-Xms256m -Xmx1024m
archash=680d8dfc055a1336c06b32d7d4429661e6c6fddd archash=7c853686fcf7fac56405919817d7f8caef00c0f2

View File

@@ -9,6 +9,7 @@ import org.reflections.*;
import org.reflections.scanners.*; import org.reflections.scanners.*;
import org.reflections.util.*; import org.reflections.util.*;
import java.io.*;
import java.util.*; import java.util.*;
public class ScriptStubGenerator{ public class ScriptStubGenerator{
@@ -17,7 +18,7 @@ public class ScriptStubGenerator{
String base = "io.anuke.mindustry"; String base = "io.anuke.mindustry";
Array<String> blacklist = Array.with("plugin", "mod", "net", "io", "tools", "gen"); Array<String> blacklist = Array.with("plugin", "mod", "net", "io", "tools", "gen");
Array<String> nameBlacklist = Array.with("ClientLauncher", "NetClient", "NetServer"); Array<String> nameBlacklist = Array.with("ClientLauncher", "NetClient", "NetServer");
Array<Class<?>> whitelist = Array.with(Draw.class, Core.class, TextureAtlas.class, TextureRegion.class, Time.class); Array<Class<?>> whitelist = Array.with(Draw.class, Core.class, TextureAtlas.class, TextureRegion.class, Time.class, System.class, PrintStream.class);
String fileTemplate = "package io.anuke.mindustry.mod;\n" + String fileTemplate = "package io.anuke.mindustry.mod;\n" +
"\n" + "\n" +