diff --git a/gradle.properties b/gradle.properties index 43d5b46c3..d5bf0e0b4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ modrinth_id=umyGl7zF minecraft_version=1.21.1 supported_versions=1.21.1, 1.21 -mod_version=2101.7.1 +mod_version=2101.7.2 neoforge_version=21.1.42 parchment_mc_version=1.21 diff --git a/src/main/java/dev/latvian/mods/kubejs/BuiltinKubeJSPlugin.java b/src/main/java/dev/latvian/mods/kubejs/BuiltinKubeJSPlugin.java index 50c7f35d2..4d53796fb 100644 --- a/src/main/java/dev/latvian/mods/kubejs/BuiltinKubeJSPlugin.java +++ b/src/main/java/dev/latvian/mods/kubejs/BuiltinKubeJSPlugin.java @@ -567,6 +567,7 @@ public void registerTypeWrappers(TypeWrapperRegistry registry) { registry.register(BlockPos.class, KubeJSTypeWrappers::blockPosOf); registry.register(Vec3.class, KubeJSTypeWrappers::vec3Of); + registry.register(Vec3i.class, KubeJSTypeWrappers::blockPosOf); registry.register(Item.class, ItemStackJS::getRawItem); registry.register(ItemLike.class, ItemStackJS::getRawItem); diff --git a/src/main/java/dev/latvian/mods/kubejs/KubeJSCodecs.java b/src/main/java/dev/latvian/mods/kubejs/KubeJSCodecs.java index 1dda8f8c0..a432791cc 100644 --- a/src/main/java/dev/latvian/mods/kubejs/KubeJSCodecs.java +++ b/src/main/java/dev/latvian/mods/kubejs/KubeJSCodecs.java @@ -8,12 +8,14 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; import com.mojang.serialization.JsonOps; +import com.mojang.serialization.MapCodec; import dev.latvian.mods.kubejs.util.JsonUtils; import dev.latvian.mods.kubejs.util.UtilsJS; import dev.latvian.mods.rhino.type.EnumTypeInfo; import dev.latvian.mods.rhino.type.TypeInfo; import io.netty.buffer.ByteBuf; import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.Utf8String; import net.minecraft.network.codec.ByteBufCodecs; @@ -22,6 +24,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.util.StringRepresentable; import net.minecraft.util.valueproviders.IntProvider; +import net.minecraft.world.entity.EntityType; import net.minecraft.world.level.storage.loot.providers.number.NumberProvider; import net.minecraft.world.level.storage.loot.providers.number.NumberProviders; import org.jetbrains.annotations.Nullable; @@ -89,6 +92,8 @@ public void encode(ByteBuf buffer, @Nullable JsonElement value) { Codec>> REGISTRY_KEY = ResourceLocation.CODEC.xmap(ResourceKey::createRegistryKey, ResourceKey::location); + MapCodec> ENTITY_TYPE_FIELD_CODEC = BuiltInRegistries.ENTITY_TYPE.byNameCodec().fieldOf("id"); + static Codec stringResolverCodec(Function toStringFunction, Function fromStringFunction) { return Codec.STRING.flatXmap(str -> Optional.ofNullable(fromStringFunction.apply(str)) .map(DataResult::success) diff --git a/src/main/java/dev/latvian/mods/kubejs/KubeJSTypeWrappers.java b/src/main/java/dev/latvian/mods/kubejs/KubeJSTypeWrappers.java index c969293e1..2c04fadde 100644 --- a/src/main/java/dev/latvian/mods/kubejs/KubeJSTypeWrappers.java +++ b/src/main/java/dev/latvian/mods/kubejs/KubeJSTypeWrappers.java @@ -1,6 +1,6 @@ package dev.latvian.mods.kubejs; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.kubejs.util.NBTUtils; import dev.latvian.mods.kubejs.util.RegistryAccessContainer; import dev.latvian.mods.kubejs.util.UtilsJS; @@ -133,8 +133,8 @@ static Vec3 vec3Of(@Nullable Object o) { return new Vec3(UtilsJS.parseDouble(list.get(0), 0), UtilsJS.parseDouble(list.get(1), 0), UtilsJS.parseDouble(list.get(2), 0)); } else if (o instanceof BlockPos pos) { return new Vec3(pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D); - } else if (o instanceof BlockContainerJS block) { - return new Vec3(block.getPos().getX() + 0.5D, block.getPos().getY() + 0.5D, block.getPos().getZ() + 0.5D); + } else if (o instanceof LevelBlock block) { + return new Vec3(block.getCenterX(), block.getCenterY(), block.getCenterZ()); } return Vec3.ZERO; @@ -145,7 +145,7 @@ static BlockPos blockPosOf(@Nullable Object o) { return pos; } else if (o instanceof List list && list.size() >= 3) { return new BlockPos(UtilsJS.parseInt(list.get(0), 0), UtilsJS.parseInt(list.get(1), 0), UtilsJS.parseInt(list.get(2), 0)); - } else if (o instanceof BlockContainerJS block) { + } else if (o instanceof LevelBlock block) { return block.getPos(); } else if (o instanceof Vec3 vec) { return BlockPos.containing(vec.x, vec.y, vec.z); diff --git a/src/main/java/dev/latvian/mods/kubejs/bindings/ItemWrapper.java b/src/main/java/dev/latvian/mods/kubejs/bindings/ItemWrapper.java index 1c87c1f9c..6017b1298 100644 --- a/src/main/java/dev/latvian/mods/kubejs/bindings/ItemWrapper.java +++ b/src/main/java/dev/latvian/mods/kubejs/bindings/ItemWrapper.java @@ -3,7 +3,6 @@ import com.google.gson.JsonObject; import com.mojang.authlib.properties.Property; import com.mojang.authlib.properties.PropertyMap; -import com.mojang.serialization.MapCodec; import dev.latvian.mods.kubejs.item.ItemStackJS; import dev.latvian.mods.kubejs.typings.Info; import dev.latvian.mods.kubejs.util.JsonUtils; @@ -11,7 +10,6 @@ import net.minecraft.core.component.DataComponents; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.EntityType; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -30,8 +28,6 @@ @Info("Various item related helper methods") public interface ItemWrapper { - MapCodec> ENTITY_TYPE_FIELD_CODEC = BuiltInRegistries.ENTITY_TYPE.byNameCodec().fieldOf("id"); - @Info("Returns an ItemStack of the input") static ItemStack of(ItemStack in) { return in; diff --git a/src/main/java/dev/latvian/mods/kubejs/block/BlockBrokenKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/block/BlockBrokenKubeEvent.java index 9983ab9fd..f97e61a09 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/BlockBrokenKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/BlockBrokenKubeEvent.java @@ -1,6 +1,6 @@ package dev.latvian.mods.kubejs.block; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.kubejs.player.KubePlayerEvent; import dev.latvian.mods.kubejs.typings.Info; import net.minecraft.world.entity.player.Player; @@ -24,9 +24,7 @@ public Player getEntity() { } @Info("The block that was broken.") - public BlockContainerJS getBlock() { - var block = new BlockContainerJS((Level) event.getLevel(), event.getPos()); - block.cachedState = event.getState(); - return block; + public LevelBlock getBlock() { + return ((Level) event.getLevel()).kjs$getBlock(event.getPos()).cache(event.getState()); } } \ No newline at end of file diff --git a/src/main/java/dev/latvian/mods/kubejs/block/BlockDropsKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/block/BlockDropsKubeEvent.java index 37ca96d11..9d74368f0 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/BlockDropsKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/BlockDropsKubeEvent.java @@ -2,7 +2,7 @@ import dev.latvian.mods.kubejs.entity.KubeEntityEvent; import dev.latvian.mods.kubejs.item.ItemPredicate; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.kubejs.typings.Info; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Mth; @@ -37,11 +37,8 @@ public Entity getEntity() { } @Info("The block that was broken.") - public BlockContainerJS getBlock() { - var block = new BlockContainerJS(event.getLevel(), event.getPos()); - block.cachedState = event.getState(); - block.cachedEntity = event.getBlockEntity(); - return block; + public LevelBlock getBlock() { + return event.getLevel().kjs$getBlock(event.getPos()).cache(event.getState()).cache(event.getBlockEntity()); } @Info("The experience dropped by the block.") diff --git a/src/main/java/dev/latvian/mods/kubejs/block/BlockLeftClickedKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/block/BlockLeftClickedKubeEvent.java index 5e6549c6d..2b80c84e8 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/BlockLeftClickedKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/BlockLeftClickedKubeEvent.java @@ -1,6 +1,6 @@ package dev.latvian.mods.kubejs.block; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.kubejs.player.KubePlayerEvent; import dev.latvian.mods.kubejs.typings.Info; import net.minecraft.core.Direction; @@ -26,8 +26,8 @@ public Player getEntity() { } @Info("The block that was left clicked.") - public BlockContainerJS getBlock() { - return new BlockContainerJS(event.getLevel(), event.getPos()); + public LevelBlock getBlock() { + return event.getLevel().kjs$getBlock(event.getPos()); } @Info("The item that was used to left click the block.") diff --git a/src/main/java/dev/latvian/mods/kubejs/block/BlockPlacedKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/block/BlockPlacedKubeEvent.java index 1bba03ed5..8ea1cbb28 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/BlockPlacedKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/BlockPlacedKubeEvent.java @@ -1,7 +1,7 @@ package dev.latvian.mods.kubejs.block; import dev.latvian.mods.kubejs.entity.KubeEntityEvent; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.kubejs.typings.Info; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; @@ -30,9 +30,7 @@ public Entity getEntity() { } @Info("The block that is placed.") - public BlockContainerJS getBlock() { - var block = new BlockContainerJS((Level) event.getLevel(), event.getPos()); - block.cachedState = event.getPlacedBlock(); - return block; + public LevelBlock getBlock() { + return ((Level) event.getLevel()).kjs$getBlock(event.getPos()).cache(event.getPlacedBlock()); } } \ No newline at end of file diff --git a/src/main/java/dev/latvian/mods/kubejs/block/BlockRightClickedKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/block/BlockRightClickedKubeEvent.java index ccb62ed08..6962dd105 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/BlockRightClickedKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/BlockRightClickedKubeEvent.java @@ -1,6 +1,6 @@ package dev.latvian.mods.kubejs.block; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.kubejs.player.KubePlayerEvent; import dev.latvian.mods.kubejs.typings.Info; import net.minecraft.core.BlockPos; @@ -21,7 +21,7 @@ public class BlockRightClickedKubeEvent implements KubePlayerEvent { private final BlockPos pos; private final Direction direction; private final BlockHitResult hitResult; - private BlockContainerJS block; + private LevelBlock block; public BlockRightClickedKubeEvent(ItemStack item, Player player, InteractionHand hand, BlockPos pos, Direction direction, @Nullable BlockHitResult hitResult) { this.item = item; @@ -39,9 +39,9 @@ public Player getEntity() { } @Info("The block that was right clicked.") - public BlockContainerJS getBlock() { + public LevelBlock getBlock() { if (block == null) { - block = new BlockContainerJS(player.level(), pos); + block = player.level().kjs$getBlock(pos); } return block; diff --git a/src/main/java/dev/latvian/mods/kubejs/block/BlockStartedFallingKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/block/BlockStartedFallingKubeEvent.java index 3dbf3d3f6..f2cd406f2 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/BlockStartedFallingKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/BlockStartedFallingKubeEvent.java @@ -1,7 +1,7 @@ package dev.latvian.mods.kubejs.block; import dev.latvian.mods.kubejs.entity.KubeEntityEvent; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.kubejs.typings.Info; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; @@ -13,12 +13,11 @@ Invoked when a falling block starts to fall. """) public class BlockStartedFallingKubeEvent implements KubeEntityEvent { - private final BlockContainerJS block; + private final LevelBlock block; private final FallingBlockEntity entity; public BlockStartedFallingKubeEvent(Level level, BlockPos pos, BlockState state, FallingBlockEntity entity) { - this.block = new BlockContainerJS(level, pos); - this.block.cachedState = state; + this.block = level.kjs$getBlock(pos).cache(state); this.entity = entity; } @@ -32,7 +31,7 @@ public Entity getEntity() { return entity; } - public BlockContainerJS getBlock() { + public LevelBlock getBlock() { return block; } } \ No newline at end of file diff --git a/src/main/java/dev/latvian/mods/kubejs/block/BlockStoppedFallingKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/block/BlockStoppedFallingKubeEvent.java index b74cec520..346a259b1 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/BlockStoppedFallingKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/BlockStoppedFallingKubeEvent.java @@ -1,7 +1,7 @@ package dev.latvian.mods.kubejs.block; import dev.latvian.mods.kubejs.entity.KubeEntityEvent; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.kubejs.typings.Info; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; @@ -13,18 +13,16 @@ Invoked when a falling block finishes falling. """) public class BlockStoppedFallingKubeEvent implements KubeEntityEvent { - public final BlockContainerJS block; + public final LevelBlock block; private final FallingBlockEntity entity; public final double fallSpeed; - public final BlockContainerJS replacedBlock; + public final LevelBlock replacedBlock; public BlockStoppedFallingKubeEvent(Level level, BlockPos pos, BlockState state, FallingBlockEntity entity, double fallSpeed, BlockState replacedState) { - this.block = new BlockContainerJS(level, pos); - this.block.cachedState = state; + this.block = level.kjs$getBlock(pos).cache(state); this.entity = entity; this.fallSpeed = fallSpeed; - this.replacedBlock = new BlockContainerJS(level, pos); - this.replacedBlock.cachedState = replacedState; + this.replacedBlock = level.kjs$getBlock(pos).cache(replacedState); } @Override diff --git a/src/main/java/dev/latvian/mods/kubejs/block/DetectorBlockKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/block/DetectorBlockKubeEvent.java index 6d5e489f9..1881b3a61 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/DetectorBlockKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/DetectorBlockKubeEvent.java @@ -1,7 +1,7 @@ package dev.latvian.mods.kubejs.block; -import dev.latvian.mods.kubejs.level.BlockContainerJS; import dev.latvian.mods.kubejs.level.KubeLevelEvent; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.kubejs.typings.Info; import net.minecraft.core.BlockPos; import net.minecraft.world.level.Level; @@ -14,16 +14,14 @@ public class DetectorBlockKubeEvent implements KubeLevelEvent { private final String detectorId; private final Level level; - private final BlockPos pos; private final boolean powered; - private final BlockContainerJS block; + private final LevelBlock block; public DetectorBlockKubeEvent(String i, Level l, BlockPos p, boolean pow) { detectorId = i; level = l; - pos = p; powered = pow; - block = new BlockContainerJS(level, pos); + block = level.kjs$getBlock(p); } @Info("The id of the detector block when it was registered.") @@ -43,7 +41,7 @@ public boolean isPowered() { } @Info("The detector block.") - public BlockContainerJS getBlock() { + public LevelBlock getBlock() { return block; } } diff --git a/src/main/java/dev/latvian/mods/kubejs/block/FarmlandTrampledKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/block/FarmlandTrampledKubeEvent.java index a13c920f8..cd51600b5 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/FarmlandTrampledKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/FarmlandTrampledKubeEvent.java @@ -1,7 +1,7 @@ package dev.latvian.mods.kubejs.block; import dev.latvian.mods.kubejs.entity.KubeEntityEvent; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.kubejs.typings.Info; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; @@ -12,12 +12,11 @@ """) public class FarmlandTrampledKubeEvent implements KubeEntityEvent { private final BlockEvent.FarmlandTrampleEvent event; - private final BlockContainerJS block; + private final LevelBlock block; public FarmlandTrampledKubeEvent(BlockEvent.FarmlandTrampleEvent event) { this.event = event; - this.block = new BlockContainerJS((Level) event.getLevel(), event.getPos()); - this.block.cachedState = event.getState(); + this.block = ((Level) event.getLevel()).kjs$getBlock(event.getPos()).cache(event.getState()); } @Info("The distance of the entity from the block.") @@ -38,7 +37,7 @@ public Level getLevel() { } @Info("The farmland block.") - public BlockContainerJS getBlock() { + public LevelBlock getBlock() { return block; } } diff --git a/src/main/java/dev/latvian/mods/kubejs/block/RandomTickCallbackJS.java b/src/main/java/dev/latvian/mods/kubejs/block/RandomTickCallbackJS.java index 0136e0130..a17db36cb 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/RandomTickCallbackJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/RandomTickCallbackJS.java @@ -1,16 +1,16 @@ package dev.latvian.mods.kubejs.block; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import net.minecraft.server.MinecraftServer; import net.minecraft.util.RandomSource; import net.minecraft.world.level.Level; public class RandomTickCallbackJS { - public BlockContainerJS block; - public RandomSource random; + public final LevelBlock block; + public final RandomSource random; - public RandomTickCallbackJS(BlockContainerJS containerJS, RandomSource random) { - this.block = containerJS; + public RandomTickCallbackJS(LevelBlock block, RandomSource random) { + this.block = block; this.random = random; } diff --git a/src/main/java/dev/latvian/mods/kubejs/block/RandomTickKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/block/RandomTickKubeEvent.java index 1ce4e5602..a5b69790e 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/RandomTickKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/RandomTickKubeEvent.java @@ -1,7 +1,7 @@ package dev.latvian.mods.kubejs.block; -import dev.latvian.mods.kubejs.level.BlockContainerJS; import dev.latvian.mods.kubejs.level.KubeLevelEvent; +import dev.latvian.mods.kubejs.level.LevelBlock; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; @@ -12,7 +12,7 @@ public class RandomTickKubeEvent implements KubeLevelEvent { private final BlockPos pos; private final BlockState state; public final RandomSource random; - private BlockContainerJS block; + private LevelBlock block; public RandomTickKubeEvent(ServerLevel level, BlockPos pos, BlockState state, RandomSource random) { this.level = level; @@ -26,10 +26,9 @@ public ServerLevel getLevel() { return level; } - public BlockContainerJS getBlock() { + public LevelBlock getBlock() { if (block == null) { - block = new BlockContainerJS(level, pos); - block.cachedState = state; + block = level.kjs$getBlock(pos).cache(state); } return block; diff --git a/src/main/java/dev/latvian/mods/kubejs/block/callbacks/BlockExplodedCallbackJS.java b/src/main/java/dev/latvian/mods/kubejs/block/callbacks/BlockExplodedCallbackJS.java index b4eb186dc..dcf10fae7 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/callbacks/BlockExplodedCallbackJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/callbacks/BlockExplodedCallbackJS.java @@ -1,6 +1,6 @@ package dev.latvian.mods.kubejs.block.callbacks; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; @@ -13,29 +13,24 @@ import java.util.List; public class BlockExplodedCallbackJS { - - protected final Level level; - protected final BlockContainerJS block; - protected final BlockState state; + protected final LevelBlock block; protected final Explosion explosion; public BlockExplodedCallbackJS(Level level, BlockPos pos, Explosion explosion) { - this.level = level; - this.block = new BlockContainerJS(level, pos); - this.state = level.getBlockState(pos); + this.block = level.kjs$getBlock(pos); this.explosion = explosion; } public Level getLevel() { - return level; + return block.getLevel(); } - public BlockContainerJS getBlock() { + public LevelBlock getBlock() { return block; } public BlockState getBlockState() { - return state; + return block.getBlockState(); } public Explosion getExplosion() { diff --git a/src/main/java/dev/latvian/mods/kubejs/block/callbacks/BlockStateModifyPlacementCallbackJS.java b/src/main/java/dev/latvian/mods/kubejs/block/callbacks/BlockStateModifyPlacementCallbackJS.java index f6e8bcd10..bf20a7300 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/callbacks/BlockStateModifyPlacementCallbackJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/callbacks/BlockStateModifyPlacementCallbackJS.java @@ -1,6 +1,6 @@ package dev.latvian.mods.kubejs.block.callbacks; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.kubejs.typings.Info; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -21,13 +21,13 @@ public class BlockStateModifyPlacementCallbackJS extends BlockStateModifyCallbackJS { public final BlockPlaceContext context; public final Block minecraftBlock; - public BlockContainerJS block; + public LevelBlock block; public BlockStateModifyPlacementCallbackJS(BlockPlaceContext context, Block block) { super(getBlockStateToModify(context, block)); this.context = context; this.minecraftBlock = block; - this.block = new BlockContainerJS(context.getLevel(), context.getClickedPos()); + this.block = context.getLevel().kjs$getBlock(context.getClickedPos()); } private static BlockState getBlockStateToModify(BlockPlaceContext context, Block block) { @@ -44,8 +44,8 @@ public BlockPos getClickedPos() { } @Info("Gets the clicked block") - public BlockContainerJS getClickedBlock() { - return new BlockContainerJS(getLevel(), getClickedPos()); + public LevelBlock getClickedBlock() { + return getLevel().kjs$getBlock(getClickedPos()); } @Info("Returns if the block being placed thinks it can be placed here. This is used for replacement checks, like placing blocks in water or tall grass") diff --git a/src/main/java/dev/latvian/mods/kubejs/block/callbacks/CanBeReplacedCallbackJS.java b/src/main/java/dev/latvian/mods/kubejs/block/callbacks/CanBeReplacedCallbackJS.java index 83f7c60d6..4fa6dc145 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/callbacks/CanBeReplacedCallbackJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/callbacks/CanBeReplacedCallbackJS.java @@ -1,6 +1,6 @@ package dev.latvian.mods.kubejs.block.callbacks; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.InteractionHand; @@ -26,8 +26,8 @@ public BlockPos getClickedPos() { return context.getClickedPos(); } - public BlockContainerJS getClickedBlock() { - return new BlockContainerJS(getLevel(), getClickedPos()); + public LevelBlock getClickedBlock() { + return getLevel().kjs$getBlock(getClickedPos()); } public Direction getNearestLookingDirection() { diff --git a/src/main/java/dev/latvian/mods/kubejs/block/callbacks/EntitySteppedOnBlockCallbackJS.java b/src/main/java/dev/latvian/mods/kubejs/block/callbacks/EntitySteppedOnBlockCallbackJS.java index 69d6a151b..d1c5be94b 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/callbacks/EntitySteppedOnBlockCallbackJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/callbacks/EntitySteppedOnBlockCallbackJS.java @@ -1,6 +1,6 @@ package dev.latvian.mods.kubejs.block.callbacks; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.kubejs.typings.Info; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; @@ -10,13 +10,13 @@ public class EntitySteppedOnBlockCallbackJS { protected final Level level; protected final Entity entity; - protected final BlockContainerJS block; + protected final LevelBlock block; protected final BlockState state; public EntitySteppedOnBlockCallbackJS(Level level, Entity entity, BlockPos pos, BlockState state) { this.level = level; this.entity = entity; - this.block = new BlockContainerJS(level, pos); + this.block = level.kjs$getBlock(pos); this.state = state; } @@ -31,7 +31,7 @@ public Entity getEntity() { } @Info("Returns the block") - public BlockContainerJS getBlock() { + public LevelBlock getBlock() { return block; } diff --git a/src/main/java/dev/latvian/mods/kubejs/block/custom/BasicBlockJS.java b/src/main/java/dev/latvian/mods/kubejs/block/custom/BasicBlockJS.java index ab5b7d6c4..99665c55e 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/custom/BasicBlockJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/custom/BasicBlockJS.java @@ -14,7 +14,6 @@ import dev.latvian.mods.kubejs.block.callbacks.EntityFallenOnBlockCallbackJS; import dev.latvian.mods.kubejs.block.callbacks.EntitySteppedOnBlockCallbackJS; import dev.latvian.mods.kubejs.block.entity.KubeBlockEntity; -import dev.latvian.mods.kubejs.level.BlockContainerJS; import dev.latvian.mods.kubejs.script.ScriptType; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -178,7 +177,7 @@ public boolean propagatesSkylightDown(BlockState state, BlockGetter level, Block @Deprecated public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { if (blockBuilder.randomTickCallback != null) { - var callback = new RandomTickCallbackJS(new BlockContainerJS(level, pos), random); + var callback = new RandomTickCallbackJS(level.kjs$getBlock(pos), random); safeCallback(blockBuilder.randomTickCallback, callback, "Error while random ticking custom block "); } } diff --git a/src/main/java/dev/latvian/mods/kubejs/block/custom/BasicCropBlockJS.java b/src/main/java/dev/latvian/mods/kubejs/block/custom/BasicCropBlockJS.java index afe5305ce..9262fc701 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/custom/BasicCropBlockJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/custom/BasicCropBlockJS.java @@ -2,7 +2,6 @@ import dev.latvian.mods.kubejs.block.KubeJSBlockProperties; import dev.latvian.mods.kubejs.block.RandomTickCallbackJS; -import dev.latvian.mods.kubejs.level.BlockContainerJS; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; @@ -60,7 +59,7 @@ public VoxelShape getShape(BlockState blockState, BlockGetter blockGetter, Block @Override public void randomTick(BlockState blockState, ServerLevel serverLevel, BlockPos blockPos, RandomSource random) { - double f = builder.growSpeedCallback == null ? -1 : builder.growSpeedCallback.applyAsDouble(new RandomTickCallbackJS(new BlockContainerJS(serverLevel, blockPos), random)); + double f = builder.growSpeedCallback == null ? -1 : builder.growSpeedCallback.applyAsDouble(new RandomTickCallbackJS(serverLevel.kjs$getBlock(blockPos).cache(blockState), random)); int age = this.getAge(blockState); if (age < this.getMaxAge()) { if (f < 0) { @@ -77,7 +76,7 @@ public void growCrops(Level level, BlockPos blockPos, BlockState blockState) { if (builder.fertilizerCallback == null) { super.growCrops(level, blockPos, blockState); } else { - int effect = builder.fertilizerCallback.applyAsInt(new RandomTickCallbackJS(new BlockContainerJS(level, blockPos), level.random)); + int effect = builder.fertilizerCallback.applyAsInt(new RandomTickCallbackJS(level.kjs$getBlock(blockPos).cache(blockState), level.random)); if (effect > 0) { level.setBlock(blockPos, this.getStateForAge(Integer.min(getAge(blockState) + effect, getMaxAge())), 2); } diff --git a/src/main/java/dev/latvian/mods/kubejs/block/entity/BlockEntityTickKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/block/entity/BlockEntityTickKubeEvent.java index 28a2fa6ca..45ad2df49 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/entity/BlockEntityTickKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/entity/BlockEntityTickKubeEvent.java @@ -1,7 +1,7 @@ package dev.latvian.mods.kubejs.block.entity; -import dev.latvian.mods.kubejs.level.BlockContainerJS; import dev.latvian.mods.kubejs.level.KubeLevelEvent; +import dev.latvian.mods.kubejs.level.LevelBlock; import net.minecraft.world.level.Level; public class BlockEntityTickKubeEvent implements KubeLevelEvent { @@ -16,7 +16,7 @@ public Level getLevel() { return entity.getLevel(); } - public BlockContainerJS getBlock() { + public LevelBlock getBlock() { return entity.getBlock(); } diff --git a/src/main/java/dev/latvian/mods/kubejs/block/entity/KubeBlockEntity.java b/src/main/java/dev/latvian/mods/kubejs/block/entity/KubeBlockEntity.java index 8a644e4db..8c4e253a3 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/entity/KubeBlockEntity.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/entity/KubeBlockEntity.java @@ -1,7 +1,7 @@ package dev.latvian.mods.kubejs.block.entity; import dev.latvian.mods.kubejs.bindings.event.BlockEvents; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import net.minecraft.core.BlockPos; import net.minecraft.core.HolderLookup; import net.minecraft.nbt.CompoundTag; @@ -26,7 +26,7 @@ public class KubeBlockEntity extends BlockEntity { public final BlockEntityInfo info; public final ResourceKey blockKey; - protected BlockContainerJS block; + protected LevelBlock block; public final int x, y, z; public int tick, cycle; public CompoundTag data; @@ -182,11 +182,9 @@ public boolean triggerEvent(int eventId, int data) { return false; } - public BlockContainerJS getBlock() { + public LevelBlock getBlock() { if (block == null) { - this.block = new BlockContainerJS(level, worldPosition); - this.block.cachedEntity = this; - this.block.cachedState = getBlockState(); + this.block = level.kjs$getBlock(worldPosition).cache(this).cache(getBlockState()); } return block; diff --git a/src/main/java/dev/latvian/mods/kubejs/block/predicate/BlockEntityPredicate.java b/src/main/java/dev/latvian/mods/kubejs/block/predicate/BlockEntityPredicate.java index 570757b84..9dd66835e 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/predicate/BlockEntityPredicate.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/predicate/BlockEntityPredicate.java @@ -1,6 +1,6 @@ package dev.latvian.mods.kubejs.block.predicate; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; @@ -18,7 +18,7 @@ public BlockEntityPredicate data(BlockEntityPredicateDataCheck cd) { } @Override - public boolean check(BlockContainerJS block) { + public boolean check(LevelBlock block) { var tileEntity = block.getEntity(); return tileEntity != null && id.equals(BuiltInRegistries.BLOCK_ENTITY_TYPE.getKey(tileEntity.getType())) && (checkData == null || checkData.checkData(block.getEntityData())); } diff --git a/src/main/java/dev/latvian/mods/kubejs/block/predicate/BlockIDPredicate.java b/src/main/java/dev/latvian/mods/kubejs/block/predicate/BlockIDPredicate.java index 2c65c614b..0105b5aa1 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/predicate/BlockIDPredicate.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/predicate/BlockIDPredicate.java @@ -1,6 +1,6 @@ package dev.latvian.mods.kubejs.block.predicate; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.kubejs.util.Cast; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; @@ -113,7 +113,7 @@ public BlockState getBlockState() { } @Override - public boolean check(BlockContainerJS b) { + public boolean check(LevelBlock b) { return getBlock() != Blocks.AIR && checkState(b.getBlockState()); } diff --git a/src/main/java/dev/latvian/mods/kubejs/block/predicate/BlockPredicate.java b/src/main/java/dev/latvian/mods/kubejs/block/predicate/BlockPredicate.java index fd8fe33c1..403bbaae2 100644 --- a/src/main/java/dev/latvian/mods/kubejs/block/predicate/BlockPredicate.java +++ b/src/main/java/dev/latvian/mods/kubejs/block/predicate/BlockPredicate.java @@ -1,7 +1,7 @@ package dev.latvian.mods.kubejs.block.predicate; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; public interface BlockPredicate { - boolean check(BlockContainerJS block); + boolean check(LevelBlock block); } \ No newline at end of file diff --git a/src/main/java/dev/latvian/mods/kubejs/core/BlockBehaviourKJS.java b/src/main/java/dev/latvian/mods/kubejs/core/BlockBehaviourKJS.java index 4a4bb8208..69d9c41a6 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/BlockBehaviourKJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/BlockBehaviourKJS.java @@ -1,16 +1,13 @@ package dev.latvian.mods.kubejs.core; import dev.latvian.mods.kubejs.block.RandomTickCallbackJS; +import dev.latvian.mods.rhino.util.RemapPrefixForJS; import net.minecraft.world.level.block.SoundType; -import java.util.Map; import java.util.function.Consumer; -public interface BlockBehaviourKJS { - default Map kjs$getTypeData() { - throw new NoMixinException(); - } - +@RemapPrefixForJS("kjs$") +public interface BlockBehaviourKJS extends BlockProviderKJS { default void kjs$setHasCollision(boolean v) { throw new NoMixinException(); } diff --git a/src/main/java/dev/latvian/mods/kubejs/core/BlockKJS.java b/src/main/java/dev/latvian/mods/kubejs/core/BlockKJS.java index 94c49b15a..9334f0b47 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/BlockKJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/BlockKJS.java @@ -5,25 +5,16 @@ import dev.latvian.mods.kubejs.recipe.match.Replaceable; import dev.latvian.mods.rhino.Context; import dev.latvian.mods.rhino.util.RemapPrefixForJS; -import net.minecraft.core.Registry; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import java.util.List; @RemapPrefixForJS("kjs$") -public interface BlockKJS extends BlockBuilderProvider, RegistryObjectKJS, Replaceable { +public interface BlockKJS extends BlockBuilderProvider, BlockBehaviourKJS, Replaceable { @Override - default ResourceKey> kjs$getRegistryId() { - return Registries.BLOCK; - } - - @Override - default Registry kjs$getRegistry() { - return BuiltInRegistries.BLOCK; + default Block kjs$getBlock() { + return (Block) this; } default void kjs$setBlockBuilder(BlockBuilder b) { @@ -53,7 +44,7 @@ public interface BlockKJS extends BlockBuilderProvider, RegistryObjectKJS } default List kjs$getBlockStates() { - return this instanceof Block block ? block.getStateDefinition().getPossibleStates() : List.of(); + return kjs$getBlock().getStateDefinition().getPossibleStates(); } @Override diff --git a/src/main/java/dev/latvian/mods/kubejs/core/BlockProviderKJS.java b/src/main/java/dev/latvian/mods/kubejs/core/BlockProviderKJS.java new file mode 100644 index 000000000..875655f63 --- /dev/null +++ b/src/main/java/dev/latvian/mods/kubejs/core/BlockProviderKJS.java @@ -0,0 +1,45 @@ +package dev.latvian.mods.kubejs.core; + +import dev.latvian.mods.rhino.util.RemapPrefixForJS; +import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.block.Block; + +import java.util.Map; + +@RemapPrefixForJS("kjs$") +public interface BlockProviderKJS extends RegistryObjectKJS { + Block kjs$getBlock(); + + @Override + default ResourceKey> kjs$getRegistryId() { + return Registries.BLOCK; + } + + @Override + default Registry kjs$getRegistry() { + return BuiltInRegistries.BLOCK; + } + + @Override + default Holder kjs$asHolder() { + return kjs$getBlock().builtInRegistryHolder(); + } + + @Override + default ResourceKey kjs$getKey() { + return kjs$getBlock().builtInRegistryHolder().key(); + } + + @Override + default String kjs$getId() { + return kjs$getBlock().kjs$getId(); + } + + default Map kjs$getTypeData() { + return kjs$getBlock().kjs$getTypeData(); + } +} diff --git a/src/main/java/dev/latvian/mods/kubejs/core/ClientLevelKJS.java b/src/main/java/dev/latvian/mods/kubejs/core/ClientLevelKJS.java index 2ea1b0df7..3f865ef30 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/ClientLevelKJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/ClientLevelKJS.java @@ -1,12 +1,9 @@ package dev.latvian.mods.kubejs.core; import dev.latvian.mods.kubejs.client.KubeAnimatedParticle; -import dev.latvian.mods.kubejs.player.EntityArrayList; -import dev.latvian.mods.kubejs.script.ScriptType; import dev.latvian.mods.rhino.util.RemapPrefixForJS; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.particle.SpriteSet; -import net.minecraft.core.particles.ParticleOptions; @RemapPrefixForJS("kjs$") public interface ClientLevelKJS extends LevelKJS { @@ -15,47 +12,6 @@ public interface ClientLevelKJS extends LevelKJS { return (ClientLevel) this; } - @Override - default ScriptType kjs$getScriptType() { - return ScriptType.CLIENT; - } - - @Override - default EntityArrayList kjs$getEntities() { - return new EntityArrayList(kjs$self(), kjs$self().entitiesForRendering()); - } - - @Override - default void kjs$spawnParticles(ParticleOptions options, boolean overrideLimiter, double x, double y, double z, double vx, double vy, double vz, int count, double speed) { - if (count == 0) { - double d0 = speed * vx; - double d2 = speed * vy; - double d4 = speed * vz; - - try { - kjs$self().addParticle(options, overrideLimiter, x, y, z, d0, d2, d4); - } catch (Throwable var17) { - } - } else { - var random = kjs$self().random; - - for (int i = 0; i < count; ++i) { - double ox = random.nextGaussian() * vx; - double oy = random.nextGaussian() * vy; - double oz = random.nextGaussian() * vz; - double d6 = random.nextGaussian() * speed; - double d7 = random.nextGaussian() * speed; - double d8 = random.nextGaussian() * speed; - - try { - kjs$self().addParticle(options, overrideLimiter, x + ox, y + oy, z + oz, d6, d7, d8); - } catch (Throwable var16) { - return; - } - } - } - } - default KubeAnimatedParticle kubeParticle(double x, double y, double z, SpriteSet spriteSet) { return new KubeAnimatedParticle(kjs$self(), x, y, z, spriteSet); } diff --git a/src/main/java/dev/latvian/mods/kubejs/core/ContainerKJS.java b/src/main/java/dev/latvian/mods/kubejs/core/ContainerKJS.java index b4ab536e5..10cebb11e 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/ContainerKJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/ContainerKJS.java @@ -1,6 +1,6 @@ package dev.latvian.mods.kubejs.core; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.rhino.util.RemapPrefixForJS; import net.minecraft.world.Container; import net.minecraft.world.entity.player.Inventory; @@ -178,7 +178,7 @@ public interface ContainerKJS extends InventoryKJS { } @Override - default @Nullable BlockContainerJS kjs$getBlock(Level level) { + default @Nullable LevelBlock kjs$getBlock(Level level) { if (kjs$self() instanceof BlockEntity be) { return level.kjs$getBlock(be); } diff --git a/src/main/java/dev/latvian/mods/kubejs/core/EntityCollectionKJS.java b/src/main/java/dev/latvian/mods/kubejs/core/EntityCollectionKJS.java new file mode 100644 index 000000000..a7a1a309f --- /dev/null +++ b/src/main/java/dev/latvian/mods/kubejs/core/EntityCollectionKJS.java @@ -0,0 +1,75 @@ +package dev.latvian.mods.kubejs.core; + +import dev.latvian.mods.kubejs.player.EntityArrayList; +import dev.latvian.mods.rhino.util.RemapPrefixForJS; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.AABB; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@RemapPrefixForJS("kjs$") +public interface EntityCollectionKJS { + Iterable kjs$getMcEntities(); + + default List kjs$getMcPlayers() { + var list = new ArrayList(10); + + for (var entity : kjs$getMcEntities()) { + if (entity instanceof Player p) { + list.add(p); + } + } + + return list; + } + + default EntityArrayList kjs$getPlayers() { + return new EntityArrayList(kjs$getMcPlayers()); + } + + default EntityArrayList kjs$getEntities() { + return new EntityArrayList(kjs$getMcEntities()); + } + + default EntityArrayList kjs$getEntitiesWithin(AABB aabb) { + if (aabb == null || aabb == AABB.INFINITE) { + return kjs$getEntities(); + } + + var list = new EntityArrayList(10); + + for (var entity : kjs$getMcEntities()) { + if (entity.getBoundingBox().intersects(aabb)) { + list.add(entity); + } + } + + return list; + } + + @Nullable + default Entity kjs$getEntityByUUID(UUID id) { + for (var entity : kjs$getMcEntities()) { + if (entity.getUUID().equals(id)) { + return entity; + } + } + + return null; + } + + @Nullable + default Entity kjs$getEntityByNetworkID(int id) { + for (var entity : kjs$getMcEntities()) { + if (entity.getId() == id) { + return entity; + } + } + + return null; + } +} diff --git a/src/main/java/dev/latvian/mods/kubejs/core/EntityGetterKJS.java b/src/main/java/dev/latvian/mods/kubejs/core/EntityGetterKJS.java new file mode 100644 index 000000000..8a995aa99 --- /dev/null +++ b/src/main/java/dev/latvian/mods/kubejs/core/EntityGetterKJS.java @@ -0,0 +1,37 @@ +package dev.latvian.mods.kubejs.core; + +import dev.latvian.mods.kubejs.player.EntityArrayList; +import dev.latvian.mods.rhino.util.RemapPrefixForJS; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.EntityGetter; +import net.minecraft.world.phys.AABB; + +import java.util.List; + +@RemapPrefixForJS("kjs$") +public interface EntityGetterKJS extends EntityCollectionKJS { + default EntityGetter kjs$self() { + return (EntityGetter) this; + } + + @Override + default List kjs$getMcPlayers() { + return kjs$self().players(); + } + + @Override + default EntityArrayList kjs$getPlayers() { + return new EntityArrayList(kjs$self().players()); + } + + @Override + default Iterable kjs$getMcEntities() { + return kjs$self().getEntities((Entity) null, AABB.INFINITE, EntityArrayList.ALWAYS_TRUE_PREDICATE); + } + + @Override + default EntityArrayList kjs$getEntitiesWithin(AABB aabb) { + return new EntityArrayList(kjs$self().getEntities(null, aabb)); + } +} diff --git a/src/main/java/dev/latvian/mods/kubejs/core/EntityKJS.java b/src/main/java/dev/latvian/mods/kubejs/core/EntityKJS.java index ffacc73ec..6e23d5a72 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/EntityKJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/EntityKJS.java @@ -3,7 +3,7 @@ import com.mojang.authlib.GameProfile; import com.mojang.brigadier.exceptions.CommandSyntaxException; import dev.latvian.mods.kubejs.entity.RayTraceResultJS; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.kubejs.player.EntityArrayList; import dev.latvian.mods.kubejs.script.ScriptType; import dev.latvian.mods.kubejs.script.ScriptTypeHolder; @@ -200,7 +200,7 @@ public interface EntityKJS extends WithPersistentData, MessageSenderKJS, ScriptT } } - default void kjs$setPosition(BlockContainerJS block) { + default void kjs$setPosition(LevelBlock block) { kjs$teleportTo(block.getDimension(), block.getX(), block.getY(), block.getZ(), kjs$self().getYRot(), kjs$self().getXRot()); } @@ -217,7 +217,7 @@ public interface EntityKJS extends WithPersistentData, MessageSenderKJS, ScriptT } default EntityArrayList kjs$getPassengers() { - return new EntityArrayList(kjs$getLevel(), kjs$self().getPassengers()); + return new EntityArrayList(kjs$self().getPassengers()); } default String kjs$getTeamId() { @@ -240,8 +240,8 @@ public interface EntityKJS extends WithPersistentData, MessageSenderKJS, ScriptT return kjs$self().getDirection(); } - default BlockContainerJS kjs$getBlock() { - return new BlockContainerJS(kjs$getLevel(), kjs$self().blockPosition()); + default LevelBlock kjs$getBlock() { + return kjs$getLevel().kjs$getBlock(kjs$self().blockPosition()); } default CompoundTag kjs$getNbt() { diff --git a/src/main/java/dev/latvian/mods/kubejs/core/FluidStackKJS.java b/src/main/java/dev/latvian/mods/kubejs/core/FluidStackKJS.java index 4bd263a68..5cb212387 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/FluidStackKJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/FluidStackKJS.java @@ -43,6 +43,8 @@ public interface FluidStackKJS extends default boolean specialEquals(Context cx, Object o, boolean shallow) { if (o instanceof CharSequence) { return kjs$getId().equals(ID.string(o.toString())); + } else if (o instanceof ResourceLocation) { + return kjs$getIdLocation().equals(o); } else if (o instanceof FluidStack s) { return kjs$equalsIgnoringCount(s); } diff --git a/src/main/java/dev/latvian/mods/kubejs/core/InventoryKJS.java b/src/main/java/dev/latvian/mods/kubejs/core/InventoryKJS.java index f9b20783e..6eadb6aab 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/InventoryKJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/InventoryKJS.java @@ -1,7 +1,7 @@ package dev.latvian.mods.kubejs.core; import dev.latvian.mods.kubejs.item.ItemPredicate; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.rhino.util.RemapPrefixForJS; import net.minecraft.world.Container; import net.minecraft.world.item.ItemStack; @@ -194,7 +194,7 @@ public interface InventoryKJS { } @Nullable - default BlockContainerJS kjs$getBlock(Level level) { + default LevelBlock kjs$getBlock(Level level) { return null; } diff --git a/src/main/java/dev/latvian/mods/kubejs/core/ItemStackKJS.java b/src/main/java/dev/latvian/mods/kubejs/core/ItemStackKJS.java index a4c011819..bbe74341d 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/ItemStackKJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/ItemStackKJS.java @@ -5,7 +5,7 @@ import dev.latvian.mods.kubejs.component.DataComponentWrapper; import dev.latvian.mods.kubejs.component.ItemComponentFunctions; import dev.latvian.mods.kubejs.item.ItemStackJS; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.kubejs.recipe.match.ItemMatch; import dev.latvian.mods.kubejs.recipe.match.Replaceable; import dev.latvian.mods.kubejs.util.Cast; @@ -66,6 +66,8 @@ public interface ItemStackKJS extends default boolean specialEquals(Context cx, Object o, boolean shallow) { if (o instanceof CharSequence) { return kjs$getId().equals(ID.string(o.toString())); + } else if (o instanceof ResourceLocation) { + return kjs$getIdLocation().equals(o); } else if (o instanceof ItemStack s) { return kjs$equalsIgnoringCount(s); } @@ -185,7 +187,7 @@ default boolean specialEquals(Context cx, Object o, boolean shallow) { return ItemStack.isSameItemSameComponents(kjs$self(), other); } - default float kjs$getHarvestSpeed(@Nullable BlockContainerJS block) { + default float kjs$getHarvestSpeed(@Nullable LevelBlock block) { return kjs$self().getDestroySpeed(block == null ? Blocks.AIR.defaultBlockState() : block.getBlockState()); } diff --git a/src/main/java/dev/latvian/mods/kubejs/core/LevelKJS.java b/src/main/java/dev/latvian/mods/kubejs/core/LevelKJS.java index c99b7550d..6023e53d2 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/LevelKJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/LevelKJS.java @@ -1,8 +1,8 @@ package dev.latvian.mods.kubejs.core; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.CachedLevelBlock; import dev.latvian.mods.kubejs.level.ExplosionJS; -import dev.latvian.mods.kubejs.player.EntityArrayList; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.kubejs.script.ScriptType; import dev.latvian.mods.kubejs.script.ScriptTypeHolder; import dev.latvian.mods.rhino.util.RemapForJS; @@ -12,6 +12,7 @@ import net.minecraft.core.particles.ParticleOptions; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.projectile.FireworkRocketEntity; @@ -20,14 +21,14 @@ import net.minecraft.world.item.component.Fireworks; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.phys.AABB; +import net.minecraft.world.level.storage.ServerLevelData; import org.jetbrains.annotations.Nullable; -import java.util.Collection; -import java.util.UUID; +import java.util.function.Consumer; @RemapPrefixForJS("kjs$") -public interface LevelKJS extends WithAttachedData, ScriptTypeHolder { +public interface LevelKJS extends WithAttachedData, ScriptTypeHolder, EntityGetterKJS { + @Override default Level kjs$self() { return (Level) this; } @@ -35,7 +36,7 @@ public interface LevelKJS extends WithAttachedData, ScriptTypeHolder { @Override @RemapForJS("getSide") default ScriptType kjs$getScriptType() { - throw new NoMixinException(); + return kjs$self().isClientSide() ? ScriptType.CLIENT : ScriptType.SERVER; } @Override @@ -86,28 +87,22 @@ public interface LevelKJS extends WithAttachedData, ScriptTypeHolder { return kjs$self().dimension() == Level.OVERWORLD; } - default BlockContainerJS kjs$getBlock(int x, int y, int z) { - return kjs$getBlock(new BlockPos(x, y, z)); - } - - default BlockContainerJS kjs$getBlock(BlockPos pos) { - return new BlockContainerJS(kjs$self(), pos); - } - - default BlockContainerJS kjs$getBlock(BlockEntity blockEntity) { - return new BlockContainerJS(blockEntity); + default void kjs$setTime(long time) { + if (kjs$self().getLevelData() instanceof ServerLevelData d) { + d.setGameTime(time); + } } - default EntityArrayList kjs$createEntityList(Collection entities) { - return new EntityArrayList(kjs$self(), entities); + default LevelBlock kjs$getBlock(int x, int y, int z) { + return kjs$getBlock(new BlockPos(x, y, z)); } - default EntityArrayList kjs$getPlayers() { - return kjs$createEntityList(kjs$self().players()); + default LevelBlock kjs$getBlock(BlockPos pos) { + return new CachedLevelBlock(kjs$self(), pos); } - default EntityArrayList kjs$getEntities() { - return new EntityArrayList(kjs$self(), 0); + default LevelBlock kjs$getBlock(BlockEntity entity) { + return new CachedLevelBlock(entity.getLevel(), entity.getBlockPos()).cache(entity).cache(entity.getBlockState()); } default ExplosionJS kjs$createExplosion(double x, double y, double z) { @@ -119,9 +114,18 @@ public interface LevelKJS extends WithAttachedData, ScriptTypeHolder { return type.create(kjs$self()); } - default void kjs$spawnFireworks(double x, double y, double z, Fireworks f, int lifetime) { + default void spawnEntity(EntityType type, Consumer callback) { + var entity = type.create(kjs$self()); + + if (entity != null) { + callback.accept(entity); + kjs$self().addFreshEntity(entity); + } + } + + default void kjs$spawnFireworks(double x, double y, double z, Fireworks fireworks, int lifetime) { var stack = new ItemStack(Items.FIREWORK_ROCKET); - stack.set(DataComponents.FIREWORKS, f); + stack.set(DataComponents.FIREWORKS, fireworks); var rocket = new FireworkRocketEntity(kjs$self(), x, y, z, stack); @@ -133,21 +137,47 @@ public interface LevelKJS extends WithAttachedData, ScriptTypeHolder { kjs$self().addFreshEntity(rocket); } - default EntityArrayList kjs$getEntitiesWithin(AABB aabb) { - return new EntityArrayList(kjs$self(), kjs$self().getEntities(null, aabb)); - } - default void kjs$spawnParticles(ParticleOptions options, boolean overrideLimiter, double x, double y, double z, double vx, double vy, double vz, int count, double speed) { - } + var level = kjs$self(); - @Nullable - default Entity kjs$getEntityByUUID(UUID id) { - for (var entity : kjs$getEntities()) { - if (entity.getUUID().equals(id)) { - return entity; + if (count == 0) { + double d0 = speed * vx; + double d2 = speed * vy; + double d4 = speed * vz; + + try { + level.addParticle(options, overrideLimiter, x, y, z, d0, d2, d4); + } catch (Throwable var17) { + } + } else { + var random = level.random; + + for (int i = 0; i < count; ++i) { + double ox = random.nextGaussian() * vx; + double oy = random.nextGaussian() * vy; + double oz = random.nextGaussian() * vz; + double d6 = random.nextGaussian() * speed; + double d7 = random.nextGaussian() * speed; + double d8 = random.nextGaussian() * speed; + + try { + level.addParticle(options, overrideLimiter, x + ox, y + oy, z + oz, d6, d7, d8); + } catch (Throwable var16) { + return; + } } } + } + + default void kjs$spawnLightning(double x, double y, double z, boolean visualOnly, @Nullable ServerPlayer cause) { + var e = EntityType.LIGHTNING_BOLT.create(kjs$self()); + e.moveTo(x, y, z); + e.setCause(cause); + e.setVisualOnly(visualOnly); + kjs$self().addFreshEntity(e); + } - return null; + default void kjs$spawnLightning(double x, double y, double z, boolean visualOnly) { + kjs$spawnLightning(x, y, z, visualOnly, null); } } diff --git a/src/main/java/dev/latvian/mods/kubejs/core/MinecraftServerKJS.java b/src/main/java/dev/latvian/mods/kubejs/core/MinecraftServerKJS.java index dd096b88d..73aca5372 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/MinecraftServerKJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/MinecraftServerKJS.java @@ -19,15 +19,20 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.network.PacketDistributor; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.UUID; @RemapPrefixForJS("kjs$") -public interface MinecraftServerKJS extends WithAttachedData, WithPersistentData, DataSenderKJS, MinecraftEnvironmentKJS { +public interface MinecraftServerKJS extends WithAttachedData, WithPersistentData, DataSenderKJS, MinecraftEnvironmentKJS, EntityCollectionKJS { default MinecraftServer kjs$self() { return (MinecraftServer) this; } @@ -81,18 +86,61 @@ public interface MinecraftServerKJS extends WithAttachedData, W return selector.getPlayer(kjs$self()); } + @Override + default Iterable kjs$getMcEntities() { + var list = new ArrayList(10); + + for (var level : kjs$self().getAllLevels()) { + var i = level.getAllEntities(); + + if (i instanceof Collection c) { + list.addAll(c); + } else { + for (var e : i) { + list.add(e); + } + } + } + + return list; + } + + @Override + default List kjs$getMcPlayers() { + return kjs$self().getPlayerList().getPlayers(); + } + + @Override default EntityArrayList kjs$getPlayers() { - return new EntityArrayList(kjs$self().overworld(), kjs$self().getPlayerList().getPlayers()); + return new EntityArrayList(kjs$self().getPlayerList().getPlayers()); } - default EntityArrayList kjs$getEntities() { - var list = new EntityArrayList(kjs$self().overworld(), 10); + @Override + @Nullable + default Entity kjs$getEntityByUUID(UUID id) { + for (var level : kjs$self().getAllLevels()) { + var e = level.getEntities().get(id); + + if (e != null) { + return e; + } + } + + return null; + } + @Override + @Nullable + default Entity kjs$getEntityByNetworkID(int id) { for (var level : kjs$self().getAllLevels()) { - list.addAllIterable(level.getAllEntities()); + var e = level.getEntities().get(id); + + if (e != null) { + return e; + } } - return list; + return null; } @Nullable diff --git a/src/main/java/dev/latvian/mods/kubejs/core/RegistryObjectKJS.java b/src/main/java/dev/latvian/mods/kubejs/core/RegistryObjectKJS.java index 7e69901cc..327d85c91 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/RegistryObjectKJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/RegistryObjectKJS.java @@ -1,17 +1,30 @@ package dev.latvian.mods.kubejs.core; import dev.latvian.mods.kubejs.util.RegistryAccessContainer; +import dev.latvian.mods.rhino.Context; import dev.latvian.mods.rhino.util.RemapPrefixForJS; +import dev.latvian.mods.rhino.util.SpecialEquality; import net.minecraft.core.Holder; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; -import java.util.Collection; +import java.util.List; @RemapPrefixForJS("kjs$") -public interface RegistryObjectKJS { +public interface RegistryObjectKJS extends SpecialEquality { + @Override + default boolean specialEquals(Context cx, Object o, boolean shallow) { + if (o instanceof CharSequence) { + return kjs$getId().equals(o.toString()); + } else if (o instanceof ResourceLocation) { + return kjs$getIdLocation().equals(o); + } + + return equals(o); + } + default ResourceKey> kjs$getRegistryId() { throw new NoMixinException(); } @@ -49,7 +62,11 @@ public interface RegistryObjectKJS { return kjs$getIdLocation().getNamespace(); } - default Collection kjs$getTags() { + default List> kjs$getTagKeys() { + return kjs$asHolder().tags().toList(); + } + + default List kjs$getTags() { return kjs$asHolder().tags().map(TagKey::location).toList(); } diff --git a/src/main/java/dev/latvian/mods/kubejs/core/ServerLevelKJS.java b/src/main/java/dev/latvian/mods/kubejs/core/ServerLevelKJS.java index fad017618..0462b51dc 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/ServerLevelKJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/ServerLevelKJS.java @@ -1,14 +1,8 @@ package dev.latvian.mods.kubejs.core; -import dev.latvian.mods.kubejs.player.EntityArrayList; -import dev.latvian.mods.kubejs.script.ScriptType; import dev.latvian.mods.rhino.util.RemapPrefixForJS; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.storage.ServerLevelData; -import org.jetbrains.annotations.Nullable; @RemapPrefixForJS("kjs$") public interface ServerLevelKJS extends LevelKJS, WithPersistentData { @@ -17,32 +11,6 @@ public interface ServerLevelKJS extends LevelKJS, WithPersistentData { return (ServerLevel) this; } - @Override - default ScriptType kjs$getScriptType() { - return ScriptType.SERVER; - } - - @Override - default EntityArrayList kjs$getEntities() { - return new EntityArrayList(kjs$self(), kjs$self().getAllEntities()); - } - - default void kjs$spawnLightning(double x, double y, double z, boolean effectOnly, @Nullable ServerPlayer player) { - var e = EntityType.LIGHTNING_BOLT.create(kjs$self()); - e.moveTo(x, y, z); - e.setCause(player); - e.setVisualOnly(effectOnly); - kjs$self().addFreshEntity(e); - } - - default void kjs$spawnLightning(double x, double y, double z, boolean effectOnly) { - kjs$spawnLightning(x, y, z, effectOnly, null); - } - - default void kjs$setTime(long time) { - ((ServerLevelData) kjs$self().getLevelData()).setGameTime(time); - } - @Override default void kjs$spawnParticles(ParticleOptions options, boolean overrideLimiter, double x, double y, double z, double vx, double vy, double vz, int count, double speed) { for (var player : kjs$self().players()) { diff --git a/src/main/java/dev/latvian/mods/kubejs/core/ServerPlayerKJS.java b/src/main/java/dev/latvian/mods/kubejs/core/ServerPlayerKJS.java index aa11c9d8d..ba23f5db8 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/ServerPlayerKJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/ServerPlayerKJS.java @@ -4,7 +4,7 @@ import dev.latvian.mods.kubejs.gui.KubeJSMenu; import dev.latvian.mods.kubejs.gui.chest.ChestMenuData; import dev.latvian.mods.kubejs.gui.chest.CustomChestMenu; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.kubejs.net.NotificationPayload; import dev.latvian.mods.kubejs.net.SendDataFromServerPayload; import dev.latvian.mods.kubejs.net.SetActivePostShaderPayload; @@ -139,13 +139,13 @@ public interface ServerPlayerKJS extends PlayerKJS { } @Nullable - default BlockContainerJS kjs$getSpawnLocation() { + default LevelBlock kjs$getSpawnLocation() { var pos = kjs$self().getRespawnPosition(); - return pos == null ? null : new BlockContainerJS(kjs$getLevel(), pos); + return pos == null ? null : kjs$getLevel().kjs$getBlock(pos); } - default void kjs$setSpawnLocation(BlockContainerJS c) { - kjs$self().setRespawnPosition(c.minecraftLevel.dimension(), c.getPos(), 0F, true, false); + default void kjs$setSpawnLocation(LevelBlock c) { + kjs$self().setRespawnPosition(c.getDimensionKey(), c.getPos(), 0F, true, false); } @Override diff --git a/src/main/java/dev/latvian/mods/kubejs/core/mixin/BlockBehaviourMixin.java b/src/main/java/dev/latvian/mods/kubejs/core/mixin/BlockBehaviourMixin.java index cef3cb26e..996570028 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/mixin/BlockBehaviourMixin.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/mixin/BlockBehaviourMixin.java @@ -2,7 +2,6 @@ import dev.latvian.mods.kubejs.block.RandomTickCallbackJS; import dev.latvian.mods.kubejs.core.BlockBehaviourKJS; -import dev.latvian.mods.kubejs.level.BlockContainerJS; import dev.latvian.mods.rhino.util.RemapPrefixForJS; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; @@ -18,28 +17,14 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.HashMap; -import java.util.Map; import java.util.function.Consumer; @Mixin(BlockBehaviour.class) @RemapPrefixForJS("kjs$") public abstract class BlockBehaviourMixin implements BlockBehaviourKJS { - @Unique - private Map kjs$typeData; - @Unique private Consumer kjs$randomTickCallback; - @Override - public Map kjs$getTypeData() { - if (kjs$typeData == null) { - kjs$typeData = new HashMap<>(); - } - - return kjs$typeData; - } - @Override public void kjs$setRandomTickCallback(Consumer callback) { kjs$setIsRandomlyTicking(true); @@ -49,7 +34,7 @@ public abstract class BlockBehaviourMixin implements BlockBehaviourKJS { @Inject(method = "randomTick", at = @At("HEAD"), cancellable = true) private void onRandomTick(BlockState blockState, ServerLevel serverLevel, BlockPos blockPos, RandomSource randomSource, CallbackInfo ci) { if (kjs$randomTickCallback != null) { - kjs$randomTickCallback.accept(new RandomTickCallbackJS(new BlockContainerJS(serverLevel, blockPos), randomSource)); + kjs$randomTickCallback.accept(new RandomTickCallbackJS(serverLevel.kjs$getBlock(blockPos).cache(blockState), randomSource)); ci.cancel(); } } diff --git a/src/main/java/dev/latvian/mods/kubejs/core/mixin/BlockMixin.java b/src/main/java/dev/latvian/mods/kubejs/core/mixin/BlockMixin.java index b2e61c65e..06e7b3ece 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/mixin/BlockMixin.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/mixin/BlockMixin.java @@ -3,49 +3,37 @@ import dev.latvian.mods.kubejs.block.BlockBuilder; import dev.latvian.mods.kubejs.core.BlockKJS; import dev.latvian.mods.rhino.util.RemapPrefixForJS; -import net.minecraft.core.Holder; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; -import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.block.Block; import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.HashMap; +import java.util.Map; + @Mixin(Block.class) @RemapPrefixForJS("kjs$") public abstract class BlockMixin implements BlockKJS { - @Shadow - @Final - private Holder.Reference builtInRegistryHolder; - @Unique private String kjs$id; @Unique private BlockBuilder kjs$blockBuilder; - @Override - public Holder.Reference kjs$asHolder() { - return builtInRegistryHolder; - } - - @Override - public ResourceKey kjs$getKey() { - return builtInRegistryHolder.key(); - } + @Unique + private Map kjs$typeData; @Override public String kjs$getId() { if (kjs$id == null) { - kjs$id = builtInRegistryHolder.key().location().toString(); + kjs$id = kjs$getBlock().builtInRegistryHolder().key().location().toString(); } return kjs$id; @@ -62,6 +50,15 @@ public abstract class BlockMixin implements BlockKJS { kjs$blockBuilder = b; } + @Override + public Map kjs$getTypeData() { + if (kjs$typeData == null) { + kjs$typeData = new HashMap<>(); + } + + return kjs$typeData; + } + @Override @Accessor("descriptionId") @Mutable diff --git a/src/main/java/dev/latvian/mods/kubejs/core/mixin/ClientLevelMixin.java b/src/main/java/dev/latvian/mods/kubejs/core/mixin/ClientLevelMixin.java index 1a8b29607..08e8e535e 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/mixin/ClientLevelMixin.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/mixin/ClientLevelMixin.java @@ -4,15 +4,11 @@ import dev.latvian.mods.rhino.util.HideFromJS; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.entity.LevelEntityGetter; -import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import java.util.List; -import java.util.UUID; @Mixin(ClientLevel.class) public abstract class ClientLevelMixin implements ClientLevelKJS { @@ -24,14 +20,4 @@ public abstract class ClientLevelMixin implements ClientLevelKJS { @Shadow @HideFromJS public abstract List players(); - - @Shadow - @HideFromJS - protected abstract LevelEntityGetter getEntities(); - - @Override - @Nullable - public Entity kjs$getEntityByUUID(UUID id) { - return getEntities().get(id); - } } diff --git a/src/main/java/dev/latvian/mods/kubejs/core/mixin/EntityGetterMixin.java b/src/main/java/dev/latvian/mods/kubejs/core/mixin/EntityGetterMixin.java new file mode 100644 index 000000000..5b126f78c --- /dev/null +++ b/src/main/java/dev/latvian/mods/kubejs/core/mixin/EntityGetterMixin.java @@ -0,0 +1,19 @@ +package dev.latvian.mods.kubejs.core.mixin; + +import dev.latvian.mods.kubejs.core.EntityGetterKJS; +import dev.latvian.mods.rhino.util.HideFromJS; +import dev.latvian.mods.rhino.util.RemapPrefixForJS; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.EntityGetter; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.List; + +@Mixin(EntityGetter.class) +@RemapPrefixForJS("kjs$") +public interface EntityGetterMixin extends EntityGetterKJS { + @Shadow + @HideFromJS + List players(); +} diff --git a/src/main/java/dev/latvian/mods/kubejs/core/mixin/IItemHandlerMixin.java b/src/main/java/dev/latvian/mods/kubejs/core/mixin/IItemHandlerMixin.java index 146600dbb..0c88c1421 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/mixin/IItemHandlerMixin.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/mixin/IItemHandlerMixin.java @@ -1,7 +1,7 @@ package dev.latvian.mods.kubejs.core.mixin; import dev.latvian.mods.kubejs.core.InventoryKJS; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; @@ -58,7 +58,7 @@ public interface IItemHandlerMixin extends InventoryKJS { boolean kjs$isItemValid(int i, ItemStack itemStack); @Override - default @Nullable BlockContainerJS kjs$getBlock(Level level) { + default @Nullable LevelBlock kjs$getBlock(Level level) { if (kjs$self() instanceof BlockEntity entity) { return level.kjs$getBlock(entity); } diff --git a/src/main/java/dev/latvian/mods/kubejs/core/mixin/LevelMixin.java b/src/main/java/dev/latvian/mods/kubejs/core/mixin/LevelMixin.java index c5b07e1f0..b1bd2badb 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/mixin/LevelMixin.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/mixin/LevelMixin.java @@ -4,14 +4,22 @@ import dev.latvian.mods.kubejs.plugin.KubeJSPlugin; import dev.latvian.mods.kubejs.plugin.KubeJSPlugins; import dev.latvian.mods.kubejs.util.AttachedData; +import dev.latvian.mods.rhino.util.HideFromJS; import dev.latvian.mods.rhino.util.RemapForJS; +import dev.latvian.mods.rhino.util.RemapPrefixForJS; import net.minecraft.resources.ResourceKey; +import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; +import net.minecraft.world.level.entity.LevelEntityGetter; +import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; +import java.util.UUID; + @Mixin(Level.class) +@RemapPrefixForJS("kjs$") public abstract class LevelMixin implements LevelKJS { @Unique private AttachedData kjs$attachedData; @@ -33,4 +41,25 @@ public abstract class LevelMixin implements LevelKJS { @Shadow @RemapForJS("getDimensionKey") public abstract ResourceKey dimension(); + + @Shadow + @HideFromJS + protected abstract LevelEntityGetter getEntities(); + + @Override + public Iterable kjs$getMcEntities() { + return getEntities().getAll(); + } + + @Override + @Nullable + public Entity kjs$getEntityByUUID(UUID id) { + return getEntities().get(id); + } + + @Override + @Nullable + public Entity kjs$getEntityByNetworkID(int id) { + return getEntities().get(id); + } } diff --git a/src/main/java/dev/latvian/mods/kubejs/core/mixin/ServerLevelMixin.java b/src/main/java/dev/latvian/mods/kubejs/core/mixin/ServerLevelMixin.java index 3c4062944..3ecb310f3 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/mixin/ServerLevelMixin.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/mixin/ServerLevelMixin.java @@ -2,12 +2,12 @@ import dev.latvian.mods.kubejs.core.ServerLevelKJS; import dev.latvian.mods.rhino.util.HideFromJS; +import dev.latvian.mods.rhino.util.RemapPrefixForJS; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.entity.LevelEntityGetter; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -17,12 +17,8 @@ import java.util.UUID; @Mixin(ServerLevel.class) +@RemapPrefixForJS("kjs$") public abstract class ServerLevelMixin implements ServerLevelKJS { - @Shadow - @Final - @HideFromJS - List players; - @Unique private CompoundTag kjs$persistentData; @@ -42,11 +38,11 @@ public abstract class ServerLevelMixin implements ServerLevelKJS { public abstract List players(); @Shadow + @Nullable @HideFromJS - public abstract LevelEntityGetter getEntities(); + public abstract Entity getEntity(UUID uniqueId); @Shadow - @Nullable @HideFromJS - public abstract Entity getEntity(UUID uniqueId); + public abstract LevelEntityGetter getEntities(); } diff --git a/src/main/java/dev/latvian/mods/kubejs/entity/CheckLivingEntitySpawnKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/entity/CheckLivingEntitySpawnKubeEvent.java index 296b60adf..8841a84fe 100644 --- a/src/main/java/dev/latvian/mods/kubejs/entity/CheckLivingEntitySpawnKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/entity/CheckLivingEntitySpawnKubeEvent.java @@ -1,7 +1,7 @@ package dev.latvian.mods.kubejs.entity; import com.mojang.datafixers.util.Either; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.kubejs.level.SpawnerJS; import dev.latvian.mods.kubejs.typings.Info; import net.minecraft.core.BlockPos; @@ -52,8 +52,8 @@ public LivingEntity getEntity() { } @Info("The block the entity is being spawned on.") - public BlockContainerJS getBlock() { - return new BlockContainerJS(level, BlockPos.containing(x, y, z)); + public LevelBlock getBlock() { + return level.kjs$getBlock(BlockPos.containing(x, y, z)); } @Info("The type of spawn.") diff --git a/src/main/java/dev/latvian/mods/kubejs/entity/RayTraceResultJS.java b/src/main/java/dev/latvian/mods/kubejs/entity/RayTraceResultJS.java index 3e5ec0dc7..83239547f 100644 --- a/src/main/java/dev/latvian/mods/kubejs/entity/RayTraceResultJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/entity/RayTraceResultJS.java @@ -1,6 +1,6 @@ package dev.latvian.mods.kubejs.entity; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import net.minecraft.core.Direction; import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.BlockHitResult; @@ -15,7 +15,7 @@ public class RayTraceResultJS { public final double distance; public Vec3 hit = null; - public BlockContainerJS block = null; + public LevelBlock block = null; public Direction facing = null; public Entity entity = null; @@ -27,7 +27,7 @@ public RayTraceResultJS(Entity from, @Nullable HitResult result, double d) { if (result instanceof BlockHitResult b && result.getType() == HitResult.Type.BLOCK) { hit = result.getLocation(); - block = new BlockContainerJS(from.level(), b.getBlockPos()); + block = from.level().kjs$getBlock(b.getBlockPos()); facing = b.getDirection(); } else if (result instanceof EntityHitResult e && result.getType() == HitResult.Type.ENTITY) { hit = result.getLocation(); diff --git a/src/main/java/dev/latvian/mods/kubejs/level/BlockContainerJS.java b/src/main/java/dev/latvian/mods/kubejs/level/BlockContainerJS.java deleted file mode 100644 index 2b44c16a0..000000000 --- a/src/main/java/dev/latvian/mods/kubejs/level/BlockContainerJS.java +++ /dev/null @@ -1,418 +0,0 @@ -package dev.latvian.mods.kubejs.level; - -import dev.latvian.mods.kubejs.bindings.BlockWrapper; -import dev.latvian.mods.kubejs.core.InventoryKJS; -import dev.latvian.mods.kubejs.player.EntityArrayList; -import dev.latvian.mods.kubejs.util.Cast; -import dev.latvian.mods.kubejs.util.Tags; -import dev.latvian.mods.rhino.Context; -import dev.latvian.mods.rhino.util.SpecialEquality; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.tags.TagKey; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.component.Fireworks; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LightLayer; -import net.minecraft.world.level.biome.Biomes; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.Property; -import net.minecraft.world.phys.AABB; -import net.neoforged.neoforge.capabilities.Capabilities; -import net.neoforged.neoforge.common.util.FakePlayer; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public class BlockContainerJS implements SpecialEquality { - public final Level minecraftLevel; - private final BlockPos pos; - - public transient BlockState cachedState; - public transient BlockEntity cachedEntity; - - public BlockContainerJS(Level w, BlockPos p) { - minecraftLevel = w; - pos = p; - } - - public BlockContainerJS(BlockEntity blockEntity) { - minecraftLevel = blockEntity.getLevel(); - pos = blockEntity.getBlockPos(); - cachedEntity = blockEntity; - } - - public void clearCache() { - cachedState = null; - cachedEntity = null; - } - - public Level getLevel() { - return minecraftLevel; - } - - public BlockPos getPos() { - return pos; - } - - public ResourceLocation getDimension() { - return minecraftLevel.dimension().location(); - } - - public int getX() { - return getPos().getX(); - } - - public int getY() { - return getPos().getY(); - } - - public int getZ() { - return getPos().getZ(); - } - - public BlockContainerJS offset(Direction f, int d) { - return new BlockContainerJS(minecraftLevel, getPos().relative(f, d)); - } - - public BlockContainerJS offset(Direction f) { - return offset(f, 1); - } - - public BlockContainerJS offset(int x, int y, int z) { - return new BlockContainerJS(minecraftLevel, getPos().offset(x, y, z)); - } - - public BlockContainerJS getDown() { - return offset(Direction.DOWN); - } - - public BlockContainerJS getUp() { - return offset(Direction.UP); - } - - public BlockContainerJS getNorth() { - return offset(Direction.NORTH); - } - - public BlockContainerJS getSouth() { - return offset(Direction.SOUTH); - } - - public BlockContainerJS getWest() { - return offset(Direction.WEST); - } - - public BlockContainerJS getEast() { - return offset(Direction.EAST); - } - - public BlockState getBlockState() { - if (cachedState == null) { - cachedState = minecraftLevel.getBlockState(getPos()); - } - - return cachedState; - } - - public void setBlockState(BlockState state, int flags) { - minecraftLevel.setBlock(getPos(), state, flags); - clearCache(); - cachedState = state; - } - - public ResourceLocation getId() { - return getBlockState().getBlock().kjs$getIdLocation(); - } - - public Collection getTags() { - return Tags.byBlockState(getBlockState()).map(TagKey::location).collect(Collectors.toSet()); - } - - public boolean hasTag(ResourceLocation tag) { - return getBlockState().is(Tags.block(tag)); - } - - public void set(Block block, Map properties, int flags) { - var state = block.defaultBlockState(); - - if (!properties.isEmpty() && state.getBlock() != Blocks.AIR) { - state = BlockWrapper.withProperties(state, properties); - - var pmap = new HashMap>(); - - for (var property : state.getProperties()) { - pmap.put(property.getName(), property); - } - - for (var entry : properties.entrySet()) { - var property = pmap.get(String.valueOf(entry.getKey())); - - if (property != null) { - state = state.setValue(property, Cast.to(property.getValue(String.valueOf(entry.getValue())).orElseThrow())); - } - } - } - - setBlockState(state, flags); - } - - public void set(Block block, Map properties) { - set(block, properties, 3); - } - - public void set(Block block) { - set(block, Collections.emptyMap()); - } - - public Map getProperties() { - Map map = new HashMap<>(); - var state = getBlockState(); - - for (Property property : state.getProperties()) { - map.put(property.getName(), property.getName(state.getValue(property))); - } - - return map; - } - - @Nullable - public BlockEntity getEntity() { - if (cachedEntity == null || cachedEntity.isRemoved()) { - cachedEntity = minecraftLevel.getBlockEntity(pos); - } - - return cachedEntity; - } - - public String getEntityId() { - var entity = getEntity(); - return entity == null ? "minecraft:air" : BuiltInRegistries.BLOCK_ENTITY_TYPE.getKey(entity.getType()).toString(); - } - - @Nullable - public CompoundTag getEntityData() { - var entity = getEntity(); - - if (entity != null) { - return entity.saveWithoutMetadata(minecraftLevel.registryAccess()); - } - - return null; - } - - public void setEntityData(@Nullable CompoundTag tag) { - if (tag != null) { - var entity = getEntity(); - - if (entity != null) { - entity.loadWithComponents(tag, minecraftLevel.registryAccess()); - } - } - } - - public void mergeEntityData(@Nullable CompoundTag tag) { - var t = getEntityData(); - - if (t == null) { - setEntityData(tag); - } else if (tag != null && !tag.isEmpty()) { - for (var s : tag.getAllKeys()) { - t.put(s, tag.get(s)); - } - } - - setEntityData(t); - } - - public int getLight() { - return minecraftLevel.getMaxLocalRawBrightness(pos); - } - - public int getSkyLight() { - return minecraftLevel.getBrightness(LightLayer.SKY, pos) - minecraftLevel.getSkyDarken(); - } - - public int getBlockLight() { - return minecraftLevel.getBrightness(LightLayer.BLOCK, pos); - } - - public boolean getCanSeeSky() { - return minecraftLevel.canSeeSky(pos); - } - - public boolean canSeeSkyFromBelowWater() { - return minecraftLevel.canSeeSkyFromBelowWater(pos); - } - - @Override - public String toString() { - var id = getId(); - var properties = getProperties(); - - if (properties.isEmpty()) { - return id.toString(); - } - - var builder = new StringBuilder(id.toString()); - builder.append('['); - - var first = true; - - for (var entry : properties.entrySet()) { - if (first) { - first = false; - } else { - builder.append(','); - } - - builder.append(entry.getKey()); - builder.append('='); - builder.append(entry.getValue()); - } - - builder.append(']'); - return builder.toString(); - } - - public ExplosionJS createExplosion() { - return new ExplosionJS(minecraftLevel, getX() + 0.5D, getY() + 0.5D, getZ() + 0.5D); - } - - @Nullable - public Entity createEntity(EntityType type) { - var entity = getLevel().kjs$createEntity(type); - - if (entity != null) { - entity.kjs$setPosition(this); - } - - return entity; - } - - public void spawnLightning(boolean effectOnly, @Nullable ServerPlayer player) { - if (minecraftLevel instanceof ServerLevel) { - var e = EntityType.LIGHTNING_BOLT.create(minecraftLevel); - e.moveTo(getX() + 0.5D, getY() + 0.5D, getZ() + 0.5D); - e.setCause(player); - e.setVisualOnly(effectOnly); - minecraftLevel.addFreshEntity(e); - } - } - - public void spawnLightning(boolean effectOnly) { - spawnLightning(effectOnly, null); - } - - public void spawnLightning() { - spawnLightning(false); - } - - public void spawnFireworks(Fireworks fireworks, int lifetime) { - minecraftLevel.kjs$spawnFireworks(getX() + 0.5D, getY() + 0.5D, getZ() + 0.5D, fireworks, lifetime); - } - - @Nullable - public InventoryKJS getInventory() { - return getInventory(Direction.UP); - } - - @Nullable - public InventoryKJS getInventory(Direction facing) { - var entity = getEntity(); - - if (entity != null) { - var c = minecraftLevel.getCapability(Capabilities.ItemHandler.BLOCK, getPos(), getBlockState(), getEntity(), facing); - - if (c instanceof InventoryKJS inv) { - return inv; - } else if (entity instanceof InventoryKJS inv) { - return inv; - } - } - - return null; - } - - public ItemStack getItem() { - var state = getBlockState(); - return state.getBlock().getCloneItemStack(minecraftLevel, pos, state); - } - - public List getDrops() { - return getDrops(null, ItemStack.EMPTY); - } - - public List getDrops(@Nullable Entity entity, ItemStack heldItem) { - if (minecraftLevel instanceof ServerLevel s) { - return Block.getDrops(getBlockState(), s, pos, getEntity(), entity, heldItem); - } - - return null; - } - - public void popItem(ItemStack item) { - Block.popResource(minecraftLevel, pos, item); - } - - public void popItemFromFace(ItemStack item, Direction dir) { - Block.popResourceFromFace(minecraftLevel, pos, dir, item); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } else if (obj instanceof CharSequence || obj instanceof ResourceLocation) { - return getId().equals(obj.toString()); - } - - return super.equals(obj); - } - - private static boolean isReal(Player p) { - return !(p instanceof FakePlayer); - } - - public EntityArrayList getPlayersInRadius(double radius) { - return new EntityArrayList(minecraftLevel, minecraftLevel.getEntitiesOfClass(Player.class, new AABB(pos.getX() - radius, pos.getY() - radius, pos.getZ() - radius, pos.getX() + 1D + radius, pos.getY() + 1D + radius, pos.getZ() + 1D + radius), BlockContainerJS::isReal)); - } - - public EntityArrayList getPlayersInRadius() { - return getPlayersInRadius(8D); - } - - public ResourceLocation getBiomeId() { - var k = minecraftLevel.getBiome(pos).getKey(); - return k == null ? Biomes.PLAINS.location() : k.location(); - } - - @Override - public boolean specialEquals(Context cx, Object o, boolean shallow) { - if (o instanceof CharSequence || o instanceof ResourceLocation) { - return getId().equals(o.toString()); - } - - return equals(o); - } - - public Map getTypeData() { - return getBlockState().getBlock().kjs$getTypeData(); - } -} \ No newline at end of file diff --git a/src/main/java/dev/latvian/mods/kubejs/level/CachedLevelBlock.java b/src/main/java/dev/latvian/mods/kubejs/level/CachedLevelBlock.java new file mode 100644 index 000000000..4aa947323 --- /dev/null +++ b/src/main/java/dev/latvian/mods/kubejs/level/CachedLevelBlock.java @@ -0,0 +1,92 @@ +package dev.latvian.mods.kubejs.level; + +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.Nullable; + +public class CachedLevelBlock implements LevelBlock { + public final Level minecraftLevel; + private final BlockPos pos; + + public transient BlockState cachedState; + public transient BlockEntity cachedEntity; + + public CachedLevelBlock(Level w, BlockPos p) { + minecraftLevel = w; + pos = p; + } + + @Override + public Level getLevel() { + return minecraftLevel; + } + + @Override + public BlockPos getPos() { + return pos; + } + + @Override + public LevelBlock cache(BlockState state) { + cachedState = state; + return this; + } + + @Override + public LevelBlock cache(BlockEntity entity) { + cachedEntity = entity; + return this; + } + + public void clearCache() { + cachedState = null; + cachedEntity = null; + } + + @Override + public BlockState getBlockState() { + if (cachedState == null) { + cachedState = minecraftLevel.getBlockState(getPos()); + } + + return cachedState; + } + + @Override + public void setBlockState(BlockState state, int flags) { + minecraftLevel.setBlock(getPos(), state, flags); + clearCache(); + cachedState = state; + } + + @Override + @Nullable + public BlockEntity getEntity() { + if (cachedEntity == null || cachedEntity.isRemoved()) { + cachedEntity = minecraftLevel.getBlockEntity(pos); + } + + return cachedEntity; + } + + @Override + public String toString() { + return toBlockStateString(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (obj instanceof CharSequence) { + return kjs$getId().equals(obj.toString()); + } else if (obj instanceof ResourceLocation) { + return kjs$getIdLocation().equals(obj); + } + + return super.equals(obj); + } +} \ No newline at end of file diff --git a/src/main/java/dev/latvian/mods/kubejs/level/ExplosionKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/level/ExplosionKubeEvent.java index ab71b78b6..01f3b7f3d 100644 --- a/src/main/java/dev/latvian/mods/kubejs/level/ExplosionKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/level/ExplosionKubeEvent.java @@ -43,8 +43,8 @@ public double getZ() { return getPosition().z; } - public BlockContainerJS getBlock() { - return new BlockContainerJS(level, BlockPos.containing(getPosition())); + public LevelBlock getBlock() { + return level.kjs$getBlock(BlockPos.containing(getPosition())); } @Nullable @@ -84,7 +84,7 @@ public After(Level level, Explosion explosion, List affectedEntities) { @Info("Gets a list of all entities affected by the explosion.") public EntityArrayList getAffectedEntities() { - return new EntityArrayList(level, affectedEntities); + return new EntityArrayList(affectedEntities); } @Info("Remove an entity from the list of affected entities.") @@ -98,18 +98,18 @@ public void removeAllAffectedEntities() { } @Info("Gets a list of all blocks affected by the explosion.") - public List getAffectedBlocks() { - List list = new ArrayList<>(explosion.getToBlow().size()); + public List getAffectedBlocks() { + List list = new ArrayList<>(explosion.getToBlow().size()); for (var pos : explosion.getToBlow()) { - list.add(new BlockContainerJS(level, pos)); + list.add(level.kjs$getBlock(pos)); } return list; } @Info("Remove a block from the list of affected blocks.") - public void removeAffectedBlock(BlockContainerJS block) { + public void removeAffectedBlock(LevelBlock block) { explosion.getToBlow().remove(block.getPos()); } diff --git a/src/main/java/dev/latvian/mods/kubejs/level/LevelBlock.java b/src/main/java/dev/latvian/mods/kubejs/level/LevelBlock.java new file mode 100644 index 000000000..ef660b7fc --- /dev/null +++ b/src/main/java/dev/latvian/mods/kubejs/level/LevelBlock.java @@ -0,0 +1,380 @@ +package dev.latvian.mods.kubejs.level; + +import dev.latvian.mods.kubejs.bindings.BlockWrapper; +import dev.latvian.mods.kubejs.core.BlockProviderKJS; +import dev.latvian.mods.kubejs.core.InventoryKJS; +import dev.latvian.mods.kubejs.player.EntityArrayList; +import dev.latvian.mods.kubejs.util.Cast; +import dev.latvian.mods.rhino.util.HideFromJS; +import dev.latvian.mods.rhino.util.RemapPrefixForJS; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.Fireworks; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LightLayer; +import net.minecraft.world.level.biome.Biomes; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.Property; +import net.minecraft.world.phys.AABB; +import net.neoforged.neoforge.capabilities.Capabilities; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@RemapPrefixForJS("kjs$") +public interface LevelBlock extends BlockProviderKJS { + Level getLevel(); + + BlockPos getPos(); + + @Override + default Block kjs$getBlock() { + return getBlockState().getBlock(); + } + + @HideFromJS + default LevelBlock cache(BlockState state) { + return this; + } + + @HideFromJS + default LevelBlock cache(BlockEntity entity) { + return this; + } + + default ResourceKey getDimensionKey() { + return getLevel().dimension(); + } + + default ResourceLocation getDimension() { + return getDimensionKey().location(); + } + + default int getX() { + return getPos().getX(); + } + + default int getY() { + return getPos().getY(); + } + + default int getZ() { + return getPos().getZ(); + } + + default double getCenterX() { + return getX() + 0.5D; + } + + default double getCenterY() { + return getY() + 0.5D; + } + + default double getCenterZ() { + return getZ() + 0.5D; + } + + default LevelBlock offset(Direction f, int d) { + return getLevel().kjs$getBlock(getPos().relative(f, d)); + } + + default LevelBlock offset(Direction f) { + return offset(f, 1); + } + + default LevelBlock offset(int x, int y, int z) { + return getLevel().kjs$getBlock(getPos().offset(x, y, z)); + } + + default LevelBlock getDown() { + return offset(Direction.DOWN); + } + + default LevelBlock getUp() { + return offset(Direction.UP); + } + + default LevelBlock getNorth() { + return offset(Direction.NORTH); + } + + default LevelBlock getSouth() { + return offset(Direction.SOUTH); + } + + default LevelBlock getWest() { + return offset(Direction.WEST); + } + + default LevelBlock getEast() { + return offset(Direction.EAST); + } + + default BlockState getBlockState() { + return getLevel().getBlockState(getPos()); + } + + default void setBlockState(BlockState state, int flags) { + getLevel().setBlock(getPos(), state, flags); + } + + default void setBlockState(BlockState state) { + setBlockState(state, Block.UPDATE_ALL); + } + + default void set(Block block, Map properties, int flags) { + var state = block.defaultBlockState(); + + if (!properties.isEmpty() && state.getBlock() != Blocks.AIR) { + state = BlockWrapper.withProperties(state, properties); + + var pmap = new HashMap>(); + + for (var property : state.getProperties()) { + pmap.put(property.getName(), property); + } + + for (var entry : properties.entrySet()) { + var property = pmap.get(String.valueOf(entry.getKey())); + + if (property != null) { + state = state.setValue(property, Cast.to(property.getValue(String.valueOf(entry.getValue())).orElseThrow())); + } + } + } + + setBlockState(state, flags); + } + + default void set(Block block, Map properties) { + set(block, properties, 3); + } + + default void set(Block block) { + set(block, Collections.emptyMap()); + } + + default Map getProperties() { + Map map = new HashMap<>(); + var state = getBlockState(); + + for (Property property : state.getProperties()) { + map.put(property.getName(), property.getName(state.getValue(property))); + } + + return map; + } + + @Nullable + default BlockEntity getEntity() { + return getLevel().getBlockEntity(getPos()); + } + + default String getEntityId() { + var entity = getEntity(); + return entity == null ? "minecraft:air" : BuiltInRegistries.BLOCK_ENTITY_TYPE.getKey(entity.getType()).toString(); + } + + @Nullable + default CompoundTag getEntityData() { + var entity = getEntity(); + + if (entity != null) { + return entity.saveWithoutMetadata(getLevel().registryAccess()); + } + + return null; + } + + default void setEntityData(@Nullable CompoundTag tag) { + if (tag != null) { + var entity = getEntity(); + + if (entity != null) { + entity.loadWithComponents(tag, getLevel().registryAccess()); + } + } + } + + default void mergeEntityData(@Nullable CompoundTag tag) { + var t = getEntityData(); + + if (t == null) { + setEntityData(tag); + } else if (tag != null && !tag.isEmpty()) { + for (var s : tag.getAllKeys()) { + t.put(s, tag.get(s)); + } + } + + setEntityData(t); + } + + default int getLight() { + return getLevel().getMaxLocalRawBrightness(getPos()); + } + + default int getSkyLight() { + return getLevel().getBrightness(LightLayer.SKY, getPos()) - getLevel().getSkyDarken(); + } + + default int getBlockLight() { + return getLevel().getBrightness(LightLayer.BLOCK, getPos()); + } + + default boolean getCanSeeSky() { + return getLevel().canSeeSky(getPos()); + } + + default boolean canSeeSkyFromBelowWater() { + return getLevel().canSeeSkyFromBelowWater(getPos()); + } + + default ExplosionJS createExplosion() { + return new ExplosionJS(getLevel(), getX() + 0.5D, getY() + 0.5D, getZ() + 0.5D); + } + + @Nullable + default Entity createEntity(EntityType type) { + var entity = getLevel().kjs$createEntity(type); + + if (entity != null) { + entity.kjs$setPosition(this); + } + + return entity; + } + + default void spawnLightning(boolean effectOnly, @Nullable ServerPlayer player) { + getLevel().kjs$spawnLightning(getCenterX(), getCenterY(), getCenterZ(), effectOnly, player); + } + + default void spawnLightning(boolean effectOnly) { + spawnLightning(effectOnly, null); + } + + default void spawnLightning() { + spawnLightning(false); + } + + default void spawnFireworks(Fireworks fireworks, int lifetime) { + getLevel().kjs$spawnFireworks(getCenterX(), getCenterY(), getCenterZ(), fireworks, lifetime); + } + + @Nullable + default InventoryKJS getInventory() { + return getInventory(Direction.UP); + } + + @Nullable + default InventoryKJS getInventory(Direction facing) { + var entity = getEntity(); + + if (entity != null) { + var c = getLevel().getCapability(Capabilities.ItemHandler.BLOCK, getPos(), getBlockState(), getEntity(), facing); + + if (c instanceof InventoryKJS inv) { + return inv; + } else if (entity instanceof InventoryKJS inv) { + return inv; + } + } + + return null; + } + + default ItemStack getItem() { + var state = getBlockState(); + return state.getBlock().getCloneItemStack(getLevel(), getPos(), state); + } + + default List getDrops() { + return getDrops(null, ItemStack.EMPTY); + } + + default List getDrops(@Nullable Entity entity, ItemStack heldItem) { + if (getLevel() instanceof ServerLevel s) { + return Block.getDrops(getBlockState(), s, getPos(), getEntity(), entity, heldItem); + } + + return List.of(); + } + + default void popItem(ItemStack item) { + Block.popResource(getLevel(), getPos(), item); + } + + default void popItemFromFace(ItemStack item, Direction dir) { + Block.popResourceFromFace(getLevel(), getPos(), dir, item); + } + + default EntityArrayList getPlayersInRadius(double radius) { + var list = new EntityArrayList(1); + + double cx = getCenterX(); + double cy = getCenterY(); + double cz = getCenterZ(); + + for (var entity : getLevel().getEntities((Entity) null, new AABB(cx - 0.5D - radius, cy - 0.5D - radius, cz - 0.5D - radius, cx + 0.5D + radius, cy + 0.5D + radius, cz + 0.5D + radius), EntityArrayList.ALWAYS_TRUE_PREDICATE)) { + if (entity.distanceToSqr(cx, cy, cz) <= radius * radius && entity instanceof Player p && !p.isFakePlayer()) { + list.add(p); + } + } + + return list; + } + + default EntityArrayList getPlayersInRadius() { + return getPlayersInRadius(8D); + } + + default ResourceLocation getBiomeId() { + var k = getLevel().getBiome(getPos()).getKey(); + return k == null ? Biomes.PLAINS.location() : k.location(); + } + + default String toBlockStateString() { + var id = kjs$getId(); + var properties = getProperties(); + + if (properties.isEmpty()) { + return id; + } + + var builder = new StringBuilder(id); + builder.append('['); + + var first = true; + + for (var entry : properties.entrySet()) { + if (first) { + first = false; + } else { + builder.append(','); + } + + builder.append(entry.getKey()); + builder.append('='); + builder.append(entry.getValue()); + } + + builder.append(']'); + return builder.toString(); + } +} diff --git a/src/main/java/dev/latvian/mods/kubejs/level/SpawnerJS.java b/src/main/java/dev/latvian/mods/kubejs/level/SpawnerJS.java index 55513c039..387dea464 100644 --- a/src/main/java/dev/latvian/mods/kubejs/level/SpawnerJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/level/SpawnerJS.java @@ -5,7 +5,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; import org.jetbrains.annotations.Nullable; -public record SpawnerJS(@Nullable Entity entity, @Nullable BlockContainerJS block) { +public record SpawnerJS(@Nullable Entity entity, @Nullable LevelBlock block) { public static SpawnerJS of(Either spawner) { if (spawner == null) { return new SpawnerJS(null, null); @@ -20,7 +20,7 @@ public static SpawnerJS of(Either spawner) { var be = spawner.left().orElse(null); if (be != null) { - return new SpawnerJS(null, new BlockContainerJS(be)); + return new SpawnerJS(null, be.getLevel().kjs$getBlock(be)); } return new SpawnerJS(null, null); diff --git a/src/main/java/dev/latvian/mods/kubejs/player/ChestKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/player/ChestKubeEvent.java index 87f0bdb3e..300152989 100644 --- a/src/main/java/dev/latvian/mods/kubejs/player/ChestKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/player/ChestKubeEvent.java @@ -1,6 +1,6 @@ package dev.latvian.mods.kubejs.player; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.kubejs.typings.Info; import net.minecraft.world.Container; import net.minecraft.world.entity.player.Player; @@ -26,7 +26,7 @@ public Container getInventory() { @Nullable @Info("Gets the chest block.") - public BlockContainerJS getBlock() { + public LevelBlock getBlock() { if (getInventory() instanceof BlockEntity be) { return getLevel().kjs$getBlock(be); } diff --git a/src/main/java/dev/latvian/mods/kubejs/player/EntityArrayList.java b/src/main/java/dev/latvian/mods/kubejs/player/EntityArrayList.java index fd993de82..9a6a2eaae 100644 --- a/src/main/java/dev/latvian/mods/kubejs/player/EntityArrayList.java +++ b/src/main/java/dev/latvian/mods/kubejs/player/EntityArrayList.java @@ -4,13 +4,14 @@ import dev.latvian.mods.kubejs.core.MessageSenderKJS; import dev.latvian.mods.rhino.util.RemapPrefixForJS; import net.minecraft.commands.arguments.selector.EntitySelector; +import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.SoundEvent; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.Level; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -20,15 +21,14 @@ @RemapPrefixForJS("kjs$") public class EntityArrayList extends ArrayList implements MessageSenderKJS, DataSenderKJS { - public final Level level; + public static final Predicate ALWAYS_TRUE_PREDICATE = entity -> true; - public EntityArrayList(Level l, int size) { + public EntityArrayList(int size) { super(size); - level = l; } - public EntityArrayList(Level l, Iterable entities) { - this(l, entities instanceof Collection c ? c.size() : 4); + public EntityArrayList(Iterable entities) { + this(entities instanceof Collection c ? c.size() : 4); addAllIterable(entities); } @@ -103,12 +103,29 @@ public void playSound(SoundEvent id) { playSound(id, 1F, 1F); } + public EntityArrayList oneFilter(Predicate filter) { + if (isEmpty()) { + return this; + } + + var list = new EntityArrayList(size() / 4); + + for (var entity : this) { + if (filter.test(entity)) { + list.add(entity); + break; + } + } + + return list; + } + public EntityArrayList filter(List> filterList) { if (isEmpty() || filterList.isEmpty()) { return this; } - var list = new EntityArrayList(level, size()); + var list = new EntityArrayList(size()); for (var entity : this) { for (var filter : filterList) { @@ -125,6 +142,30 @@ public EntityArrayList filterSelector(EntitySelector selector) { return filter(selector.contextFreePredicates); } + public EntityArrayList filterDistance(double x, double y, double z, double distance) { + var list = new EntityArrayList(size()); + + for (var entity : this) { + if (entity.distanceToSqr(x, y, z) <= distance * distance) { + list.add(entity); + } + } + + return list; + } + + public EntityArrayList filterDistance(BlockPos pos, double distance) { + return filterDistance(pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D, distance); + } + + public EntityArrayList filterPlayers() { + return oneFilter(e -> e instanceof Player); + } + + public EntityArrayList filterItems() { + return oneFilter(e -> e instanceof ItemEntity); + } + @Override public void kjs$sendData(String channel, @Nullable CompoundTag data) { for (var entity : this) { diff --git a/src/main/java/dev/latvian/mods/kubejs/server/BasicCommandKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/server/BasicCommandKubeEvent.java index 1055a07f8..ab877bef8 100644 --- a/src/main/java/dev/latvian/mods/kubejs/server/BasicCommandKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/server/BasicCommandKubeEvent.java @@ -1,7 +1,7 @@ package dev.latvian.mods.kubejs.server; import dev.latvian.mods.kubejs.entity.KubeEntityEvent; -import dev.latvian.mods.kubejs.level.BlockContainerJS; +import dev.latvian.mods.kubejs.level.LevelBlock; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; @@ -46,7 +46,7 @@ public ServerPlayer getPlayer() { return serverPlayer; } - public BlockContainerJS getBlock() { + public LevelBlock getBlock() { return this.getLevel().kjs$getBlock(pos); } } \ No newline at end of file diff --git a/src/main/resources/kubejs.mixins.json b/src/main/resources/kubejs.mixins.json index 065b5820f..5d20a1541 100644 --- a/src/main/resources/kubejs.mixins.json +++ b/src/main/resources/kubejs.mixins.json @@ -20,6 +20,7 @@ "DifferenceIngredientMixin", "DirectionMixin", "DyeColorMixin", + "EntityGetterMixin", "EntityMixin", "EntityTypeMixin", "FallingBlockEntityMixin",