diff --git a/src/main/kotlin/org/sandboxpowered/fabric/api/PolyglotRecipeManager.kt b/src/main/kotlin/org/sandboxpowered/fabric/api/PolyglotRecipeManager.kt index 47da9ef..a622f6b 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 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/item/PolyglotGlobalItemManager.kt b/src/main/kotlin/org/sandboxpowered/fabric/api/item/PolyglotGlobalItemManager.kt new file mode 100644 index 0000000..e53daa8 --- /dev/null +++ b/src/main/kotlin/org/sandboxpowered/fabric/api/item/PolyglotGlobalItemManager.kt @@ -0,0 +1,45 @@ +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> = ImmutableMap.builder Item>().apply { + this["item"] = { PolyglotItem(itemPropertiesToSettings(it), it) } + }.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..8ccd9a8 --- /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) { + require(value.hasMembers()) { "Unsupported value as custom item" } + 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 63cee70..09345ef 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 8baf261..65737ac 100644 --- a/src/main/kotlin/org/sandboxpowered/fabric/scripting/PolyglotScriptLoader.kt +++ b/src/main/kotlin/org/sandboxpowered/fabric/scripting/PolyglotScriptLoader.kt @@ -4,14 +4,18 @@ 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 org.sandboxpowered.fabric.util.TimingUtil import java.util.concurrent.Executors 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) @@ -23,9 +27,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 -> @@ -33,9 +39,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/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 a16ca06..dcc903c 100644 --- a/src/main/kotlin/org/sandboxpowered/fabric/util/polyglot.kt +++ b/src/main/kotlin/org/sandboxpowered/fabric/util/polyglot.kt @@ -3,9 +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.getMemberValue(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(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 { @@ -18,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