diff --git a/README.md b/README.md index 85300586..b8edc6f7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ -![GitHub all releases](https://img.shields.io/github/downloads/SkriptDev/HySkript/total) # Skript... but for Hytale. ![landscape](https://github.com/user-attachments/assets/2234f5ea-c2dc-4e79-b51c-4300b795e64f) diff --git a/src/main/java/com/github/skriptdev/skript/api/hytale/utils/EntityReferenceUtils.java b/src/main/java/com/github/skriptdev/skript/api/hytale/utils/EntityReferenceUtils.java index ec790cdf..7c42afac 100644 --- a/src/main/java/com/github/skriptdev/skript/api/hytale/utils/EntityReferenceUtils.java +++ b/src/main/java/com/github/skriptdev/skript/api/hytale/utils/EntityReferenceUtils.java @@ -6,12 +6,13 @@ import com.hypixel.hytale.component.Store; import com.hypixel.hytale.component.spatial.SpatialResource; import com.hypixel.hytale.math.vector.Vector3d; +import com.hypixel.hytale.server.core.entity.Entity; import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.modules.entity.EntityModule; import com.hypixel.hytale.server.core.modules.entity.item.ItemComponent; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.npc.entities.NPCEntity; -import it.unimi.dsi.fastutil.objects.ObjectList; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.annotation.Nonnull; @@ -44,34 +45,36 @@ public static ReferenceType getType(Class> componentCl return TYPES_MAP.get(componentClass); } + @SuppressWarnings("unchecked") + public static @Nullable Ref getRef(Object o) { + if (o instanceof Ref ref && ref.isValid()) { + return (Ref) ref; + } else if (o instanceof Entity entity) { + Ref reference = entity.getReference(); + if (reference != null && reference.isValid()) return reference; + } + return null; + } + public static List> getRefsInSphere(@Nonnull Vector3d pos, double radius, @Nonnull Store store) { - ObjectList> results = SpatialResource.getThreadLocalReferenceList(); + List> results = SpatialResource.getThreadLocalReferenceList(); EntityModule entityModule = EntityModule.get(); - SpatialResource, EntityStore> entities = store.getResource(entityModule.getEntitySpatialResourceType()); + SpatialResource, EntityStore> entities = store.getResource(entityModule.getNetworkSendableSpatialResourceType()); entities.getSpatialStructure().collect(pos, (float) radius, results); - SpatialResource, EntityStore> players = store.getResource(entityModule.getPlayerSpatialResourceType()); - players.getSpatialStructure().collect(pos, (float) radius, results); - SpatialResource, EntityStore> items = store.getResource(entityModule.getItemSpatialResourceType()); - items.getSpatialStructure().collect(pos, (float) radius, results); return results; } @Nonnull public static List> getRefsInBox(@Nonnull Vector3d min, @Nonnull Vector3d max, @Nonnull Store store) { - ObjectList> results = SpatialResource.getThreadLocalReferenceList(); + List> results = SpatialResource.getThreadLocalReferenceList(); EntityModule entityModule = EntityModule.get(); - SpatialResource, EntityStore> entities = store.getResource(entityModule.getEntitySpatialResourceType()); + SpatialResource, EntityStore> entities = store.getResource(entityModule.getNetworkSendableSpatialResourceType()); entities.getSpatialStructure().collectBox(min, max, results); - SpatialResource, EntityStore> players = store.getResource(entityModule.getPlayerSpatialResourceType()); - players.getSpatialStructure().collectBox(min, max, results); - SpatialResource, EntityStore> items = store.getResource(entityModule.getItemSpatialResourceType()); - items.getSpatialStructure().collectBox(min, max, results); return results; } public static class ReferenceType> { - private final String name; private final Class componentClass; private final ComponentType componentType; @@ -99,4 +102,95 @@ public Class getComponentClass() { } } + /** + * Get a component from an Object (Entity/Ref). + * + * @param object Object to get component from + * @param type Component type to get + * @param EntityStore Type + * @param Type of returned component + * @return Component from entity if available otherwise null + */ + @SuppressWarnings("unchecked") + public static > @Nullable T getComponent(Object object, ComponentType type) { + Ref reference = (Ref) getRef(object); + if (reference == null) return null; + + Store store = reference.getStore(); + return store.getComponent(reference, type); + } + + /** + * Get a component from an Object (Entity/Ref) or create it if not present. + * + * @param object Object to get component from + * @param type Component type to get + * @param EntityStore Type + * @param Type of returned component + * @return Component from entity if available otherwise will create/add a new one + */ + @SuppressWarnings("unchecked") + public static > @NotNull T ensureAndGetComponent(Object object, ComponentType type) { + Ref reference = (Ref) getRef(object); + if (reference == null) { + throw new IllegalStateException("Object '" + object + "' does not have a reference"); + } + + Store store = reference.getStore(); + return store.ensureAndGetComponent(reference, type); + } + + /** + * Add a component on an Object (Entity/Ref). + * + * @param object Object (Entity/Ref) to add component to + * @param type Type of component to add + * @param component Component to add + * @param EntityStore Type + * @param Type of component + */ + @SuppressWarnings("unchecked") + public static > void addComponent(Object object, ComponentType type, Component component) { + Ref reference = (Ref) getRef(object); + if (reference == null) { + throw new IllegalStateException("Object '" + object + "' does not have a reference"); + } + reference.getStore().addComponent(reference, type, (T) component); + } + + /** + * Put a component on an Object (Entity/Ref). + * + * @param object Object (Entity/Ref) to put component on + * @param type Type of component to put + * @param component Component to put + * @param EntityStore Type + * @param Type of component + */ + @SuppressWarnings("unchecked") + public static > void putComponent(Object object, ComponentType type, Component component) { + Ref reference = (Ref) getRef(object); + if (reference == null) { + throw new IllegalStateException("Object '" + object + "' does not have a reference"); + } + reference.getStore().putComponent(reference, type, (T) component); + } + + /** + * Try to remove a component from an Object (Entity/Ref). + * + * @param object Object (Entity/Ref) to remove component from + * @param type Type of component to remove + * @param Store type + * @param Component type + */ + @SuppressWarnings("unchecked") + public static > void tryRemoveComponent(Object object, ComponentType type) { + Ref reference = (Ref) getRef(object); + if (reference == null) { + throw new IllegalStateException("Object '" + object + "' does not have a reference"); + } + reference.getStore().tryRemoveComponent(reference, type); + } + } diff --git a/src/main/java/com/github/skriptdev/skript/api/hytale/utils/EntityUtils.java b/src/main/java/com/github/skriptdev/skript/api/hytale/utils/EntityUtils.java index d0518e4f..04ef05e6 100644 --- a/src/main/java/com/github/skriptdev/skript/api/hytale/utils/EntityUtils.java +++ b/src/main/java/com/github/skriptdev/skript/api/hytale/utils/EntityUtils.java @@ -10,15 +10,30 @@ import com.hypixel.hytale.math.vector.Location; import com.hypixel.hytale.math.vector.Vector3d; import com.hypixel.hytale.math.vector.Vector3f; +import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; +import com.hypixel.hytale.server.core.asset.type.item.config.Item; +import com.hypixel.hytale.server.core.asset.type.model.config.Model; +import com.hypixel.hytale.server.core.asset.type.model.config.ModelAsset; import com.hypixel.hytale.server.core.entity.Entity; import com.hypixel.hytale.server.core.entity.LivingEntity; import com.hypixel.hytale.server.core.entity.UUIDComponent; +import com.hypixel.hytale.server.core.entity.entities.BlockEntity; import com.hypixel.hytale.server.core.entity.movement.MovementStatesComponent; import com.hypixel.hytale.server.core.entity.nameplate.Nameplate; import com.hypixel.hytale.server.core.inventory.ItemStack; +import com.hypixel.hytale.server.core.modules.entity.component.EntityScaleComponent; +import com.hypixel.hytale.server.core.modules.entity.component.HeadRotation; +import com.hypixel.hytale.server.core.modules.entity.component.ModelComponent; +import com.hypixel.hytale.server.core.modules.entity.component.PersistentModel; +import com.hypixel.hytale.server.core.modules.entity.component.PropComponent; +import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent; import com.hypixel.hytale.server.core.modules.entity.item.ItemComponent; +import com.hypixel.hytale.server.core.modules.entity.item.PreventItemMerging; +import com.hypixel.hytale.server.core.modules.entity.item.PreventPickup; +import com.hypixel.hytale.server.core.modules.entity.tracker.NetworkId; import com.hypixel.hytale.server.core.modules.entitystats.EntityStatMap; import com.hypixel.hytale.server.core.modules.entitystats.EntityStatsModule; +import com.hypixel.hytale.server.core.universe.Universe; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.npc.entities.NPCEntity; @@ -29,6 +44,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.annotation.Nonnull; import java.util.UUID; /** @@ -227,7 +243,7 @@ public static > void tryRemoveComponent(Entity ent @SuppressWarnings({"DataFlowIssue"}) public static @NotNull Pair, ItemComponent> dropItem(Store store, ItemStack itemStack, - Location location, Vector3f velocity, float pickupDelay) { + Location location, Vector3f velocity, float pickupDelay) { if (itemStack.isEmpty() || !itemStack.isValid()) { return new Pair<>(null, null); } @@ -324,4 +340,119 @@ public static void clearMarkedEntity(NPCEntity npcEntity, @Nullable Entity targe } } + private static String getItemModelId(@Nonnull Item item) { + String modelId = item.getModel(); + + if (modelId == null && item.hasBlockType()) { + BlockType blockType = BlockType.getAssetMap().getAsset(item.getId()); + + if (blockType != null && blockType.getCustomModel() != null) { + modelId = blockType.getCustomModel(); + } + } + + return modelId; + } + + private static Model getItemModel(@Nonnull Item item) { + String modelId = getItemModelId(item); + + if (modelId == null) { + return null; + } else { + ModelAsset modelAsset = ModelAsset.getAssetMap().getAsset(modelId); + + return modelAsset != null ? Model.createStaticScaledModel(modelAsset, 1.0f) : null; + } + } + + public static Ref spawnModel(@NotNull Object object, @NotNull Location location) { + return switch (object) { + case Item item -> spawnItem(item, location); + case BlockType blockType -> spawnBlock(null, blockType, location); + case ModelAsset modelAsset -> spawnModel(null, Model.createStaticScaledModel(modelAsset, 1.0f), location); + default -> null; + }; + } + + public static Ref spawnModel(@Nullable Item item, @NotNull Model model, @NotNull Location location) { + World world = Universe.get().getWorld(location.getWorld()); + if (world == null) return null; + + Store store = world.getEntityStore().getStore(); + Holder holder = store.getRegistry().newHolder(); + + holder.addComponent(NetworkId.getComponentType(), new NetworkId(store.getExternalData().takeNextNetworkId())); + holder.addComponent(TransformComponent.getComponentType(), new TransformComponent(location.getPosition(), location.getRotation())); + holder.addComponent(ModelComponent.getComponentType(), new ModelComponent(model)); + holder.addComponent(PersistentModel.getComponentType(), + new PersistentModel( + new Model.ModelReference(model.getModelAssetId(), 1.0f, null, true))); + if (item != null) { + ItemStack itemStack = new ItemStack(item.getId(), 1); + itemStack.setOverrideDroppedItemAnimation(true); + holder.addComponent(ItemComponent.getComponentType(), new ItemComponent(itemStack)); + } + holder.addComponent(EntityScaleComponent.getComponentType(), new EntityScaleComponent(1.0f)); + holder.addComponent(PreventPickup.getComponentType(), PreventPickup.INSTANCE); + holder.addComponent(PreventItemMerging.getComponentType(), PreventItemMerging.INSTANCE); + holder.addComponent(HeadRotation.getComponentType(), new HeadRotation(location.getRotation())); + holder.addComponent(PropComponent.getComponentType(), PropComponent.get()); + holder.ensureComponent(UUIDComponent.getComponentType()); + return store.addEntity(holder, AddReason.SPAWN); + } + + public static Ref spawnItem(@NotNull Item item, @NotNull Location location) { + Model model = getItemModel(item); + if (model != null) { + return spawnModel(item, model, location); + } + if (item.hasBlockType()) { + BlockType blockType = BlockType.getAssetMap().getAsset(item.getId()); + if (blockType != null) { + return spawnBlock(item, blockType, location); + } + } + World world = Universe.get().getWorld(location.getWorld()); + if (world == null) return null; + + Store store = world.getEntityStore().getStore(); + Holder holder = store.getRegistry().newHolder(); + + holder.addComponent(NetworkId.getComponentType(), new NetworkId(store.getExternalData().takeNextNetworkId())); + holder.addComponent(TransformComponent.getComponentType(), new TransformComponent(location.getPosition(), location.getRotation())); + ItemStack itemStack = new ItemStack(item.getId(), 1); + itemStack.setOverrideDroppedItemAnimation(true); + holder.addComponent(ItemComponent.getComponentType(), new ItemComponent(itemStack)); + holder.addComponent(EntityScaleComponent.getComponentType(), new EntityScaleComponent(1.0f)); + holder.addComponent(PreventPickup.getComponentType(), PreventPickup.INSTANCE); + holder.addComponent(PreventItemMerging.getComponentType(), PreventItemMerging.INSTANCE); + holder.addComponent(HeadRotation.getComponentType(), new HeadRotation(location.getRotation())); + holder.addComponent(PropComponent.getComponentType(), PropComponent.get()); + return store.addEntity(holder, AddReason.SPAWN); + } + + public static Ref spawnBlock(@Nullable Item item, @NotNull BlockType blockType, @NotNull Location location) { + World world = Universe.get().getWorld(location.getWorld()); + if (world == null) return null; + + Store store = world.getEntityStore().getStore(); + Holder holder = store.getRegistry().newHolder(); + + holder.addComponent(BlockEntity.getComponentType(), new BlockEntity(blockType.getId())); + holder.addComponent(TransformComponent.getComponentType(), new TransformComponent(location.getPosition(), location.getRotation())); + holder.addComponent(EntityScaleComponent.getComponentType(), new EntityScaleComponent(1.0F)); + if (item != null) { + ItemStack itemStack = new ItemStack(item.getId(), 1); + itemStack.setOverrideDroppedItemAnimation(true); + holder.addComponent(ItemComponent.getComponentType(), new ItemComponent(itemStack)); + } + holder.addComponent(PreventPickup.getComponentType(), PreventPickup.INSTANCE); + holder.addComponent(PreventItemMerging.getComponentType(), PreventItemMerging.INSTANCE); + holder.addComponent(HeadRotation.getComponentType(), new HeadRotation(location.getRotation())); + holder.addComponent(PropComponent.getComponentType(), PropComponent.get()); + holder.ensureComponent(UUIDComponent.getComponentType()); + return store.addEntity(holder, AddReason.SPAWN); + } + } diff --git a/src/main/java/com/github/skriptdev/skript/api/skript/docs/JsonDocPrinter.java b/src/main/java/com/github/skriptdev/skript/api/skript/docs/JsonDocPrinter.java index c6a88b1a..73bce174 100644 --- a/src/main/java/com/github/skriptdev/skript/api/skript/docs/JsonDocPrinter.java +++ b/src/main/java/com/github/skriptdev/skript/api/skript/docs/JsonDocPrinter.java @@ -50,6 +50,7 @@ public class JsonDocPrinter { private final SkriptAddon addon; private final String addonKey; private final boolean includeSkriptParser; + private final List ids = new ArrayList<>(); public JsonDocPrinter(CommandSender sender, SkriptAddon addon) { this.sender = sender; @@ -593,7 +594,12 @@ private BsonString getId(String type, String syntaxId) { addonName = "HySkript"; } String s = type + ":" + addonName + ":" + syntaxId; - return new BsonString(s.toLowerCase(Locale.ROOT).replace(" ", "_")); + String id = s.toLowerCase(Locale.ROOT).replace(" ", "_"); + if (this.ids.contains(id)) { + Utils.error("Duplicate ID: " + id); + } + this.ids.add(id); + return new BsonString(id); } diff --git a/src/main/java/com/github/skriptdev/skript/api/utils/ReflectionUtils.java b/src/main/java/com/github/skriptdev/skript/api/utils/ReflectionUtils.java index 20cae7be..7d04b03b 100644 --- a/src/main/java/com/github/skriptdev/skript/api/utils/ReflectionUtils.java +++ b/src/main/java/com/github/skriptdev/skript/api/utils/ReflectionUtils.java @@ -2,6 +2,9 @@ import com.hypixel.hytale.server.core.modules.accesscontrol.AccessControlModule; import com.hypixel.hytale.server.core.modules.accesscontrol.provider.HytaleBanProvider; +import com.hypixel.hytale.server.core.universe.world.World; +import com.hypixel.hytale.server.core.universe.world.WorldConfig; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.reflect.Field; @@ -37,4 +40,28 @@ public static void init() { return BAN_PROVIDER; } + /** + * Set world override time durations of a world. + *
I didn't want to do this, but Hytale doesn't have a setter and this is private. + * + * @param world World to change times for + * @param seconds Seconds to override + * @param day Whether to override daytime or nighttime duration + */ + public static void setWorldTimeOverrides(@NotNull World world, @Nullable Integer seconds, boolean day) { + WorldConfig worldConfig = world.getWorldConfig(); + try { + Field field; + if (day) { + field = worldConfig.getClass().getDeclaredField("daytimeDurationSecondsOverride"); + } else { + field = worldConfig.getClass().getDeclaredField("nighttimeDurationSecondsOverride"); + } + field.setAccessible(true); + field.set(worldConfig, seconds); + } catch (NoSuchFieldException | IllegalAccessException ignore) { + + } + } + } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/conditions/ConditionHandler.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/conditions/ConditionHandler.java index 6599cc6d..e351fc4a 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/conditions/ConditionHandler.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/conditions/ConditionHandler.java @@ -25,6 +25,7 @@ import com.github.skriptdev.skript.plugin.elements.conditions.player.CondPlayerMovementSprinting; import com.github.skriptdev.skript.plugin.elements.conditions.player.CondPlayerMovementSwimming; import com.github.skriptdev.skript.plugin.elements.conditions.player.CondPlayerMovementWalking; +import com.github.skriptdev.skript.plugin.elements.conditions.ref.CondCanBePickedUp; import com.github.skriptdev.skript.plugin.elements.conditions.world.CondChunkIsLoaded; import com.github.skriptdev.skript.plugin.elements.conditions.world.CondWorldTimePaused; @@ -66,6 +67,9 @@ public static void register(SkriptRegistration registration) { CondPlayerMovementSwimming.register(registration); CondPlayerMovementWalking.register(registration); + // REF + CondCanBePickedUp.register(registration); + // WORLD CondChunkIsLoaded.register(registration); CondWorldTimePaused.register(registration); diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/conditions/ref/CondCanBePickedUp.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/conditions/ref/CondCanBePickedUp.java new file mode 100644 index 00000000..5fd4bc02 --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/conditions/ref/CondCanBePickedUp.java @@ -0,0 +1,67 @@ +package com.github.skriptdev.skript.plugin.elements.conditions.ref; + +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.server.core.modules.entity.item.PreventPickup; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import io.github.syst3ms.skriptparser.lang.TriggerContext; +import io.github.syst3ms.skriptparser.lang.properties.ConditionalType; +import io.github.syst3ms.skriptparser.lang.properties.PropertyConditional; +import io.github.syst3ms.skriptparser.types.changers.ChangeMode; +import io.github.syst3ms.skriptparser.util.CollectionUtils; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; + +public class CondCanBePickedUp extends PropertyConditional> { + + public static void register(SkriptRegistration reg) { + reg.newPropertyConditional(CondCanBePickedUp.class, + "refs", ConditionalType.CAN, "be picked up") + .name("Ref - Can Be Picked Up") + .description("Check if a ref can be picked up.", + "This generally refers to dropped items.", + "This can be set, preventing items from being picked up.") + .since("INSERT VERSION") + .register(); + } + + @Override + public boolean check(@NotNull TriggerContext ctx) { + return getPerformer().check(ctx, ref -> { + Store store = ref.getStore(); + return store.getComponent(ref, PreventPickup.getComponentType()) == null; + }, isNegated()); + } + + @Override + public Optional[]> acceptsChange(@NotNull ChangeMode mode) { + if (mode == ChangeMode.SET) { + return CollectionUtils.optionalArrayOf(Boolean.class); + } + return Optional.empty(); + } + + @SuppressWarnings("ConstantValue") + @Override + public void change(@NotNull TriggerContext ctx, @NotNull ChangeMode changeMode, Object @NotNull [] changeWith) { + if (changeWith == null || changeWith.length == 0 || !(changeWith[0] instanceof Boolean bool)) { + return; + } + for (Ref ref : getPerformer().getArray(ctx)) { + Store store = ref.getStore(); + if (bool) { + store.removeComponentIfExists(ref, PreventPickup.getComponentType()); + } else { + store.ensureComponent(ref, PreventPickup.getComponentType()); + } + } + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + return getPerformer().toString(ctx, debug) + " can be picked up"; + } + +} diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/EffectHandler.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/EffectHandler.java index ab5928c0..8b95e43c 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/EffectHandler.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/EffectHandler.java @@ -12,6 +12,7 @@ import com.github.skriptdev.skript.plugin.elements.effects.entity.EffFreeze; import com.github.skriptdev.skript.plugin.elements.effects.entity.EffInteraction; import com.github.skriptdev.skript.plugin.elements.effects.entity.EffKill; +import com.github.skriptdev.skript.plugin.elements.effects.entity.EffPlayAnimation; import com.github.skriptdev.skript.plugin.elements.effects.entity.EffRemoveStatModifier; import com.github.skriptdev.skript.plugin.elements.effects.entity.EffRide; import com.github.skriptdev.skript.plugin.elements.effects.entity.EffShoot; @@ -56,6 +57,7 @@ public static void register(SkriptRegistration registration) { EffFreeze.register(registration); EffInteraction.register(registration); EffKill.register(registration); + EffPlayAnimation.register(registration); EffRemoveStatModifier.register(registration); EffRide.register(registration); EffShoot.register(registration); diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/entity/EffPlayAnimation.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/entity/EffPlayAnimation.java new file mode 100644 index 00000000..4ef6f7b1 --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/effects/entity/EffPlayAnimation.java @@ -0,0 +1,84 @@ +package com.github.skriptdev.skript.plugin.elements.effects.entity; + +import com.github.skriptdev.skript.api.hytale.utils.EntityReferenceUtils; +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.protocol.AnimationSlot; +import com.hypixel.hytale.server.core.entity.AnimationUtils; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import io.github.syst3ms.skriptparser.lang.Effect; +import io.github.syst3ms.skriptparser.lang.Expression; +import io.github.syst3ms.skriptparser.lang.TriggerContext; +import io.github.syst3ms.skriptparser.parsing.ParseContext; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; + +public class EffPlayAnimation extends Effect { + + public static void register(SkriptRegistration reg) { + reg.newEffect(EffPlayAnimation.class, + "play animation %string% on %entities/refs%", + "play %animationslot% animation %string% on %entities/refs%") + .name("Play Animation") + .description("Plays an animation on the specified entity.", + "If the animation slot is not specified, the action slot will be used.") + // TODO add note about emotes when they're available in update 4 + .examples("play animation \"Death\" on player", + "play action animation \"Eat\" on target entity of player", + "play movement animation \"Jump\" on player") + .since("INSERT VERSION") + .register(); + } + + private Expression animation; + private Expression slot; + private Expression owners; + + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression @NotNull [] expressions, int matchedPattern, @NotNull ParseContext parseContext) { + if (matchedPattern == 0) { + this.animation = (Expression) expressions[0]; + this.owners = expressions[1]; + } else { + this.slot = (Expression) expressions[0]; + this.animation = (Expression) expressions[1]; + this.owners = expressions[2]; + } + return true; + } + + @Override + protected void execute(@NotNull TriggerContext ctx) { + String animation = this.animation.getSingle(ctx).orElse(null); + if (animation == null) return; + + AnimationSlot slot = AnimationSlot.Action; + if (this.slot != null) { + Optional single = this.slot.getSingle(ctx); + if (single.isPresent()) slot = single.get(); + } + + for (Object o : this.owners.getArray(ctx)) { + Ref ref = EntityReferenceUtils.getRef(o); + if (ref == null) continue; + + Store store = ref.getStore(); + + AnimationUtils.playAnimation(ref, slot, animation, true, store); + } + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + if (this.slot != null) { + return "play animation " + this.animation.toString(ctx, debug) + + " in " + this.slot.toString(ctx, debug) + " slot on " + this.owners.toString(ctx, debug); + } + return "play animation " + this.animation.toString(ctx, debug) + + " on " + this.owners.toString(ctx, debug); + } + +} diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/inventory/EvtItemStackSlotTransaction.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/inventory/EvtItemStackSlotTransaction.java index 1e26a281..0337ee65 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/inventory/EvtItemStackSlotTransaction.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/inventory/EvtItemStackSlotTransaction.java @@ -17,7 +17,7 @@ public class EvtItemStackSlotTransaction extends SkriptEvent { public static void register(SkriptRegistration reg) { reg.newEvent(EvtItemStackSlotTransaction.class, "inventory item[stack] slot transaction") - .name("Inventory Item Slot Transaction") + .name("Inventory ItemStack Slot Transaction") .description("Called when there is an inventory transaction involving an ItemStack in a slot.") .since("1.3.0") .setHandledContexts(ItemStackSlotContext.class) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/inventory/EvtSlotTransaction.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/inventory/EvtSlotTransaction.java index cfd36c8e..e637002c 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/inventory/EvtSlotTransaction.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/inventory/EvtSlotTransaction.java @@ -14,8 +14,8 @@ public class EvtSlotTransaction extends SkriptEvent { public static void register(SkriptRegistration reg) { reg.newEvent(EvtSlotTransaction.class, - "inventory item[stack] slot transaction") - .name("Inventory Item Slot Transaction") + "inventory slot transaction") + .name("Inventory Slot Transaction") .description("Called when there is an inventory transaction involving a slot.") .since("1.3.0") .setHandledContexts(SlotTransactionContext.class) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/skript/EvtLoad.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/skript/EvtLoad.java index f08a9955..d79f3fbb 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/skript/EvtLoad.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/skript/EvtLoad.java @@ -1,13 +1,14 @@ package com.github.skriptdev.skript.plugin.elements.events.skript; import io.github.syst3ms.skriptparser.lang.Expression; +import io.github.syst3ms.skriptparser.lang.Statement; import io.github.syst3ms.skriptparser.lang.Trigger; import io.github.syst3ms.skriptparser.lang.TriggerContext; -import io.github.syst3ms.skriptparser.lang.TriggerMap; import io.github.syst3ms.skriptparser.lang.event.SkriptEvent; import io.github.syst3ms.skriptparser.lang.event.StartOnLoadEvent; import io.github.syst3ms.skriptparser.parsing.ParseContext; import io.github.syst3ms.skriptparser.registration.SkriptRegistration; +import io.github.syst3ms.skriptparser.variables.Variables; import org.jetbrains.annotations.Nullable; public class EvtLoad extends SkriptEvent implements StartOnLoadEvent { @@ -38,7 +39,9 @@ public String toString(@Nullable TriggerContext ctx, boolean debug) { @Override public void onInitialLoad(Trigger trigger) { - TriggerMap.callTriggersByContext(new ScriptLoadContext()); + ScriptLoadContext scriptLoadContext = new ScriptLoadContext(); + Statement.runAll(trigger, scriptLoadContext); + Variables.clearLocalVariables(scriptLoadContext); } private static class ScriptLoadContext implements TriggerContext { diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/skript/EvtPeriodical.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/skript/EvtPeriodical.java index 30096ad8..9b884d98 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/skript/EvtPeriodical.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/skript/EvtPeriodical.java @@ -7,14 +7,15 @@ import com.hypixel.hytale.server.core.universe.world.World; import io.github.syst3ms.skriptparser.lang.Expression; import io.github.syst3ms.skriptparser.lang.Literal; +import io.github.syst3ms.skriptparser.lang.Statement; import io.github.syst3ms.skriptparser.lang.Trigger; import io.github.syst3ms.skriptparser.lang.TriggerContext; -import io.github.syst3ms.skriptparser.lang.TriggerMap; import io.github.syst3ms.skriptparser.lang.VariableString; import io.github.syst3ms.skriptparser.lang.event.SkriptEvent; import io.github.syst3ms.skriptparser.lang.event.StartOnLoadEvent; import io.github.syst3ms.skriptparser.log.ErrorType; import io.github.syst3ms.skriptparser.parsing.ParseContext; +import io.github.syst3ms.skriptparser.variables.Variables; import java.time.Duration; import java.util.concurrent.ScheduledFuture; @@ -73,7 +74,11 @@ public void onInitialLoad(Trigger trigger) { Duration dur = this.duration.getSingle().orElseThrow(AssertionError::new); long durationMillis = dur.toMillis(); - Runnable runTrigger = () -> TriggerMap.callTriggersByContext(new PeriodicalContext(this.world)); + Runnable runTrigger = () -> { + PeriodicalContext periodicalContext = new PeriodicalContext(this.world); + Statement.runAll(trigger, periodicalContext); + Variables.clearLocalVariables(periodicalContext); + }; this.scheduledFuture = HytaleServer.SCHEDULED_EXECUTOR.scheduleAtFixedRate(() -> { if (this.world != null) { diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/world/EvtAtWorldTime.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/world/EvtAtWorldTime.java index 07af6ff4..fccab489 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/events/world/EvtAtWorldTime.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/events/world/EvtAtWorldTime.java @@ -10,15 +10,16 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import io.github.syst3ms.skriptparser.lang.Expression; import io.github.syst3ms.skriptparser.lang.Literal; +import io.github.syst3ms.skriptparser.lang.Statement; import io.github.syst3ms.skriptparser.lang.Trigger; import io.github.syst3ms.skriptparser.lang.TriggerContext; -import io.github.syst3ms.skriptparser.lang.TriggerMap; import io.github.syst3ms.skriptparser.lang.VariableString; import io.github.syst3ms.skriptparser.lang.event.SkriptEvent; import io.github.syst3ms.skriptparser.lang.event.StartOnLoadEvent; import io.github.syst3ms.skriptparser.log.ErrorType; import io.github.syst3ms.skriptparser.parsing.ParseContext; import io.github.syst3ms.skriptparser.util.Time; +import io.github.syst3ms.skriptparser.variables.Variables; import org.jetbrains.annotations.NotNull; import java.util.Optional; @@ -85,7 +86,9 @@ public void onInitialLoad(Trigger trigger) { // Check every in-world minute for a match if (time.getHour() != worldTime.getHour() || time.getMinute() != worldTime.getMinute()) return; - TriggerMap.callTriggersByContext(new WorldTimeContext(this.world)); + WorldTimeContext worldTimeContext = new WorldTimeContext(this.world); + Statement.runAll(trigger, worldTimeContext); + Variables.clearLocalVariables(worldTimeContext); }), 0, duration, TimeUnit.MILLISECONDS); } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/ExpressionHandler.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/ExpressionHandler.java index daaca6d9..159413ee 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/ExpressionHandler.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/ExpressionHandler.java @@ -15,8 +15,11 @@ import com.github.skriptdev.skript.plugin.elements.expressions.block.ExprTargetBlockOfPlayer; import com.github.skriptdev.skript.plugin.elements.expressions.entity.ExprActiveSlot; import com.github.skriptdev.skript.plugin.elements.expressions.entity.ExprEntitiesInRadius; +import com.github.skriptdev.skript.plugin.elements.expressions.entity.ExprEntityAnimations; import com.github.skriptdev.skript.plugin.elements.expressions.entity.ExprEntityAttitude; +import com.github.skriptdev.skript.plugin.elements.expressions.entity.ExprEntityBoundingBox; import com.github.skriptdev.skript.plugin.elements.expressions.entity.ExprEntityComponents; +import com.github.skriptdev.skript.plugin.elements.expressions.entity.ExprEntityFallDistance; import com.github.skriptdev.skript.plugin.elements.expressions.entity.ExprEntityHeadRotation; import com.github.skriptdev.skript.plugin.elements.expressions.entity.ExprEntityHealth; import com.github.skriptdev.skript.plugin.elements.expressions.entity.ExprEntityModel; @@ -117,8 +120,11 @@ public static void register(SkriptRegistration registration) { // ENTITY ExprActiveSlot.register(registration); ExprEntitiesInRadius.register(registration); + ExprEntityAnimations.register(registration); ExprEntityAttitude.register(registration); + ExprEntityBoundingBox.register(registration); ExprEntityComponents.register(registration); + ExprEntityFallDistance.register(registration); ExprEntityHeadRotation.register(registration); ExprEntityHealth.register(registration); ExprEntityModel.register(registration); diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityAnimations.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityAnimations.java new file mode 100644 index 00000000..f395b2bb --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityAnimations.java @@ -0,0 +1,68 @@ +package com.github.skriptdev.skript.plugin.elements.expressions.entity; + +import com.github.skriptdev.skript.api.hytale.utils.EntityReferenceUtils; +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.Store; +import com.hypixel.hytale.server.core.asset.type.model.config.Model; +import com.hypixel.hytale.server.core.asset.type.model.config.ModelAsset; +import com.hypixel.hytale.server.core.modules.entity.component.ModelComponent; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import io.github.syst3ms.skriptparser.lang.Expression; +import io.github.syst3ms.skriptparser.lang.TriggerContext; +import io.github.syst3ms.skriptparser.parsing.ParseContext; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +public class ExprEntityAnimations implements Expression { + + public static void register(SkriptRegistration reg) { + reg.newExpression(ExprEntityAnimations.class, String.class, + false, "animations of %entities/refs/modelassets%") + .name("Entity Animations") + .description("Get the animations of an Entity/Ref.", + "If using Entity/Ref this will return the possible animations of their current model component.") + .since("INSERT VERSION") + .register(); + } + + private Expression owners; + + @Override + public boolean init(Expression[] expressions, int matchedPattern, @NotNull ParseContext parseContext) { + this.owners = expressions[0]; + return true; + } + + @Override + public String[] getValues(@NotNull TriggerContext ctx) { + List animations = new ArrayList<>(); + for (Object owner : this.owners.getArray(ctx)) { + if (owner instanceof ModelAsset modelAsset) { + Model model = Model.createRandomScaleModel(modelAsset); + animations.addAll(model.getAnimationSetMap().keySet()); + } else { + Ref ref = EntityReferenceUtils.getRef(owner); + if (ref == null) { + return null; + } else { + Store store = ref.getStore(); + ModelComponent component = store.getComponent(ref, ModelComponent.getComponentType()); + if (component == null) return null; + + animations.addAll(component.getModel().getAnimationSetMap().keySet()); + } + } + } + + return animations.stream().sorted().toArray(String[]::new); + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + return "animations of " + this.owners.toString(ctx, debug); + } + +} diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityBoundingBox.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityBoundingBox.java new file mode 100644 index 00000000..d6e4cc7d --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityBoundingBox.java @@ -0,0 +1,66 @@ +package com.github.skriptdev.skript.plugin.elements.expressions.entity; + +import com.github.skriptdev.skript.api.hytale.utils.EntityReferenceUtils; +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.math.shape.Box; +import com.hypixel.hytale.server.core.modules.entity.component.BoundingBox; +import io.github.syst3ms.skriptparser.lang.TriggerContext; +import io.github.syst3ms.skriptparser.lang.properties.PropertyExpression; +import io.github.syst3ms.skriptparser.types.changers.ChangeMode; +import io.github.syst3ms.skriptparser.util.CollectionUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; + +public class ExprEntityBoundingBox extends PropertyExpression { + + public static void register(SkriptRegistration reg) { + reg.newPropertyExpression(ExprEntityBoundingBox.class, Box.class, + "entity bounding box", "entities/refs") + .name("Entity Bounding Box") + .description("Get/set the bounding box of an Entity/Ref.", + "This will use/return a Box object.", + "Changes may not be persistent on some objects, such as dropped items.") + .examples("set {_box} to entity bounding box of {_e}", + "set entity bounding box of {_e} to box(0, 0, 0, 1, 1, 1)") + .since("INSERT VERSION") + .register(); + } + + @Override + public @Nullable Box getProperty(@NotNull Object owner) { + BoundingBox component = EntityReferenceUtils.getComponent(owner, BoundingBox.getComponentType()); + if (component == null) return null; + + return component.getBoundingBox(); + } + + @Override + public Optional[]> acceptsChange(@NotNull ChangeMode mode) { + if (mode == ChangeMode.SET || mode == ChangeMode.DELETE) { + return CollectionUtils.optionalArrayOf(Box.class); + } + return Optional.empty(); + } + + @SuppressWarnings("ConstantValue") + @Override + public void change(@NotNull TriggerContext ctx, @NotNull ChangeMode changeMode, Object @NotNull [] changeWith) { + Box box = new Box(); + + if (changeWith != null && changeWith.length > 0 && changeWith[0] instanceof Box b) { + box = b; + } + + for (Object owner : getOwner().getArray(ctx)) { + if (changeMode == ChangeMode.SET) { + BoundingBox component = EntityReferenceUtils.ensureAndGetComponent(owner, BoundingBox.getComponentType()); + component.setBoundingBox(box); + } else { + EntityReferenceUtils.tryRemoveComponent(owner, BoundingBox.getComponentType()); + } + } + } + +} diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityComponents.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityComponents.java index 9556a11d..b5282cf4 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityComponents.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityComponents.java @@ -19,27 +19,34 @@ public class ExprEntityComponents implements Expression { public static void register(SkriptRegistration reg) { reg.newExpression(ExprEntityComponents.class, String.class, false, - "components of %entity%") + "components of %entity/ref%") .noDoc() .register(); } - private Expression entity; + private Expression entity; - @SuppressWarnings("unchecked") @Override public boolean init(Expression @NotNull [] expressions, int matchedPattern, @NotNull ParseContext parseContext) { - this.entity = (Expression) expressions[0]; + this.entity = expressions[0]; return true; } + @SuppressWarnings({"unchecked", "PatternVariableHidesField"}) @Override public String[] getValues(@NotNull TriggerContext ctx) { List components = new ArrayList<>(); - Entity entity = this.entity.getSingle(ctx).orElse(null); - if (entity == null) return null; + Object object = this.entity.getSingle(ctx).orElse(null); + if (object == null) return null; - Ref reference = entity.getReference(); + Ref reference; + if (object instanceof Entity entity) { + reference = entity.getReference(); + } else if (object instanceof Ref ref) { + reference = (Ref) ref; + } else { + return null; + } assert reference != null; Archetype archetype = reference.getStore().getArchetype(reference); diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityFallDistance.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityFallDistance.java new file mode 100644 index 00000000..ad649c69 --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityFallDistance.java @@ -0,0 +1,61 @@ +package com.github.skriptdev.skript.plugin.elements.expressions.entity; + +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.server.core.entity.LivingEntity; +import io.github.syst3ms.skriptparser.lang.TriggerContext; +import io.github.syst3ms.skriptparser.lang.properties.PropertyExpression; +import io.github.syst3ms.skriptparser.types.changers.ChangeMode; +import io.github.syst3ms.skriptparser.util.CollectionUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; + +public class ExprEntityFallDistance extends PropertyExpression { + + public static void register(SkriptRegistration reg) { + reg.newPropertyExpression(ExprEntityFallDistance.class, Number.class, + "fall distance", "livingentities") + .name("Entity Fall Distance") + .description("Get/set the fall distance of an entity.") + .examples("if fall distance of player > 10:", + "set fall distance of player to 10", + "add 1 to fall distance of player", + "remove 10 from fall distance of {_e}", + "clear fall distance of player") + .register(); + } + + @Override + public @Nullable Number getProperty(LivingEntity owner) { + return owner.getCurrentFallDistance(); + } + + @Override + public Optional[]> acceptsChange(@NotNull ChangeMode mode) { + if (mode == ChangeMode.SET || mode == ChangeMode.ADD || mode == ChangeMode.REMOVE || mode == ChangeMode.DELETE) { + return CollectionUtils.optionalArrayOf(Number.class); + } + return Optional.empty(); + } + + @SuppressWarnings("ConstantValue") + @Override + public void change(@NotNull TriggerContext ctx, @NotNull ChangeMode changeMode, Object @NotNull [] changeWith) { + double changeValue = 0; + if (changeWith != null && changeWith.length > 0 && changeWith[0] instanceof Number num) { + changeValue = num.doubleValue(); + } + + for (LivingEntity livingEntity : getOwner().getArray(ctx)) { + double current = livingEntity.getCurrentFallDistance(); + + double newValue = switch (changeMode) { + case ADD -> current + changeValue; + case REMOVE -> current - changeValue; + default -> changeValue; + }; + livingEntity.setCurrentFallDistance(Math.max(newValue, 0)); + } + } +} diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityScale.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityScale.java index 38eacd1b..06a9b188 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityScale.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprEntityScale.java @@ -2,8 +2,10 @@ import com.github.skriptdev.skript.api.hytale.utils.EntityUtils; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.server.core.entity.Entity; import com.hypixel.hytale.server.core.modules.entity.component.EntityScaleComponent; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import io.github.syst3ms.skriptparser.lang.TriggerContext; import io.github.syst3ms.skriptparser.lang.properties.PropertyExpression; import io.github.syst3ms.skriptparser.types.changers.ChangeMode; @@ -12,13 +14,13 @@ import java.util.Optional; -public class ExprEntityScale extends PropertyExpression { +public class ExprEntityScale extends PropertyExpression { public static void register(SkriptRegistration reg) { reg.newPropertyExpression(ExprEntityScale.class, Number.class, - "scale", "entities") + "scale", "entities/refs") .name("Entity Scale") - .description("Get/set the scale of an entity.", + .description("Get/set the scale of an Entity/Ref.", "**Note**: Changing the scale of a player does not affect their camera.") .examples("if scale of target entity of player > 1:", "set scale of {_e} to 10", @@ -29,11 +31,20 @@ public static void register(SkriptRegistration reg) { .register(); } + @SuppressWarnings("unchecked") @Override - public @Nullable Number getProperty(@NotNull Entity entity) { - EntityScaleComponent component = EntityUtils.getComponent(entity, EntityScaleComponent.getComponentType()); - if (component == null) return 1.0f; + public @Nullable Number getProperty(@NotNull Object o) { + EntityScaleComponent component; + if (o instanceof Entity entity) { + component = EntityUtils.getComponent(entity, EntityScaleComponent.getComponentType()); + } else if (o instanceof Ref r) { + Ref ref = (Ref) r; + component = ref.getStore().getComponent(ref, EntityScaleComponent.getComponentType()); + } else { + return null; + } + if (component == null) return 1.0f; return component.getScale(); } @@ -45,15 +56,23 @@ public Optional[]> acceptsChange(@NotNull ChangeMode mode) { return Optional.empty(); } - @SuppressWarnings("ConstantValue") + @SuppressWarnings({"ConstantValue", "unchecked"}) @Override public void change(@NotNull TriggerContext ctx, @NotNull ChangeMode changeMode, Object @NotNull [] changeWith) { if (changeWith == null || changeWith.length == 0 || !(changeWith[0] instanceof Number number)) { return; } - for (Entity entity : getOwner().getArray(ctx)) { - EntityScaleComponent component = EntityUtils.ensureAndGetComponent(entity, EntityScaleComponent.getComponentType()); + for (Object o : getOwner().getArray(ctx)) { + EntityScaleComponent component; + if (o instanceof Entity entity) { + component = EntityUtils.ensureAndGetComponent(entity, EntityScaleComponent.getComponentType()); + } else if (o instanceof Ref r) { + Ref ref = (Ref) r; + component = ref.getStore().ensureAndGetComponent(ref, EntityScaleComponent.getComponentType()); + } else { + continue; + } float oldValue = component.getScale(); float changeValue = number.floatValue(); diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprName.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprName.java index 15be814b..361877b1 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprName.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/entity/ExprName.java @@ -1,10 +1,14 @@ package com.github.skriptdev.skript.plugin.elements.expressions.entity; import com.github.skriptdev.skript.api.hytale.utils.EntityUtils; +import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.component.Store; import com.hypixel.hytale.server.core.entity.Entity; import com.hypixel.hytale.server.core.entity.entities.Player; +import com.hypixel.hytale.server.core.entity.nameplate.Nameplate; import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.world.World; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import io.github.syst3ms.skriptparser.lang.Expression; import io.github.syst3ms.skriptparser.lang.TriggerContext; import io.github.syst3ms.skriptparser.lang.properties.PropertyExpression; @@ -20,12 +24,12 @@ public class ExprName extends PropertyExpression { public static void register(SkriptRegistration registration) { registration.newPropertyExpression(ExprName.class, String.class, - "[:display] name[s]", "entities/players/playerrefs/worlds") + "[:display] name[s]", "entities/players/playerrefs/refs/worlds") .name("Name of Object") .description("Gets the name of an object.", - "Currently supports players, entities, and worlds.", + "Currently supports players, entities, refs, and worlds.", "Display name refers to the nameplate over an entity/player's head.", - "Display name of Entity/Player can be set. PlayerRef/World do not support setting.") + "Display name of Entity/Ref/Player can be set. PlayerRef/World do not support setting.") .examples("set {_name} to name of player", "set {_w} to name of world of player", "set display name of target entity of player to \"Mr Sheep\"") @@ -41,12 +45,19 @@ public boolean init(Expression @NotNull [] expressions, int matchedPattern, P return super.init(expressions, matchedPattern, parseContext); } + @SuppressWarnings("unchecked") @Override public @Nullable String getProperty(Object object) { return switch (object) { case PlayerRef playerRef -> playerRef.getUsername(); case Player player -> this.display ? EntityUtils.getName(player) : player.getDisplayName(); case Entity entity -> EntityUtils.getName(entity); + case Ref ref -> { + Ref reference = (Ref) ref; + Nameplate component = reference.getStore().getComponent(reference, Nameplate.getComponentType()); + if (component != null) yield component.getText(); + else yield null; + } case World world -> world.getName(); default -> null; }; @@ -59,7 +70,7 @@ public Optional[]> acceptsChange(@NotNull ChangeMode mode) { return Optional.empty(); } - @SuppressWarnings("ConstantValue") + @SuppressWarnings({"ConstantValue", "unchecked"}) @Override public void change(@NotNull TriggerContext ctx, @NotNull ChangeMode changeMode, Object @NotNull [] changeWith) { String name = null; @@ -71,6 +82,15 @@ public void change(@NotNull TriggerContext ctx, @NotNull ChangeMode changeMode, for (Object o : getOwner().getArray(ctx)) { if (o instanceof Entity entity) { EntityUtils.setNameplateName(entity, name); + } else if (o instanceof Ref ref) { + Ref reference = (Ref) ref; + Store store = reference.getStore(); + if (name != null) { + Nameplate component = store.ensureAndGetComponent(reference, Nameplate.getComponentType()); + component.setText(name); + } else { + store.tryRemoveComponent(reference, Nameplate.getComponentType()); + } } } } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/other/ExprCast.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/other/ExprCast.java index aaf6b9eb..4d83be39 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/other/ExprCast.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/other/ExprCast.java @@ -5,6 +5,7 @@ import io.github.syst3ms.skriptparser.lang.Literal; import io.github.syst3ms.skriptparser.lang.TriggerContext; import io.github.syst3ms.skriptparser.log.ErrorType; +import io.github.syst3ms.skriptparser.log.SkriptLogger; import io.github.syst3ms.skriptparser.parsing.ParseContext; import io.github.syst3ms.skriptparser.types.Type; import org.jetbrains.annotations.NotNull; @@ -27,33 +28,40 @@ public static void register(SkriptRegistration reg) { private String castable; private Type type; - private Function parser; + private Object parsedObject; @SuppressWarnings("unchecked") @Override public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { + SkriptLogger logger = parseContext.getLogger(); this.castable = parseContext.getMatches().getFirst().group(); Literal> expression = (Literal>) expressions[0]; this.type = expression.getSingle().orElse(null); if (this.type == null) { // This shouldn't happen, but let's be safe; - parseContext.getLogger().error("Type cannot be null for cast expression initialization.", ErrorType.SEMANTIC_ERROR); + logger.error("Type cannot be null for cast expression initialization.", ErrorType.SEMANTIC_ERROR); return false; } if (this.type.getLiteralParser().isEmpty()) { String baseName = this.type.getBaseName(); - parseContext.getLogger().error("The type '" + baseName + "' cannot be casted.", ErrorType.SEMANTIC_ERROR); + logger.error("The type '" + baseName + "' cannot be cast.", ErrorType.SEMANTIC_ERROR); + return false; + } + Function parser = this.type.getLiteralParser().get(); + // Let's parse at parse time so we don't have to worry about it during runtime + this.parsedObject = parser.apply(this.castable); + if (this.parsedObject == null) { + String baseName = this.type.getBaseName(); + logger.error("'" + this.castable + "' cannot be cast to " + baseName + ".", ErrorType.SEMANTIC_ERROR); return false; } - this.parser = this.type.getLiteralParser().get(); return true; } @Override public Object[] getValues(@NotNull TriggerContext ctx) { - Object apply = this.parser.apply(castable); - return new Object[]{apply}; + return new Object[]{this.parsedObject}; } @Override diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/other/ExprLocationDirection.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/other/ExprLocationDirection.java index 73ab9b7d..801820e7 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/other/ExprLocationDirection.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/other/ExprLocationDirection.java @@ -13,13 +13,11 @@ public class ExprLocationDirection implements Expression { public static void register(SkriptRegistration reg) { - // TODO its broken when not using "of" (parser issue) reg.newExpression(ExprLocationDirection.class, Location.class, true, "location %direction% [of] %location%", "location %number% [block[s]] %direction% [of] %location%") .name("Location Direction") - .description("Returns a location at the specified direction and location with an optional offset.", - "The parser is broken, and even thought 'of' is optional, you have to put it.") + .description("Returns a location at the specified direction and location with an optional offset.") .examples("set {_loc} to location above {_loc}", "set {_loc} to location 3 north of location of player", "set {_loc} to location 3 blocks below location of player") diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/world/ExprWorldTimeDurations.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/world/ExprWorldTimeDurations.java index b2409139..a060ec8d 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/world/ExprWorldTimeDurations.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/expressions/world/ExprWorldTimeDurations.java @@ -1,14 +1,19 @@ package com.github.skriptdev.skript.plugin.elements.expressions.world; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.github.skriptdev.skript.api.utils.ReflectionUtils; import com.hypixel.hytale.server.core.universe.world.World; import io.github.syst3ms.skriptparser.lang.Expression; +import io.github.syst3ms.skriptparser.lang.TriggerContext; import io.github.syst3ms.skriptparser.lang.properties.PropertyExpression; import io.github.syst3ms.skriptparser.parsing.ParseContext; +import io.github.syst3ms.skriptparser.types.changers.ChangeMode; +import io.github.syst3ms.skriptparser.util.CollectionUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.time.Duration; +import java.util.Optional; public class ExprWorldTimeDurations extends PropertyExpression { @@ -18,8 +23,11 @@ public static void register(SkriptRegistration reg) { .name("World Time Durations") .description("Represents the daytime/nighttime durations of a world.", "These values are from a GamePlayConfig but can be overridden in your World config.", - "**Note**: Currently these cannot be set via code.") - .examples("set {_Day} to world daytime duration of world of player") + "Set/add/remove/reset will update your world config with these values.") + .examples("set {_Day} to world daytime duration of world of player", + "set world daytime duration of {_world} to 1 hour", + "add 10 minutes to world daytime duration of {_world}", + "reset world daytime duration of {_world}") .since("1.1.0") .register(); } @@ -43,4 +51,53 @@ public boolean init(Expression @NotNull [] expressions, int matchedPattern, P return Duration.ofSeconds(seconds); } + @Override + public Optional[]> acceptsChange(ChangeMode mode) { + return switch (mode) { + case ADD, REMOVE, SET, RESET -> { + if (this.pattern == 2) { + // LOG + yield Optional.empty(); + } + yield CollectionUtils.optionalArrayOf(Duration.class); + } + default -> Optional.empty(); + }; + } + + @SuppressWarnings("ConstantValue") + @Override + public void change(@NotNull TriggerContext ctx, @NotNull ChangeMode changeMode, Object @NotNull [] changeWith) { + Duration duration = null; + if (changeWith != null && changeWith.length > 0 && changeWith[0] instanceof Duration d) { + duration = d; + } + + int durationSeconds; + if (duration == null) { + durationSeconds = 0; + } else { + durationSeconds = (int) duration.toMillis() / 1000; + } + + boolean daytime = this.pattern == 0; + for (World world : getOwner().getArray(ctx)) { + int previons; + if (daytime) { + previons = world.getDaytimeDurationSeconds(); + } else { + previons = world.getNighttimeDurationSeconds(); + } + + Integer seconds = switch (changeMode) { + case ADD -> previons + durationSeconds; + case REMOVE -> previons - durationSeconds; + case SET -> durationSeconds; + default -> null; + }; + + ReflectionUtils.setWorldTimeOverrides(world, seconds, daytime); + } + } + } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/functions/DefaultFunctions.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/functions/DefaultFunctions.java index 136859e4..bcdd462f 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/functions/DefaultFunctions.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/functions/DefaultFunctions.java @@ -1,6 +1,7 @@ package com.github.skriptdev.skript.plugin.elements.functions; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.math.shape.Box; import com.hypixel.hytale.math.vector.Location; import com.hypixel.hytale.math.vector.Vector3d; import com.hypixel.hytale.math.vector.Vector3f; @@ -212,6 +213,24 @@ private static void mathFunctions(SkriptRegistration reg) { } private static void positionFunctions(SkriptRegistration reg) { + reg.newJavaFunction("box", Box.class, true) + .parameter("x1", Number.class) + .parameter("y1", Number.class) + .parameter("z1", Number.class) + .parameter("x2", Number.class) + .parameter("y2", Number.class) + .parameter("z2", Number.class) + .executeSingle(params -> { + Number x1 = (Number) params[0][0]; + Number y1 = (Number) params[1][0]; + Number z1 = (Number) params[2][0]; + Number x2 = (Number) params[3][0]; + Number y2 = (Number) params[4][0]; + Number z2 = (Number) params[5][0]; + return new Box(x1.doubleValue(), y1.doubleValue(), z1.doubleValue(), + x2.doubleValue(), y2.doubleValue(), z2.doubleValue()); + }) + .register(); reg.newJavaFunction("location", Location.class, true) .parameter("x", Number.class) .parameter("y", Number.class) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SectionHandler.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SectionHandler.java index 53faa6fc..df008312 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SectionHandler.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/SectionHandler.java @@ -3,6 +3,7 @@ import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.github.skriptdev.skript.plugin.elements.sections.entity.SecApplyStatModifier; import com.github.skriptdev.skript.plugin.elements.sections.entity.SecDropItem; +import com.github.skriptdev.skript.plugin.elements.sections.entity.SecSpawnDisplay; import com.github.skriptdev.skript.plugin.elements.sections.entity.SecSpawnNPC; import com.github.skriptdev.skript.plugin.elements.sections.player.SecPlaySound; import com.github.skriptdev.skript.plugin.elements.sections.player.SecSendNotification; @@ -18,6 +19,7 @@ public static void register(SkriptRegistration registration) { // ENTITY SecApplyStatModifier.register(registration); SecDropItem.register(registration); + SecSpawnDisplay.register(registration); SecSpawnNPC.register(registration); // PLAYER diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/entity/SecSpawnDisplay.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/entity/SecSpawnDisplay.java new file mode 100644 index 00000000..35191149 --- /dev/null +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/entity/SecSpawnDisplay.java @@ -0,0 +1,106 @@ +package com.github.skriptdev.skript.plugin.elements.sections.entity; + +import com.github.skriptdev.skript.api.hytale.utils.EntityUtils; +import com.github.skriptdev.skript.api.skript.event.RefContext; +import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; +import com.hypixel.hytale.component.Ref; +import com.hypixel.hytale.math.vector.Location; +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; +import io.github.syst3ms.skriptparser.lang.CodeSection; +import io.github.syst3ms.skriptparser.lang.Expression; +import io.github.syst3ms.skriptparser.lang.Statement; +import io.github.syst3ms.skriptparser.lang.TriggerContext; +import io.github.syst3ms.skriptparser.parsing.ParseContext; +import io.github.syst3ms.skriptparser.parsing.ParserState; +import io.github.syst3ms.skriptparser.variables.Variables; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; + +public class SecSpawnDisplay extends CodeSection { + + public static void register(SkriptRegistration reg) { + reg.newSection(SecSpawnDisplay.class, + "spawn display item %item% at %location%", + "spawn display block %blocktype% at %location%", + "spawn display model %modelasset% at %location%") + .name("Spawn Display") + .description("Spawn an item at a location.") + .examples("spawn display item ingredient_poop at {_loc}:", + "\tset {_e} to event-ref", + "\tset scale of {_e} to 10") + .since("INSERT VERSION") + .register(); + } + + int pattern; + private Expression model; + private Expression location; + + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] expressions, int matchedPattern, @NotNull ParseContext parseContext) { + this.pattern = matchedPattern; + this.model = expressions[0]; + this.location = (Expression) expressions[1]; + + ParserState parserState = parseContext.getParserState(); + List> triggerContexts = new ArrayList<>(parserState.getCurrentContexts().stream().toList()); + triggerContexts.add(ModelContext.class); + parserState.setCurrentContexts(new HashSet<>(triggerContexts)); + + return true; + } + + @Override + public Optional walk(@NotNull TriggerContext ctx) { + Optional nextStatement = getNext(); + + Object o = this.model.getSingle(ctx).orElse(null); + Location location = this.location.getSingle(ctx).orElse(null); + if (o == null || location == null) return nextStatement; + + Ref ref = EntityUtils.spawnModel(o, location); + Optional first = getFirst(); + + if (ref != null && first.isPresent()) { + ModelContext modelContext = new ModelContext(ref); + Variables.copyLocalVariables(ctx, modelContext); + Statement.runAll(first.get(), modelContext); + Variables.copyLocalVariables(modelContext, ctx); + Variables.clearLocalVariables(modelContext); + } + return nextStatement; + } + + @Override + public String toString(@NotNull TriggerContext ctx, boolean debug) { + String type = switch (this.pattern) { + case 1 -> "block"; + case 2 -> "model"; + default -> "item"; + }; + return "spawn display " + type + " " + this.model.toString(ctx, debug) + " at " + this.location.toString(ctx, debug); + } + + public static class ModelContext implements RefContext { + private final Ref ref; + + public ModelContext(Ref ref) { + this.ref = ref; + } + + public Ref getRef() { + return this.ref; + } + + @Override + public String getName() { + return "model context"; + } + } + +} diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/world/SecExecuteInWorld.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/world/SecExecuteInWorld.java index 975a5a5a..354bd6e1 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/world/SecExecuteInWorld.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/sections/world/SecExecuteInWorld.java @@ -1,5 +1,6 @@ package com.github.skriptdev.skript.plugin.elements.sections.world; +import com.github.skriptdev.skript.api.skript.event.WorldContext; import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.hypixel.hytale.server.core.universe.world.World; import io.github.syst3ms.skriptparser.lang.CodeSection; @@ -20,7 +21,7 @@ public static void register(SkriptRegistration registration) { .name("Execute In World") .description("Executes the code inside the section in the specified world.") .examples("execute in world of player:", - "\tkill player") + "\tkill all players in event-world") .since("1.0.0") .register(); } @@ -45,13 +46,14 @@ public Optional walk(@NotNull TriggerContext ctx) { VariableMap variableMap = Variables.copyLocalVariables(ctx); Statement firstStatement = first.get(); worldOptional.ifPresent(world -> world.execute(() -> { - // Place the variables back into the original context + // Place the variables back into the new context // This is done in case World#execute is delayed - Variables.setLocalVariables(ctx, variableMap); - Statement.runAll(firstStatement, ctx); + ExecuteInWorldContext worldContext = new ExecuteInWorldContext(world); + Variables.setLocalVariables(worldContext, variableMap); + Statement.runAll(firstStatement, worldContext); // Clear out old variables - Variables.clearLocalVariables(ctx); + Variables.clearLocalVariables(worldContext); })); } return getNext(); @@ -62,4 +64,16 @@ public String toString(@NotNull TriggerContext ctx, boolean debug) { return "execute in world " + this.world.toString(ctx, debug); } + public record ExecuteInWorldContext(World world) implements WorldContext { + @Override + public World getWorld() { + return this.world; + } + + @Override + public String getName() { + return "execute in world context"; + } + } + } diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesEntity.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesEntity.java index bce3364d..785593ed 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesEntity.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesEntity.java @@ -5,6 +5,7 @@ import com.github.skriptdev.skript.api.skript.registration.SkriptRegistration; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.RemoveReason; +import com.hypixel.hytale.protocol.AnimationSlot; import com.hypixel.hytale.server.core.asset.type.attitude.Attitude; import com.hypixel.hytale.server.core.entity.Entity; import com.hypixel.hytale.server.core.entity.LivingEntity; @@ -57,6 +58,11 @@ static void register(SkriptRegistration reg) { .since("1.0.0") .toStringFunction(ActiveEntityEffect::toString) .register(); + reg.newEnumType(AnimationSlot.class, "animationslot", "animationSlot@s") + .name("Animation Slot") + .description("Represents the slot for an animation to be played on an entity.") + .since("INSERT VERSION") + .register(); reg.newEnumType(Attitude.class, "attitude", "attitude@s") .name("Attitude") .description("Represents the attitude of an NPC Entity towards another entity.") @@ -89,7 +95,6 @@ static void register(SkriptRegistration reg) { reg.newType(NPCRegistry.NPCRole.class, "npcrole", "npcrole@s") .name("NPC Role") .description("Represents the type of NPCs in the game.") - .examples("coming soon") // TODO .usage(NPCRegistry.getTypeUsage()) .since("1.0.0") .toStringFunction(NPCRegistry.NPCRole::name) diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesServer.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesServer.java index b6c53d73..a3cfea94 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesServer.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesServer.java @@ -5,6 +5,7 @@ import com.google.gson.Gson; import com.google.gson.JsonElement; import com.hypixel.hytale.codec.ExtraInfo; +import com.hypixel.hytale.math.shape.Box; import com.hypixel.hytale.math.vector.Location; import com.hypixel.hytale.math.vector.Vector3d; import com.hypixel.hytale.math.vector.Vector3f; @@ -16,6 +17,7 @@ import com.hypixel.hytale.server.core.Message; import com.hypixel.hytale.server.core.command.system.CommandSender; import com.hypixel.hytale.server.core.command.system.arguments.types.ArgumentType; +import com.hypixel.hytale.server.core.modules.entity.component.BoundingBox; import com.hypixel.hytale.server.core.modules.entity.damage.Damage; import com.hypixel.hytale.server.core.receiver.IMessageReceiver; import com.hypixel.hytale.server.core.util.MessageUtil; @@ -34,6 +36,10 @@ static void register(SkriptRegistration registration) { .usage(ArgUtils.getTypeUsage()) .since("1.0.0") .register(); + registration.newType(BoundingBox.class, "boundingbox", "boundingBox@es") + .register(); + registration.newType(Box.class, "box", "box@es") + .register(); registration.newType(CommandSender.class, "commandsender", "commandSender@s") .name("Command Sender") .description("Represents a command sender such as a player or the console.") diff --git a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesWorld.java b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesWorld.java index 8f7357d8..d101fd17 100644 --- a/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesWorld.java +++ b/src/main/java/com/github/skriptdev/skript/plugin/elements/types/TypesWorld.java @@ -7,6 +7,7 @@ import com.hypixel.hytale.protocol.SoundCategory; import com.hypixel.hytale.server.core.command.system.arguments.types.RelativeDoublePosition; import com.hypixel.hytale.server.core.command.system.arguments.types.RelativeIntPosition; +import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; import com.hypixel.hytale.server.worldgen.zone.Zone; @@ -50,6 +51,10 @@ public Class[] acceptsChange(@NotNull ChangeMode mode) { public void change(Ref @NotNull [] toChange, Object @NotNull [] changeWith, @NotNull ChangeMode mode) { for (Ref ref : toChange) { Store store = ref.getStore(); + if (store.getComponent(ref, Player.getComponentType()) != null) { + // Don't allow deleting players + continue; + } store.removeEntity(ref, RemoveReason.REMOVE); } }