Add wasm
This commit is contained in:
parent
e0e75d0344
commit
88fad02b96
6 changed files with 136 additions and 45 deletions
91
build.gradle
91
build.gradle
|
@ -32,8 +32,50 @@ java.toolchain.languageVersion = JavaLanguageVersion.of(21)
|
||||||
//minecraft.accessTransformers.file rootProject.file('src/main/resources/META-INF/accesstransformer.cfg')
|
//minecraft.accessTransformers.file rootProject.file('src/main/resources/META-INF/accesstransformer.cfg')
|
||||||
//minecraft.accessTransformers.entry public net.minecraft.client.Minecraft textureManager # textureManager
|
//minecraft.accessTransformers.entry public net.minecraft.client.Minecraft textureManager # textureManager
|
||||||
|
|
||||||
// Default run configurations.
|
// Include resources generated by data generators.
|
||||||
// These can be tweaked, removed, or duplicated as needed.
|
sourceSets.main.resources { srcDir 'src/generated/resources' }
|
||||||
|
|
||||||
|
// Sets up a dependency configuration called 'localRuntime'.
|
||||||
|
// This configuration should be used instead of 'runtimeOnly' to declare
|
||||||
|
// a dependency that will be present for runtime testing but that is
|
||||||
|
// "optional", meaning it will not be pulled by dependents of this mod.
|
||||||
|
configurations {
|
||||||
|
runtimeClasspath.extendsFrom localRuntime
|
||||||
|
implementation.extendsFrom libraries
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// Specify the version of Minecraft to use.
|
||||||
|
// Depending on the plugin applied there are several options. We will assume you applied the userdev plugin as shown above.
|
||||||
|
// The group for userdev is net.neoforged, the module name is neoforge, and the version is the same as the neoforge version.
|
||||||
|
// You can however also use the vanilla plugin (net.neoforged.gradle.vanilla) to use a version of Minecraft without the neoforge loader.
|
||||||
|
// And its provides the option to then use net.minecraft as the group, and one of; client, server or joined as the module name, plus the game version as version.
|
||||||
|
// For all intends and purposes: You can treat this dependency as if it is a normal library you would use.
|
||||||
|
implementation "net.neoforged:neoforge:${neo_version}"
|
||||||
|
libraries 'com.dylibso.chicory:runtime:0.0.12'
|
||||||
|
// Example optional mod dependency with JEI
|
||||||
|
// The JEI API is declared for compile time use, while the full JEI artifact is used at runtime
|
||||||
|
// compileOnly "mezz.jei:jei-${mc_version}-common-api:${jei_version}"
|
||||||
|
// compileOnly "mezz.jei:jei-${mc_version}-neoforge-api:${jei_version}"
|
||||||
|
// We add the full version to localRuntime, not runtimeOnly, so that we do not publish a dependency on it
|
||||||
|
// localRuntime "mezz.jei:jei-${mc_version}-neoforge:${jei_version}"
|
||||||
|
|
||||||
|
// Example mod dependency using a mod jar from ./libs with a flat dir repository
|
||||||
|
// This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar
|
||||||
|
// The group id is ignored when searching -- in this case, it is "blank"
|
||||||
|
// implementation "blank:coolmod-${mc_version}:${coolmod_version}"
|
||||||
|
|
||||||
|
// Example mod dependency using a file as dependency
|
||||||
|
// implementation files("libs/coolmod-${mc_version}-${coolmod_version}.jar")
|
||||||
|
|
||||||
|
// Example project dependency using a sister or child project:
|
||||||
|
// implementation project(":myproject")
|
||||||
|
|
||||||
|
// For more info:
|
||||||
|
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
|
||||||
|
// http://www.gradle.org/docs/current/userguide/dependency_management.html
|
||||||
|
}
|
||||||
|
|
||||||
runs {
|
runs {
|
||||||
// applies to all the run configs below
|
// applies to all the run configs below
|
||||||
configureEach {
|
configureEach {
|
||||||
|
@ -50,6 +92,9 @@ runs {
|
||||||
systemProperty 'forge.logging.console.level', 'debug'
|
systemProperty 'forge.logging.console.level', 'debug'
|
||||||
|
|
||||||
modSource project.sourceSets.main
|
modSource project.sourceSets.main
|
||||||
|
dependencies {
|
||||||
|
runtime project.configurations.libraries
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
client {
|
client {
|
||||||
|
@ -77,49 +122,7 @@ runs {
|
||||||
programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(),
|
programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(),
|
||||||
'--existing', file('src/main/resources/').getAbsolutePath()
|
'--existing', file('src/main/resources/').getAbsolutePath()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Include resources generated by data generators.
|
|
||||||
sourceSets.main.resources { srcDir 'src/generated/resources' }
|
|
||||||
|
|
||||||
// Sets up a dependency configuration called 'localRuntime'.
|
|
||||||
// This configuration should be used instead of 'runtimeOnly' to declare
|
|
||||||
// a dependency that will be present for runtime testing but that is
|
|
||||||
// "optional", meaning it will not be pulled by dependents of this mod.
|
|
||||||
configurations {
|
|
||||||
runtimeClasspath.extendsFrom localRuntime
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
// Specify the version of Minecraft to use.
|
|
||||||
// Depending on the plugin applied there are several options. We will assume you applied the userdev plugin as shown above.
|
|
||||||
// The group for userdev is net.neoforged, the module name is neoforge, and the version is the same as the neoforge version.
|
|
||||||
// You can however also use the vanilla plugin (net.neoforged.gradle.vanilla) to use a version of Minecraft without the neoforge loader.
|
|
||||||
// And its provides the option to then use net.minecraft as the group, and one of; client, server or joined as the module name, plus the game version as version.
|
|
||||||
// For all intends and purposes: You can treat this dependency as if it is a normal library you would use.
|
|
||||||
implementation "net.neoforged:neoforge:${neo_version}"
|
|
||||||
implementation 'com.dylibso.chicory:runtime:0.0.12'
|
|
||||||
// Example optional mod dependency with JEI
|
|
||||||
// The JEI API is declared for compile time use, while the full JEI artifact is used at runtime
|
|
||||||
// compileOnly "mezz.jei:jei-${mc_version}-common-api:${jei_version}"
|
|
||||||
// compileOnly "mezz.jei:jei-${mc_version}-neoforge-api:${jei_version}"
|
|
||||||
// We add the full version to localRuntime, not runtimeOnly, so that we do not publish a dependency on it
|
|
||||||
// localRuntime "mezz.jei:jei-${mc_version}-neoforge:${jei_version}"
|
|
||||||
|
|
||||||
// Example mod dependency using a mod jar from ./libs with a flat dir repository
|
|
||||||
// This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar
|
|
||||||
// The group id is ignored when searching -- in this case, it is "blank"
|
|
||||||
// implementation "blank:coolmod-${mc_version}:${coolmod_version}"
|
|
||||||
|
|
||||||
// Example mod dependency using a file as dependency
|
|
||||||
// implementation files("libs/coolmod-${mc_version}-${coolmod_version}.jar")
|
|
||||||
|
|
||||||
// Example project dependency using a sister or child project:
|
|
||||||
// implementation project(":myproject")
|
|
||||||
|
|
||||||
// For more info:
|
|
||||||
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
|
|
||||||
// http://www.gradle.org/docs/current/userguide/dependency_management.html
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This block of code expands all declared replace properties in the specified resource targets.
|
// This block of code expands all declared replace properties in the specified resource targets.
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.mojang.serialization.MapCodec;
|
||||||
import dev.exhq.ajarc.Ajar;
|
import dev.exhq.ajarc.Ajar;
|
||||||
import dev.exhq.ajarc.network.ComputerScreenUpdate;
|
import dev.exhq.ajarc.network.ComputerScreenUpdate;
|
||||||
import dev.exhq.ajarc.register.Register;
|
import dev.exhq.ajarc.register.Register;
|
||||||
|
import dev.exhq.ajarc.vm.WasmVm;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.HolderLookup;
|
import net.minecraft.core.HolderLookup;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
@ -33,7 +34,7 @@ public class ComputerBlockEntity extends BlockEntity {
|
||||||
private static final MapCodec<ComputerTerminal> screenCodec = ComputerTerminal.CODEC
|
private static final MapCodec<ComputerTerminal> screenCodec = ComputerTerminal.CODEC
|
||||||
.fieldOf("screen")
|
.fieldOf("screen")
|
||||||
.setPartial(() -> ComputerTerminal.ofSize(20, 30));
|
.setPartial(() -> ComputerTerminal.ofSize(20, 30));
|
||||||
|
private WasmVm vm = new WasmVm(this);
|
||||||
private List<String> lines = new ArrayList<>();
|
private List<String> lines = new ArrayList<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -69,6 +70,10 @@ public class ComputerBlockEntity extends BlockEntity {
|
||||||
return screen;
|
return screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setTerminal(ComputerTerminal terminal) {
|
||||||
|
this.screen = terminal;
|
||||||
|
}
|
||||||
|
|
||||||
public void executeCommand(String line) {
|
public void executeCommand(String line) {
|
||||||
lines.add("$ " + line);
|
lines.add("$ " + line);
|
||||||
if (line.equals("small")) {
|
if (line.equals("small")) {
|
||||||
|
@ -77,6 +82,10 @@ public class ComputerBlockEntity extends BlockEntity {
|
||||||
} else if (line.equals("big")) {
|
} else if (line.equals("big")) {
|
||||||
screen = ComputerTerminal.ofSize(20, 30);
|
screen = ComputerTerminal.ofSize(20, 30);
|
||||||
lines.add("Made big!");
|
lines.add("Made big!");
|
||||||
|
} else if (line.equals("add")) {
|
||||||
|
int left = 42, right = 69;
|
||||||
|
int result = vm.add(left, right);
|
||||||
|
lines.add(left + " + " + right + " = " + result);
|
||||||
} else {
|
} else {
|
||||||
lines.add("Made unknown!");
|
lines.add("Made unknown!");
|
||||||
}
|
}
|
||||||
|
|
65
src/main/java/dev/exhq/ajarc/vm/WasmVm.java
Normal file
65
src/main/java/dev/exhq/ajarc/vm/WasmVm.java
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
package dev.exhq.ajarc.vm;
|
||||||
|
|
||||||
|
import com.dylibso.chicory.runtime.HostFunction;
|
||||||
|
import com.dylibso.chicory.runtime.HostImports;
|
||||||
|
import com.dylibso.chicory.runtime.Instance;
|
||||||
|
import com.dylibso.chicory.runtime.Module;
|
||||||
|
import com.dylibso.chicory.wasm.types.Value;
|
||||||
|
import com.dylibso.chicory.wasm.types.ValueType;
|
||||||
|
import dev.exhq.ajarc.Ajar;
|
||||||
|
import dev.exhq.ajarc.computer.ComputerBlockEntity;
|
||||||
|
import dev.exhq.ajarc.computer.ComputerTerminal;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class WasmVm {
|
||||||
|
|
||||||
|
private final Instance instance;
|
||||||
|
|
||||||
|
public WasmVm(ComputerBlockEntity entity) {
|
||||||
|
try {
|
||||||
|
var setSize = new HostFunction(
|
||||||
|
(instance1, args) -> {
|
||||||
|
int rows = args[0].asInt();
|
||||||
|
int cols = args[1].asInt();
|
||||||
|
entity.setTerminal(ComputerTerminal.ofSize(rows, cols));
|
||||||
|
return new Value[0];
|
||||||
|
},
|
||||||
|
"env",
|
||||||
|
"setSize",
|
||||||
|
List.of(ValueType.I32, ValueType.I32),
|
||||||
|
List.of());
|
||||||
|
var inputStream = Minecraft.getInstance()
|
||||||
|
.getResourceManager()
|
||||||
|
.getResourceOrThrow(Ajar.identifier("test.wasm"))
|
||||||
|
.open();
|
||||||
|
var module = Module.builder(inputStream)
|
||||||
|
.withHostImports(new HostImports(
|
||||||
|
new HostFunction[]{
|
||||||
|
setSize
|
||||||
|
}
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
this.instance = module.instantiate();
|
||||||
|
} catch (IOException e) {
|
||||||
|
Ajar.LOGGER.error("Could not load wasm module", e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int add(int left, int right) {
|
||||||
|
var export = instance.export("add");
|
||||||
|
var timer = System.nanoTime();
|
||||||
|
for (int i = 0; i < 10000; i++) {
|
||||||
|
export.apply(Value.i32(left), Value.i32(right));
|
||||||
|
}
|
||||||
|
System.out.println("Took " + ((System.nanoTime() - timer) / 1_000_000) + "ms to add 1000*2 numbers");
|
||||||
|
var result = export.apply(Value.i32(left), Value.i32(right));
|
||||||
|
assert result.length == 1;
|
||||||
|
return result[0].asInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
BIN
src/main/resources/assets/ajarc/test.wasm
Normal file
BIN
src/main/resources/assets/ajarc/test.wasm
Normal file
Binary file not shown.
BIN
test.wasm
Normal file
BIN
test.wasm
Normal file
Binary file not shown.
14
test.wat
Normal file
14
test.wat
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
(module
|
||||||
|
(import "computer" "setSize" (func $setSize (param $rows i32) (param $cols i32)))
|
||||||
|
(func $add (param $left i32) (param $right i32) (result i32)
|
||||||
|
i32.const 10
|
||||||
|
i32.const 12
|
||||||
|
call $setSize
|
||||||
|
local.get $left
|
||||||
|
local.get $right
|
||||||
|
i32.add
|
||||||
|
i32.const 10
|
||||||
|
i32.add
|
||||||
|
)
|
||||||
|
(export "add" (func $add))
|
||||||
|
)
|
Loading…
Reference in a new issue