From 541c11b8b83576876eae8db1be139cbc4d30a20b Mon Sep 17 00:00:00 2001 From: Coded Date: Mon, 23 Aug 2021 22:56:22 +0100 Subject: [PATCH 1/3] Allow custom basic blocks to be registered --- .../fabric/mixin/impl/MixinBlock.java | 19 ------- .../fabric/api/PolyglotStateProperty.kt | 12 ++++- .../api/SandboxResourcePolyglotContext.kt | 2 +- .../fabric/api/block/PolyBlock.kt | 8 --- .../fabric/api/block/PolyglotBlock.kt | 23 ++++++++ .../fabric/api/block/PolyglotBlockManager.kt | 13 +++++ .../api/block/PolyglotGlobalBlockManager.kt | 54 +++++++++++++++++++ .../fabric/loading/SandboxLoader.kt | 4 ++ .../fabric/scripting/PolyglotScriptLoader.kt | 12 ++++- .../org/sandboxpowered/fabric/util/map.kt | 6 +++ .../sandboxpowered/fabric/util/polyglot.kt | 15 +++++- src/main/resources/sandbox.mixins.json | 5 +- 12 files changed, 137 insertions(+), 36 deletions(-) delete mode 100644 src/main/java/org/sandboxpowered/fabric/mixin/impl/MixinBlock.java delete mode 100644 src/main/kotlin/org/sandboxpowered/fabric/api/block/PolyBlock.kt create mode 100644 src/main/kotlin/org/sandboxpowered/fabric/api/block/PolyglotBlock.kt create mode 100644 src/main/kotlin/org/sandboxpowered/fabric/api/block/PolyglotBlockManager.kt create mode 100644 src/main/kotlin/org/sandboxpowered/fabric/api/block/PolyglotGlobalBlockManager.kt diff --git a/src/main/java/org/sandboxpowered/fabric/mixin/impl/MixinBlock.java b/src/main/java/org/sandboxpowered/fabric/mixin/impl/MixinBlock.java deleted file mode 100644 index 2321476..0000000 --- a/src/main/java/org/sandboxpowered/fabric/mixin/impl/MixinBlock.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.sandboxpowered.fabric.mixin.impl; - -import net.minecraft.block.Block; -import net.minecraft.util.registry.Registry; -import org.jetbrains.annotations.NotNull; -import org.sandboxpowered.fabric.api.block.PolyBlock; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(Block.class) -@Implements(@Interface(iface = PolyBlock.class, prefix = "sbx$", unique = true)) -public class MixinBlock { - - @NotNull - public String sbx$id() { - return Registry.BLOCK.getId((Block) (Object) this).toString(); - } -} diff --git a/src/main/kotlin/org/sandboxpowered/fabric/api/PolyglotStateProperty.kt b/src/main/kotlin/org/sandboxpowered/fabric/api/PolyglotStateProperty.kt index 7eb3389..184f753 100644 --- a/src/main/kotlin/org/sandboxpowered/fabric/api/PolyglotStateProperty.kt +++ b/src/main/kotlin/org/sandboxpowered/fabric/api/PolyglotStateProperty.kt @@ -4,7 +4,7 @@ import net.minecraft.state.property.* import org.graalvm.polyglot.HostAccess.Export class PolyglotStateProperty private constructor( - private val property: Property<*>?, + val property: Property<*>?, @JvmField @Export val name: String, @JvmField @Export val type: String, @JvmField @Export val values: Array<*> @@ -27,12 +27,20 @@ class PolyglotStateProperty private constructor( ) fun from(name: String, type: String, extra: Array<*> = emptyArray()) = PolyglotStateProperty( - property = null, + property = test(name, type, extra), name = name, type = type, values = extra ) + private fun test(name: String, type: String, extra: Array<*> = emptyArray()): Property<*>? { + return when (type) { + INT -> IntProperty.of(name, extra.first() as Int, extra.last() as Int) + BOOLEAN -> BooleanProperty.of(name) + else -> null + } + } + const val BOOLEAN = "boolean" const val INT = "int" const val DIRECTION = "direction" diff --git a/src/main/kotlin/org/sandboxpowered/fabric/api/SandboxResourcePolyglotContext.kt b/src/main/kotlin/org/sandboxpowered/fabric/api/SandboxResourcePolyglotContext.kt index be14f58..5efcee0 100644 --- a/src/main/kotlin/org/sandboxpowered/fabric/api/SandboxResourcePolyglotContext.kt +++ b/src/main/kotlin/org/sandboxpowered/fabric/api/SandboxResourcePolyglotContext.kt @@ -23,7 +23,7 @@ class SandboxResourcePolyglotContext(private val resource: String, private val s @Export fun emit(event: String, vararg args: Any) { if (event.contains(':')) scriptLoader.emitEventToAll(event, *args) - else scriptLoader.emitEventTo(resource, event, *args) + else scriptLoader.emitEventTo(resource, event, args = args) } @Export diff --git a/src/main/kotlin/org/sandboxpowered/fabric/api/block/PolyBlock.kt b/src/main/kotlin/org/sandboxpowered/fabric/api/block/PolyBlock.kt deleted file mode 100644 index 3e3b3fb..0000000 --- a/src/main/kotlin/org/sandboxpowered/fabric/api/block/PolyBlock.kt +++ /dev/null @@ -1,8 +0,0 @@ -package org.sandboxpowered.fabric.api.block - -import org.graalvm.polyglot.HostAccess.Export - -interface PolyBlock { - @Export - fun id(): String -} \ No newline at end of file diff --git a/src/main/kotlin/org/sandboxpowered/fabric/api/block/PolyglotBlock.kt b/src/main/kotlin/org/sandboxpowered/fabric/api/block/PolyglotBlock.kt new file mode 100644 index 0000000..f0f3df2 --- /dev/null +++ b/src/main/kotlin/org/sandboxpowered/fabric/api/block/PolyglotBlock.kt @@ -0,0 +1,23 @@ +package org.sandboxpowered.fabric.api.block + +import net.minecraft.block.Block +import net.minecraft.block.BlockState +import net.minecraft.state.StateManager +import org.graalvm.polyglot.Value +import org.sandboxpowered.fabric.api.PolyglotStateProperty + +class PolyglotBlock(settings: Settings, private val possibleStates: List?, value: Value) : Block(settings) { + override fun appendProperties(builder: StateManager.Builder) { + super.appendProperties(builder) + println(hackOverwrite) + hackOverwrite?.forEach { + if (it.property != null) { + builder.add(it.property) + } + } + } + + companion object { + var hackOverwrite: List? = null + } +} \ No newline at end of file diff --git a/src/main/kotlin/org/sandboxpowered/fabric/api/block/PolyglotBlockManager.kt b/src/main/kotlin/org/sandboxpowered/fabric/api/block/PolyglotBlockManager.kt new file mode 100644 index 0000000..66fa607 --- /dev/null +++ b/src/main/kotlin/org/sandboxpowered/fabric/api/block/PolyglotBlockManager.kt @@ -0,0 +1,13 @@ +package org.sandboxpowered.fabric.api.block + +import net.minecraft.util.Identifier +import org.graalvm.polyglot.HostAccess.Export +import org.graalvm.polyglot.Value + +class PolyglotBlockManager(private val domain: String, private val global: PolyglotGlobalBlockManager) { + @Export + fun add(id: String, value: Value) { + require(value.hasMembers()) { "Unsupported value for block registration" } + global.addBlock(Identifier(domain, id), value) + } +} \ No newline at end of file diff --git a/src/main/kotlin/org/sandboxpowered/fabric/api/block/PolyglotGlobalBlockManager.kt b/src/main/kotlin/org/sandboxpowered/fabric/api/block/PolyglotGlobalBlockManager.kt new file mode 100644 index 0000000..b751382 --- /dev/null +++ b/src/main/kotlin/org/sandboxpowered/fabric/api/block/PolyglotGlobalBlockManager.kt @@ -0,0 +1,54 @@ +package org.sandboxpowered.fabric.api.block + +import com.google.common.collect.ImmutableMap +import net.minecraft.block.AbstractBlock +import net.minecraft.block.Block +import net.minecraft.block.Material +import net.minecraft.util.Identifier +import net.minecraft.util.registry.Registry +import org.graalvm.polyglot.Value +import org.sandboxpowered.fabric.api.PolyglotStateProperty +import org.sandboxpowered.fabric.util.* + +class PolyglotGlobalBlockManager { + private val archetypeMap: Map Block> = ImmutableMap.builder Block>() + .apply { + this["block"] = { + val settings: AbstractBlock.Settings + var possibleStates: List? = null + if (!it.hasMember("properties")) settings = AbstractBlock.Settings.of(Material.AIR) + else { + val properties = it.getMember("properties") + settings = itemPropertiesToSettings(properties) + possibleStates = properties.getMemberValue("state")?.let { state -> state.asArray().map { value -> value.convert() } } + } + PolyglotBlock.hackOverwrite = possibleStates + PolyglotBlock(settings, possibleStates ?: emptyList(), it) + } + } + .build() + + private fun itemPropertiesToSettings(properties: Value): AbstractBlock.Settings { + val settings = AbstractBlock.Settings.of(materialFromString(properties.getMemberValue("material", "air"))) + properties.getMemberValueFloat("hardness")?.let(settings::hardness) + properties.getMemberValueFloat("resistance")?.let(settings::resistance) + return settings + } + + private fun materialFromString(input: String): Material { + return when (input) { + "stone" -> Material.STONE + "ice" -> Material.ICE + "soil", "dirt" -> Material.SOIL + else -> Material.AIR + } + } + + fun addBlock(id: Identifier, value: Value) { + val archetype = value.getMemberValue("archetype", "block") + require(archetype in archetypeMap) { "Unknown block archetype [$archetype]" } + val block = archetypeMap[archetype]!!(value) + Registry.register(Registry.BLOCK, id, block) + //TODO register itemblock + } +} \ No newline at end of file diff --git a/src/main/kotlin/org/sandboxpowered/fabric/loading/SandboxLoader.kt b/src/main/kotlin/org/sandboxpowered/fabric/loading/SandboxLoader.kt index 63cee70..118787b 100644 --- a/src/main/kotlin/org/sandboxpowered/fabric/loading/SandboxLoader.kt +++ b/src/main/kotlin/org/sandboxpowered/fabric/loading/SandboxLoader.kt @@ -87,6 +87,10 @@ class SandboxLoader { log.info("Loaded ${addons.size} resources") + resourceContent.keys.forEach { + polyglotLoader.emitEventTo(it, "blocks", false, polyglotLoader.getBlockManager(it)) + } + if (side == Side.SERVER) { val json = JsonObject() diff --git a/src/main/kotlin/org/sandboxpowered/fabric/scripting/PolyglotScriptLoader.kt b/src/main/kotlin/org/sandboxpowered/fabric/scripting/PolyglotScriptLoader.kt index 8baf261..f962554 100644 --- a/src/main/kotlin/org/sandboxpowered/fabric/scripting/PolyglotScriptLoader.kt +++ b/src/main/kotlin/org/sandboxpowered/fabric/scripting/PolyglotScriptLoader.kt @@ -4,6 +4,8 @@ import org.graalvm.polyglot.Context import org.graalvm.polyglot.HostAccess import org.graalvm.polyglot.Source import org.sandboxpowered.fabric.api.SandboxResourcePolyglotContext +import org.sandboxpowered.fabric.api.block.PolyglotBlockManager +import org.sandboxpowered.fabric.api.block.PolyglotGlobalBlockManager import org.sandboxpowered.fabric.scripting.polyglot.PolyglotFileSystem import org.sandboxpowered.fabric.util.TimingUtil import java.util.concurrent.Executors @@ -12,6 +14,8 @@ class PolyglotScriptLoader { private val executor = Executors.newSingleThreadExecutor() private val scriptContext: MutableMap> = HashMap() private val polyglotContext: MutableMap = HashMap() + private val globalBlockManager = PolyglotGlobalBlockManager() + private val blockManagers: MutableMap = hashMapOf() private fun buildContext(): Context = Context.newBuilder("js", "python") .allowExperimentalOptions(true) @@ -33,9 +37,10 @@ class PolyglotScriptLoader { } } - fun emitEventTo(resource: String, event: String, vararg args: Any) { + fun emitEventTo(resource: String, event: String, emitToAll: Boolean = true, vararg args: Any) { polyglotContext[resource]?.event(event) { it(args) } - emitEventToAll(resource, "$resource:$event", *args) + if (emitToAll) + emitEventToAll(resource, "$resource:$event", *args) } fun loadScriptContext(resource: String, scriptSource: Source) { @@ -69,6 +74,9 @@ class PolyglotScriptLoader { fun markEventAsNetCapable(string: String) { } + + fun getBlockManager(it: String): PolyglotBlockManager = + blockManagers.computeIfAbsent(it) { PolyglotBlockManager(it, globalBlockManager) } } private inline fun HostAccess.Builder.allowAccessAnnotatedBy(): HostAccess.Builder { diff --git a/src/main/kotlin/org/sandboxpowered/fabric/util/map.kt b/src/main/kotlin/org/sandboxpowered/fabric/util/map.kt index 68b0dd1..35cde5a 100644 --- a/src/main/kotlin/org/sandboxpowered/fabric/util/map.kt +++ b/src/main/kotlin/org/sandboxpowered/fabric/util/map.kt @@ -1,5 +1,7 @@ package org.sandboxpowered.fabric.util +import com.google.common.collect.ImmutableMap + /** * Removes elements from this map if the predicate returns true */ @@ -9,4 +11,8 @@ inline fun MutableMap.removeIf(predicate: (K, V) -> Boolean) { val (k, v) = iter.next() if (predicate(k, v)) iter.remove() } +} + +operator fun ImmutableMap.Builder.set(key: K, value: V): ImmutableMap.Builder { + return put(key, value) } \ No newline at end of file diff --git a/src/main/kotlin/org/sandboxpowered/fabric/util/polyglot.kt b/src/main/kotlin/org/sandboxpowered/fabric/util/polyglot.kt index a2ba339..9929816 100644 --- a/src/main/kotlin/org/sandboxpowered/fabric/util/polyglot.kt +++ b/src/main/kotlin/org/sandboxpowered/fabric/util/polyglot.kt @@ -8,9 +8,11 @@ fun Value.getMemberValue(member: String): Value? = if (hasMember(member)) getMem fun Value.getMemberValueStr(member: String): String? = getMemberValue(member)?.asString() fun Value.getMemberValueInt(member: String): Int? = getMemberValue(member)?.asInt() +fun Value.getMemberValueFloat(member: String): Float? = getMemberValue(member)?.asFloat() fun Value.getMemberValue(member: String, default: String): String = getMemberValueStr(member) ?: default fun Value.getMemberValue(member: String, default: Int): Int = getMemberValueInt(member) ?: default +fun Value.getMemberValue(member: String, default: Float): Float = getMemberValueFloat(member) ?: default fun Value.toJSON(): JsonElement = when { hasArrayElements() -> JsonArray().apply { @@ -25,4 +27,15 @@ fun Value.toJSON(): JsonElement = when { isBoolean -> JsonPrimitive(asBoolean()) isNumber -> JsonPrimitive(asInt()) else -> JsonNull.INSTANCE -} \ No newline at end of file +} + +inline fun Value.convert(): T { + return `as`(T::class.java) +} + +fun Value.asArray(): Array { + if (hasArrayElements()) { + return (0 until this.arraySize).map { getArrayElement(it) }.toTypedArray() + } + return emptyArray() +} diff --git a/src/main/resources/sandbox.mixins.json b/src/main/resources/sandbox.mixins.json index bdeac57..e802900 100644 --- a/src/main/resources/sandbox.mixins.json +++ b/src/main/resources/sandbox.mixins.json @@ -5,13 +5,12 @@ "compatibilityLevel": "JAVA_16", "mixins": [ "MixinBootstrap", - "MixinMinecraftClient", "MixinMinecraftServer", "MixinRecipeManager", - "MixinServerResourceManager", - "impl.MixinBlock" + "MixinServerResourceManager" ], "client": [ + "MixinMinecraftClient", "MixinClientBrandRetriever" ], "injectors": { From ae1518beb6282f8e8b9e5f3c1ed1693f142eeabe Mon Sep 17 00:00:00 2001 From: Coded Date: Mon, 23 Aug 2021 22:57:57 +0100 Subject: [PATCH 2/3] Remove debug println --- .../kotlin/org/sandboxpowered/fabric/api/block/PolyglotBlock.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/kotlin/org/sandboxpowered/fabric/api/block/PolyglotBlock.kt b/src/main/kotlin/org/sandboxpowered/fabric/api/block/PolyglotBlock.kt index f0f3df2..60a2b54 100644 --- a/src/main/kotlin/org/sandboxpowered/fabric/api/block/PolyglotBlock.kt +++ b/src/main/kotlin/org/sandboxpowered/fabric/api/block/PolyglotBlock.kt @@ -9,7 +9,6 @@ import org.sandboxpowered.fabric.api.PolyglotStateProperty class PolyglotBlock(settings: Settings, private val possibleStates: List?, value: Value) : Block(settings) { override fun appendProperties(builder: StateManager.Builder) { super.appendProperties(builder) - println(hackOverwrite) hackOverwrite?.forEach { if (it.property != null) { builder.add(it.property) From 2d8e5a2bbfa7b968e734f8dff740289800fa455e Mon Sep 17 00:00:00 2001 From: Coded Date: Mon, 23 Aug 2021 22:59:19 +0100 Subject: [PATCH 3/3] Rename property creation method --- .../org/sandboxpowered/fabric/api/PolyglotStateProperty.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/org/sandboxpowered/fabric/api/PolyglotStateProperty.kt b/src/main/kotlin/org/sandboxpowered/fabric/api/PolyglotStateProperty.kt index 184f753..995869e 100644 --- a/src/main/kotlin/org/sandboxpowered/fabric/api/PolyglotStateProperty.kt +++ b/src/main/kotlin/org/sandboxpowered/fabric/api/PolyglotStateProperty.kt @@ -27,13 +27,13 @@ class PolyglotStateProperty private constructor( ) fun from(name: String, type: String, extra: Array<*> = emptyArray()) = PolyglotStateProperty( - property = test(name, type, extra), + property = createVanillaProperty(name, type, extra), name = name, type = type, values = extra ) - private fun test(name: String, type: String, extra: Array<*> = emptyArray()): Property<*>? { + private fun createVanillaProperty(name: String, type: String, extra: Array<*> = emptyArray()): Property<*>? { return when (type) { INT -> IntProperty.of(name, extra.first() as Int, extra.last() as Int) BOOLEAN -> BooleanProperty.of(name)