From dc0964d14a91eddac29383f77df25a1c90fbe55b Mon Sep 17 00:00:00 2001 From: Coded Date: Sun, 22 Aug 2021 19:50:39 +0100 Subject: [PATCH 1/5] Allow basic items to be registered --- .../fabric/api/PolyglotRecipeManager.kt | 10 ++-- .../api/SandboxResourcePolyglotContext.kt | 2 +- .../api/item/PolyglotGlobalItemManager.kt | 51 +++++++++++++++++++ .../fabric/api/item/PolyglotItemManager.kt | 13 +++++ .../fabric/impl/item/PolyglotItem.kt | 8 +++ .../fabric/loading/SandboxLoader.kt | 4 ++ .../fabric/scripting/PolyglotScriptLoader.kt | 21 +++++--- .../fabric/util/PolyglotUtil.kt | 11 +++- .../org/sandboxpowered/fabric/util/map.kt | 6 +++ 9 files changed, 112 insertions(+), 14 deletions(-) create mode 100644 src/main/kotlin/org/sandboxpowered/fabric/api/item/PolyglotGlobalItemManager.kt create mode 100644 src/main/kotlin/org/sandboxpowered/fabric/api/item/PolyglotItemManager.kt create mode 100644 src/main/kotlin/org/sandboxpowered/fabric/impl/item/PolyglotItem.kt diff --git a/src/main/kotlin/org/sandboxpowered/fabric/api/PolyglotRecipeManager.kt b/src/main/kotlin/org/sandboxpowered/fabric/api/PolyglotRecipeManager.kt index 0dc5ddb..26aac69 100644 --- a/src/main/kotlin/org/sandboxpowered/fabric/api/PolyglotRecipeManager.kt +++ b/src/main/kotlin/org/sandboxpowered/fabric/api/PolyglotRecipeManager.kt @@ -8,7 +8,7 @@ import net.minecraft.util.registry.Registry import org.graalvm.polyglot.HostAccess.Export import org.graalvm.polyglot.Value import org.sandboxpowered.fabric.Main -import org.sandboxpowered.fabric.util.getMemberValue +import org.sandboxpowered.fabric.util.getMemberValueStr import org.sandboxpowered.fabric.util.removeIf import org.sandboxpowered.fabric.util.toJSON import java.util.function.BiPredicate @@ -55,10 +55,10 @@ class PolyglotRecipeManager(private val map: MutableMap var predicate: BiPredicate? = null - val id = value.getMemberValue("id") - val output = value.getMemberValue("output") - val domain = value.getMemberValue("domain") - val type = value.getMemberValue("type") + val id = value.getMemberValueStr("id") + val output = value.getMemberValueStr("output") + val domain = value.getMemberValueStr("domain") + val type = value.getMemberValueStr("type") if (id != null) { val idPredicate = BiPredicate { identifier, _ -> identifier.toString() == id } diff --git a/src/main/kotlin/org/sandboxpowered/fabric/api/SandboxResourcePolyglotContext.kt b/src/main/kotlin/org/sandboxpowered/fabric/api/SandboxResourcePolyglotContext.kt index 98b7977..4029f94 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/item/PolyglotGlobalItemManager.kt b/src/main/kotlin/org/sandboxpowered/fabric/api/item/PolyglotGlobalItemManager.kt new file mode 100644 index 0000000..dcb48ef --- /dev/null +++ b/src/main/kotlin/org/sandboxpowered/fabric/api/item/PolyglotGlobalItemManager.kt @@ -0,0 +1,51 @@ +package org.sandboxpowered.fabric.api.item + +import com.google.common.collect.ImmutableMap +import net.minecraft.item.Item +import net.minecraft.util.Identifier +import net.minecraft.util.Rarity +import net.minecraft.util.registry.Registry +import org.graalvm.polyglot.Value +import org.sandboxpowered.fabric.impl.item.PolyglotItem +import org.sandboxpowered.fabric.util.getMemberValue +import org.sandboxpowered.fabric.util.getMemberValueInt +import org.sandboxpowered.fabric.util.getMemberValueStr +import org.sandboxpowered.fabric.util.set + +class PolyglotGlobalItemManager { + private val archetypeMap: Map Item> + + init { + val builder = ImmutableMap.builder Item>() + + builder["item"] = { PolyglotItem(itemPropertiesToSettings(it), it) } + + archetypeMap = builder.build() + } + + private fun itemPropertiesToSettings(value: Value): Item.Settings { + val settings = Item.Settings() + if (!value.hasMember("properties")) return settings + val properties = value.getMember("properties") + properties.getMemberValueInt("maxDamage")?.let(settings::maxDamage) + properties.getMemberValueInt("maxCount")?.let(settings::maxCount) + properties.getMemberValueStr("rarity")?.let { + settings.rarity(stringToRarity(it)) + } + return settings + } + + private fun stringToRarity(rarity: String): Rarity = when (rarity) { + "uncommon" -> Rarity.UNCOMMON + "rare" -> Rarity.RARE + "epic" -> Rarity.EPIC + else -> Rarity.COMMON + } + + fun addItem(identifier: Identifier, value: Value) { + val archetype = value.getMemberValue("archetype", "item") + if (archetype !in archetypeMap) throw UnsupportedOperationException("Unknown item archetype [$archetype]") + val item = archetypeMap[archetype]!!(value) + Registry.register(Registry.ITEM, identifier, item) + } +} diff --git a/src/main/kotlin/org/sandboxpowered/fabric/api/item/PolyglotItemManager.kt b/src/main/kotlin/org/sandboxpowered/fabric/api/item/PolyglotItemManager.kt new file mode 100644 index 0000000..1daca9e --- /dev/null +++ b/src/main/kotlin/org/sandboxpowered/fabric/api/item/PolyglotItemManager.kt @@ -0,0 +1,13 @@ +package org.sandboxpowered.fabric.api.item + +import net.minecraft.util.Identifier +import org.graalvm.polyglot.HostAccess.Export +import org.graalvm.polyglot.Value + +class PolyglotItemManager(private val domain: String, private val global: PolyglotGlobalItemManager) { + @Export + fun add(id: String, value: Value) { + if (!value.hasMembers()) throw UnsupportedOperationException("Unsupported value for item registration") + global.addItem(Identifier(domain, id), value) + } +} \ No newline at end of file diff --git a/src/main/kotlin/org/sandboxpowered/fabric/impl/item/PolyglotItem.kt b/src/main/kotlin/org/sandboxpowered/fabric/impl/item/PolyglotItem.kt new file mode 100644 index 0000000..41ea7e0 --- /dev/null +++ b/src/main/kotlin/org/sandboxpowered/fabric/impl/item/PolyglotItem.kt @@ -0,0 +1,8 @@ +package org.sandboxpowered.fabric.impl.item + +import net.minecraft.item.Item +import org.graalvm.polyglot.Value + +class PolyglotItem(settings: Settings, value: Value) : Item(settings) { + +} \ 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 965b0a5..b19d13b 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, "items", false, polyglotLoader.getItemManager(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 64ba91d..69a68fa 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.item.PolyglotGlobalItemManager +import org.sandboxpowered.fabric.api.item.PolyglotItemManager import org.sandboxpowered.fabric.scripting.polyglot.PolyglotFileSystem import java.util.concurrent.Executors import java.util.concurrent.TimeUnit @@ -11,8 +13,10 @@ import java.util.concurrent.TimeoutException class PolyglotScriptLoader { private val executor = Executors.newSingleThreadExecutor() - private val scriptContext: MutableMap> = HashMap() - private val polyglotContext: MutableMap = HashMap() + private val scriptContext: MutableMap> = hashMapOf() + private val polyglotContext: MutableMap = hashMapOf() + private val globalItemManager = PolyglotGlobalItemManager() + private val itemManager: MutableMap = hashMapOf() private fun buildContext(): Context = Context.newBuilder("js", "python") .allowExperimentalOptions(true) @@ -24,9 +28,11 @@ class PolyglotScriptLoader { return scriptContext.computeIfAbsent(resource) { HashMap() } } - private fun getPolyglotContext(resource: String): SandboxResourcePolyglotContext { - return polyglotContext.computeIfAbsent(resource) { SandboxResourcePolyglotContext(it, this) } - } + private fun getPolyglotContext(resource: String): SandboxResourcePolyglotContext = + polyglotContext.computeIfAbsent(resource) { SandboxResourcePolyglotContext(it, this) } + + fun getItemManager(resource: String): PolyglotItemManager = + itemManager.computeIfAbsent(resource) { PolyglotItemManager(it, globalItemManager) } fun emitEventToAll(event: String, vararg args: Any) { polyglotContext.values.forEach { context -> @@ -34,9 +40,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) { diff --git a/src/main/kotlin/org/sandboxpowered/fabric/util/PolyglotUtil.kt b/src/main/kotlin/org/sandboxpowered/fabric/util/PolyglotUtil.kt index a16ca06..3e7a7a8 100644 --- a/src/main/kotlin/org/sandboxpowered/fabric/util/PolyglotUtil.kt +++ b/src/main/kotlin/org/sandboxpowered/fabric/util/PolyglotUtil.kt @@ -4,9 +4,18 @@ import com.google.gson.* import org.graalvm.polyglot.Value -fun Value.getMemberValue(identifier: String): String? = +fun Value.getMemberValueStr(identifier: String): String? = if (hasMember(identifier)) getMember(identifier).asString() else null +fun Value.getMemberValue(identifier: String, default: String): String = + if (hasMember(identifier)) getMember(identifier).asString() else default + +fun Value.getMemberValueInt(identifier: String): Int? = + if (hasMember(identifier)) getMember(identifier).asInt() else null + +fun Value.getMemberValue(identifier: String, default: Int): Int = + if (hasMember(identifier)) getMember(identifier).asInt() else default + fun Value.toJSON(): JsonElement = when { hasArrayElements() -> JsonArray().apply { (0 until arraySize) 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 From 8b6139e00ff8bc6975e52681433045912e1d729d Mon Sep 17 00:00:00 2001 From: Coded Date: Mon, 23 Aug 2021 13:52:46 +0100 Subject: [PATCH 2/5] Cleanup polyglot util --- .../sandboxpowered/fabric/util/PolyglotUtil.kt | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/main/kotlin/org/sandboxpowered/fabric/util/PolyglotUtil.kt b/src/main/kotlin/org/sandboxpowered/fabric/util/PolyglotUtil.kt index 3e7a7a8..fd8cc40 100644 --- a/src/main/kotlin/org/sandboxpowered/fabric/util/PolyglotUtil.kt +++ b/src/main/kotlin/org/sandboxpowered/fabric/util/PolyglotUtil.kt @@ -3,18 +3,13 @@ package org.sandboxpowered.fabric.util import com.google.gson.* import org.graalvm.polyglot.Value +fun Value.getMemberValue(member: String): Value? = if (hasMember(member)) getMember(member) else null -fun Value.getMemberValueStr(identifier: String): String? = - if (hasMember(identifier)) getMember(identifier).asString() else null +fun Value.getMemberValueStr(member: String): String? = getMemberValue(member)?.asString() +fun Value.getMemberValueInt(member: String): Int? = getMemberValue(member)?.asInt() -fun Value.getMemberValue(identifier: String, default: String): String = - if (hasMember(identifier)) getMember(identifier).asString() else default - -fun Value.getMemberValueInt(identifier: String): Int? = - if (hasMember(identifier)) getMember(identifier).asInt() else null - -fun Value.getMemberValue(identifier: String, default: Int): Int = - if (hasMember(identifier)) getMember(identifier).asInt() else default +fun Value.getMemberValue(member: String, default: String): String = getMemberValueStr(member) ?: default +fun Value.getMemberValue(member: String, default: Int): Int = getMemberValueInt(member) ?: default fun Value.toJSON(): JsonElement = when { hasArrayElements() -> JsonArray().apply { From 9941d5f198b8dfbfed9d1da6d56947760fa0c1e3 Mon Sep 17 00:00:00 2001 From: Coded Date: Mon, 23 Aug 2021 13:56:02 +0100 Subject: [PATCH 3/5] Fix class cast exception with long/float --- .../kotlin/org/sandboxpowered/fabric/util/PolyglotUtil.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/org/sandboxpowered/fabric/util/PolyglotUtil.kt b/src/main/kotlin/org/sandboxpowered/fabric/util/PolyglotUtil.kt index fd8cc40..dcc903c 100644 --- a/src/main/kotlin/org/sandboxpowered/fabric/util/PolyglotUtil.kt +++ b/src/main/kotlin/org/sandboxpowered/fabric/util/PolyglotUtil.kt @@ -22,6 +22,11 @@ fun Value.toJSON(): JsonElement = when { } isString -> JsonPrimitive(asString()) isBoolean -> JsonPrimitive(asBoolean()) - isNumber -> JsonPrimitive(asInt()) + isNumber -> when { + fitsInInt() -> JsonPrimitive(asInt()) + fitsInLong() -> JsonPrimitive(asLong()) + fitsInFloat() -> JsonPrimitive(asFloat()) + else -> JsonNull.INSTANCE + } else -> JsonNull.INSTANCE } \ No newline at end of file From 5fcf133d0d6573ece74d05f43d897a81f597dbff Mon Sep 17 00:00:00 2001 From: Coded Date: Mon, 23 Aug 2021 15:06:50 +0100 Subject: [PATCH 4/5] Join declaration with instantiation --- .../fabric/api/item/PolyglotGlobalItemManager.kt | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/org/sandboxpowered/fabric/api/item/PolyglotGlobalItemManager.kt b/src/main/kotlin/org/sandboxpowered/fabric/api/item/PolyglotGlobalItemManager.kt index dcb48ef..e53daa8 100644 --- a/src/main/kotlin/org/sandboxpowered/fabric/api/item/PolyglotGlobalItemManager.kt +++ b/src/main/kotlin/org/sandboxpowered/fabric/api/item/PolyglotGlobalItemManager.kt @@ -13,15 +13,9 @@ import org.sandboxpowered.fabric.util.getMemberValueStr import org.sandboxpowered.fabric.util.set class PolyglotGlobalItemManager { - private val archetypeMap: Map Item> - - init { - val builder = ImmutableMap.builder Item>() - - builder["item"] = { PolyglotItem(itemPropertiesToSettings(it), it) } - - archetypeMap = builder.build() - } + private val archetypeMap: Map Item> = ImmutableMap.builder Item>().apply { + this["item"] = { PolyglotItem(itemPropertiesToSettings(it), it) } + }.build() private fun itemPropertiesToSettings(value: Value): Item.Settings { val settings = Item.Settings() From cc50d528fcc95984ed00627a32e076fad780246d Mon Sep 17 00:00:00 2001 From: Coded Date: Mon, 23 Aug 2021 15:13:25 +0100 Subject: [PATCH 5/5] Reduce explicit exception throwing --- .../org/sandboxpowered/fabric/api/item/PolyglotItemManager.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/org/sandboxpowered/fabric/api/item/PolyglotItemManager.kt b/src/main/kotlin/org/sandboxpowered/fabric/api/item/PolyglotItemManager.kt index 1daca9e..8ccd9a8 100644 --- a/src/main/kotlin/org/sandboxpowered/fabric/api/item/PolyglotItemManager.kt +++ b/src/main/kotlin/org/sandboxpowered/fabric/api/item/PolyglotItemManager.kt @@ -7,7 +7,7 @@ import org.graalvm.polyglot.Value class PolyglotItemManager(private val domain: String, private val global: PolyglotGlobalItemManager) { @Export fun add(id: String, value: Value) { - if (!value.hasMembers()) throw UnsupportedOperationException("Unsupported value for item registration") + require(value.hasMembers()) { "Unsupported value as custom item" } global.addItem(Identifier(domain, id), value) } } \ No newline at end of file