diff --git a/src/main/java/dev/latvian/mods/kubejs/BuiltinKubeJSPlugin.java b/src/main/java/dev/latvian/mods/kubejs/BuiltinKubeJSPlugin.java index 8f7edf9be..340cf6047 100644 --- a/src/main/java/dev/latvian/mods/kubejs/BuiltinKubeJSPlugin.java +++ b/src/main/java/dev/latvian/mods/kubejs/BuiltinKubeJSPlugin.java @@ -196,6 +196,7 @@ import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.entity.BannerPattern; +import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockSetType; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.dimension.DimensionType; @@ -556,6 +557,7 @@ public void registerTypeWrappers(TypeWrapperRegistry registry) { // FIXME registry.register(Enchantment.Cost.class, EnchantmentBuilder::costOf); registry.registerEnumFromStringCodec(ArmorItem.Type.class, ArmorItem.Type.CODEC); registry.register(BlockSetType.class, BlockWrapper::setTypeOf); + registry.register(BlockState.class, BlockWrapper::wrapBlockState); registry.register(ItemAbility.class, ItemWrapper::itemAbilityOf); // KubeJS // diff --git a/src/main/java/dev/latvian/mods/kubejs/bindings/BlockWrapper.java b/src/main/java/dev/latvian/mods/kubejs/bindings/BlockWrapper.java index d64695359..5d3d181d9 100644 --- a/src/main/java/dev/latvian/mods/kubejs/bindings/BlockWrapper.java +++ b/src/main/java/dev/latvian/mods/kubejs/bindings/BlockWrapper.java @@ -4,6 +4,7 @@ import dev.latvian.mods.kubejs.block.predicate.BlockIDPredicate; import dev.latvian.mods.kubejs.block.predicate.BlockPredicate; import dev.latvian.mods.kubejs.typings.Info; +import dev.latvian.mods.kubejs.util.RegistryAccessContainer; import dev.latvian.mods.kubejs.util.Tags; import dev.latvian.mods.rhino.Context; import dev.latvian.mods.rhino.type.RecordTypeInfo; @@ -12,6 +13,7 @@ import net.minecraft.commands.arguments.blocks.BlockStateParser; import net.minecraft.core.Direction; import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; @@ -120,13 +122,13 @@ public static Collection getAllBlockStates() { return ALL_STATE_CACHE; } - public static BlockState parseBlockState(String string) { + public static BlockState parseBlockState(RegistryAccessContainer registries, String string) { if (string.isEmpty()) { return Blocks.AIR.defaultBlockState(); } try { - return BlockStateParser.parseForBlock(BuiltInRegistries.BLOCK.asLookup(), string, false).blockState(); + return BlockStateParser.parseForBlock(registries.access().lookupOrThrow(Registries.BLOCK), string, false).blockState(); } catch (Exception ex) { return Blocks.AIR.defaultBlockState(); } @@ -152,10 +154,12 @@ public static BlockSetType setTypeOf(Context cx, Object from, TypeInfo target) { } @Info("Parses a block state from the input string. May throw for invalid inputs!") - static BlockState parseBlockState(Object o) { - if (o instanceof BlockState bs) { - return bs; - } - return o == null ? Blocks.AIR.defaultBlockState() : BlockWrapper.parseBlockState(o.toString()); + public static BlockState wrapBlockState(RegistryAccessContainer registries, Object o) { + return switch (o) { + case null -> Blocks.AIR.defaultBlockState(); + case BlockState bs -> bs; + case Block block -> block.defaultBlockState(); + default -> parseBlockState(registries, o.toString()); + }; } } \ No newline at end of file diff --git a/src/main/java/dev/latvian/mods/kubejs/block/state/BlockStatePredicate.java b/src/main/java/dev/latvian/mods/kubejs/block/state/BlockStatePredicate.java index 33b017941..7a4cfbeff 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/state/BlockStatePredicate.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/state/BlockStatePredicate.java @@ -53,7 +53,7 @@ default RuleTest asRuleTest() { return null; } - static BlockStatePredicate fromString(String s) { + static BlockStatePredicate fromString(RegistryAccessContainer registries, String s) { if (s.equals("*")) { return Simple.ALL; } else if (s.equals("-")) { @@ -61,7 +61,7 @@ static BlockStatePredicate fromString(String s) { } else if (s.startsWith("#")) { return new TagMatch(Tags.block(ResourceLocation.parse(s.substring(1)))); } else if (s.indexOf('[') != -1) { - var state = BlockWrapper.parseBlockState(s); + var state = BlockWrapper.parseBlockState(registries, s); if (state != Blocks.AIR.defaultBlockState()) { return new StateMatch(state); @@ -77,7 +77,7 @@ static BlockStatePredicate fromString(String s) { return Simple.NONE; } - static BlockStatePredicate of(Object o) { + static BlockStatePredicate of(RegistryAccessContainer registries, Object o) { if (o == null || o == Simple.ALL) { return Simple.ALL; } else if (o == Simple.NONE) { @@ -91,7 +91,7 @@ static BlockStatePredicate of(Object o) { var predicates = new ArrayList(); for (var o1 : list) { - var p = of(o1); + var p = of(registries, o1); if (p == Simple.ALL) { return Simple.ALL; } else if (p != Simple.NONE) { @@ -111,17 +111,17 @@ static BlockStatePredicate of(Object o) { var predicates = new ArrayList(); if (map.get("or") != null) { - predicates.add(of(map.get("or"))); + predicates.add(of(registries, map.get("or"))); } if (map.get("not") != null) { - predicates.add(new NotMatch(of(map.get("not")))); + predicates.add(new NotMatch(of(registries, map.get("not")))); } return new AndMatch(predicates); } - return ofSingle(o); + return ofSingle(registries, o); } static RuleTest ruleTestOf(Context cx, Object o) { @@ -131,15 +131,17 @@ static RuleTest ruleTestOf(Context cx, Object o) { return bsp.asRuleTest(); } + RegistryAccessContainer registries = RegistryAccessContainer.of(cx); + return Optional.ofNullable(NBTUtils.toTagCompound(cx, o)) - .map(tag -> RuleTest.CODEC.parse(RegistryAccessContainer.of(cx).nbt(), tag)) + .map(tag -> RuleTest.CODEC.parse(registries.nbt(), tag)) .flatMap(DataResult::result) - .or(() -> Optional.ofNullable(of(o).asRuleTest())) + .or(() -> Optional.ofNullable(of(registries, o).asRuleTest())) .orElseThrow(() -> new IllegalArgumentException("Could not parse valid rule test from " + o + "!")); } @SuppressWarnings("unchecked") - private static BlockStatePredicate ofSingle(Object o) { + private static BlockStatePredicate ofSingle(RegistryAccessContainer registries, Object o) { if (o instanceof BlockStatePredicate bsp) { return bsp; } else if (o instanceof Block block) { @@ -151,7 +153,7 @@ private static BlockStatePredicate ofSingle(Object o) { } var pattern = RegExpKJS.wrap(o); - return pattern == null ? BlockStatePredicate.fromString(o.toString()) : new RegexMatch(pattern); + return pattern == null ? BlockStatePredicate.fromString(registries, o.toString()) : new RegexMatch(pattern); } default Collection getBlockStates() { diff --git a/src/main/java/dev/latvian/mods/kubejs/client/KubeJSClientEventHandler.java b/src/main/java/dev/latvian/mods/kubejs/client/KubeJSClientEventHandler.java index 7bbc88b48..63a68a8eb 100644 --- a/src/main/java/dev/latvian/mods/kubejs/client/KubeJSClientEventHandler.java +++ b/src/main/java/dev/latvian/mods/kubejs/client/KubeJSClientEventHandler.java @@ -167,21 +167,30 @@ public static void onItemTooltip(ItemTooltipEvent event) { } if (staticItemTooltips == null) { - staticItemTooltips = new IdentityHashMap<>(); - ItemEvents.TOOLTIP.post(ScriptType.CLIENT, new ItemTooltipKubeEvent(staticItemTooltips)); + var staticItemTooltips0 = new IdentityHashMap>(); + ItemEvents.TOOLTIP.post(ScriptType.CLIENT, new ItemTooltipKubeEvent(staticItemTooltips0)); + staticItemTooltips = staticItemTooltips0; } try { - for (var handler : staticItemTooltips.getOrDefault(Items.AIR, List.of())) { - handler.tooltip(stack, advanced, lines); + var handlers = staticItemTooltips.get(Items.AIR); + + if (handlers != null && !handlers.isEmpty()) { + for (var handler : handlers) { + handler.tooltip(stack, advanced, lines); + } } } catch (Exception ex) { ConsoleJS.CLIENT.error("Error while gathering tooltip for " + stack, ex); } try { - for (var handler : staticItemTooltips.getOrDefault(stack.getItem(), List.of())) { - handler.tooltip(stack, advanced, lines); + var handlers = staticItemTooltips.get(stack.getItem()); + + if (handlers != null && !handlers.isEmpty()) { + for (var handler : handlers) { + handler.tooltip(stack, advanced, lines); + } } } catch (Exception ex) { ConsoleJS.CLIENT.error("Error while gathering tooltip for " + stack, ex); diff --git a/src/main/java/dev/latvian/mods/kubejs/core/mixin/FallingBlockEntityMixin.java b/src/main/java/dev/latvian/mods/kubejs/core/mixin/FallingBlockEntityMixin.java index bb0048142..403029e0e 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/mixin/FallingBlockEntityMixin.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/mixin/FallingBlockEntityMixin.java @@ -4,6 +4,7 @@ import dev.latvian.mods.kubejs.block.BlockStartedFallingKubeEvent; import dev.latvian.mods.kubejs.block.BlockStoppedFallingKubeEvent; import dev.latvian.mods.kubejs.script.ScriptType; +import dev.latvian.mods.rhino.util.RemapForJS; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.item.FallingBlockEntity; import net.minecraft.world.level.Level; @@ -11,6 +12,7 @@ import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -39,4 +41,10 @@ public class FallingBlockEntityMixin { BlockEvents.STOPPED_FALLING.post(ScriptType.SERVER, blockState.kjs$getKey(), new BlockStoppedFallingKubeEvent(entity.level(), pos, blockState, entity, fallSpeed, replacedState)); } } + + @Unique + @RemapForJS("setBlockState") + public void kjs$setBlockState(BlockState state) { + this.blockState = state; + } } diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/BlockComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/BlockComponent.java index a3e1d4ea9..734d0c936 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/BlockComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/BlockComponent.java @@ -7,6 +7,7 @@ import dev.latvian.mods.kubejs.recipe.KubeRecipe; import dev.latvian.mods.kubejs.recipe.RecipeKey; import dev.latvian.mods.kubejs.recipe.match.ReplacementMatchInfo; +import dev.latvian.mods.kubejs.util.RegistryAccessContainer; import dev.latvian.mods.rhino.Context; import dev.latvian.mods.rhino.type.TypeInfo; import net.minecraft.core.registries.BuiltInRegistries; @@ -32,8 +33,8 @@ public Block wrap(Context cx, KubeRecipe recipe, Object from) { return switch (from) { case Block b -> b; case BlockState s -> s.getBlock(); - case JsonPrimitive json -> BlockWrapper.parseBlockState(json.getAsString()).getBlock(); - case null, default -> BlockWrapper.parseBlockState(String.valueOf(from)).getBlock(); + case JsonPrimitive json -> BlockWrapper.parseBlockState(RegistryAccessContainer.of(cx), json.getAsString()).getBlock(); + case null, default -> BlockWrapper.parseBlockState(RegistryAccessContainer.of(cx), String.valueOf(from)).getBlock(); }; } diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/BlockStateComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/BlockStateComponent.java index 6e4022cb5..c0c87f6cb 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/BlockStateComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/BlockStateComponent.java @@ -11,6 +11,7 @@ import dev.latvian.mods.kubejs.recipe.match.ReplacementMatchInfo; import dev.latvian.mods.kubejs.util.JsonUtils; import dev.latvian.mods.kubejs.util.MapJS; +import dev.latvian.mods.kubejs.util.RegistryAccessContainer; import dev.latvian.mods.rhino.Context; import dev.latvian.mods.rhino.type.TypeInfo; import net.minecraft.world.level.block.Block; @@ -38,11 +39,11 @@ public BlockState wrap(Context cx, KubeRecipe recipe, Object from) { return switch (from) { case BlockState s -> s; case Block b -> b.defaultBlockState(); - case JsonPrimitive json -> BlockWrapper.parseBlockState(json.getAsString()); + case JsonPrimitive json -> BlockWrapper.parseBlockState(RegistryAccessContainer.of(cx), json.getAsString()); case null, default -> { Map map = MapJS.of(from); if (map == null) { - yield BlockWrapper.parseBlockState(String.valueOf(from)); + yield BlockWrapper.parseBlockState(RegistryAccessContainer.of(cx), String.valueOf(from)); } else { // this is formatted like so: // { Name: "blockid", Properties: {Property: "value"}}