diff --git a/src/main/java/io/github/fusionflux/portalcubed/content/prop/PropDispenseBehavior.java b/src/main/java/io/github/fusionflux/portalcubed/content/prop/PropDispenseBehavior.java index 2e410e92..2ab3e5f0 100644 --- a/src/main/java/io/github/fusionflux/portalcubed/content/prop/PropDispenseBehavior.java +++ b/src/main/java/io/github/fusionflux/portalcubed/content/prop/PropDispenseBehavior.java @@ -1,11 +1,17 @@ package io.github.fusionflux.portalcubed.content.prop; +import io.github.fusionflux.portalcubed.content.prop.entity.Prop; +import net.minecraft.core.BlockPos; + +import net.minecraft.world.entity.EntitySpawnReason; + +import net.minecraft.world.level.gameevent.GameEvent; + import org.jetbrains.annotations.NotNull; import net.minecraft.core.Direction; import net.minecraft.core.dispenser.BlockSource; import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; -import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.DispenserBlock; @@ -18,13 +24,22 @@ public PropDispenseBehavior(PropItem item) { @Override @NotNull - protected ItemStack execute(BlockSource pointer, ItemStack stack) { + protected ItemStack execute(BlockSource source, ItemStack stack) { if (!stack.is(this.item)) return stack; - ServerLevel level = pointer.level(); - Direction direction = pointer.state().getValue(DispenserBlock.FACING); - this.item.use(level, pointer.pos().relative(direction), stack, null); + // based on DispenseItemBehavior for SpawnEggItems + Direction direction = source.state().getValue(DispenserBlock.FACING); + BlockPos pos = source.pos().relative(direction); + Integer variant = PropItem.getVariant(stack); + + Prop prop = this.item.type.spawn(source.level(), pos, stack, null, EntitySpawnReason.DISPENSER, variant, direction != Direction.UP, false); + + stack.shrink(1); // intentionally not in the if statement + if (prop != null) { + prop.gameEvent(GameEvent.ENTITY_PLACE, null); + } + return stack; } } diff --git a/src/main/java/io/github/fusionflux/portalcubed/content/prop/PropItem.java b/src/main/java/io/github/fusionflux/portalcubed/content/prop/PropItem.java index b573fa62..2af66c86 100644 --- a/src/main/java/io/github/fusionflux/portalcubed/content/prop/PropItem.java +++ b/src/main/java/io/github/fusionflux/portalcubed/content/prop/PropItem.java @@ -1,14 +1,16 @@ package io.github.fusionflux.portalcubed.content.prop; import java.util.List; -import java.util.Optional; + +import io.github.fusionflux.portalcubed.content.prop.entity.Prop; + +import net.minecraft.world.entity.EntitySpawnReason; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import io.github.fusionflux.portalcubed.content.PortalCubedDataComponents; import net.minecraft.ChatFormatting; -import net.minecraft.Optionull; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; @@ -24,7 +26,7 @@ import net.minecraft.world.level.gameevent.GameEvent; public class PropItem extends Item { - private final PropType type; + public final PropType type; public PropItem(Properties settings, PropType type) { super(settings); @@ -34,56 +36,53 @@ public PropItem(Properties settings, PropType type) { @Override @NotNull public InteractionResult useOn(UseOnContext context) { - if (context.getLevel() instanceof ServerLevel world) { - BlockPos clickedPos = context.getClickedPos(); - Direction clickedFace = context.getClickedFace(); - BlockState state = world.getBlockState(clickedPos); - // TODO: rework this when the game launches -// boolean invertY = false; -// if (!state.getCollisionShape(world, clickedPos).isEmpty()) { -// clickedPos = clickedPos.relative(clickedFace); -// invertY = clickedFace == Direction.UP; -// } - - this.use(world, clickedPos, context.getItemInHand(), context.getPlayer()); + if (!(context.getLevel() instanceof ServerLevel level)) return InteractionResult.SUCCESS; + + // based on SpawnEggItem + ItemStack held = context.getItemInHand(); + BlockPos pos = context.getClickedPos(); + Direction face = context.getClickedFace(); + BlockState state = level.getBlockState(pos); + Player player = context.getPlayer(); + + BlockPos effectivePos = pos; + if (!state.getCollisionShape(level, pos).isEmpty()) { + effectivePos = pos.relative(face); + } + + boolean offsetYMore = !pos.equals(effectivePos) && face == Direction.UP; + + Integer variant = getVariant(held); + Prop prop = this.type.spawn(level, effectivePos, held, player, EntitySpawnReason.SPAWN_ITEM_USE, variant, true, offsetYMore); + if (prop != null) { + held.shrink(1); + prop.gameEvent(GameEvent.ENTITY_PLACE, player); } + return InteractionResult.SUCCESS; } @Override @NotNull public Component getName(ItemStack stack) { - return getVariant(stack) - .map(variant -> (Component) Component.translatable(this.getDescriptionId() + "." + variant)) - .orElseGet(() -> super.getName(stack)); + Integer variant = getVariant(stack); + return variant == null ? super.getName(stack) : Component.translatable(this.getDescriptionId() + "." + variant); } @Override public void appendHoverText(ItemStack stack, TooltipContext context, List tooltipComponents, TooltipFlag flag) { super.appendHoverText(stack, context, tooltipComponents, flag); - if (flag.isCreative() && (this.type.randomVariantOnSpawn && getVariant(stack).isEmpty())) - tooltipComponents.add(translate("tooltip.random").withStyle(ChatFormatting.GRAY)); - } - - public boolean use(ServerLevel world, BlockPos pos, ItemStack stack, @Nullable Player spawner) { - Optional maybeVariant = getVariant(stack); - return Optionull.mapOrDefault( - this.type.spawn(world, pos, stack, spawner, maybeVariant.orElse(0), maybeVariant.isEmpty()), - prop -> { - stack.shrink(1); - prop.gameEvent(GameEvent.ENTITY_PLACE, spawner); - return true; - }, - false - ); + if (flag.isCreative() && (this.type.randomVariantOnSpawn && getVariant(stack) == null)) + tooltipComponents.add(this.translate("tooltip.random").withStyle(ChatFormatting.GRAY)); } - public MutableComponent translate(String key) { + private MutableComponent translate(String key) { return Component.translatable(this.getDescriptionId() + "." + key); } - public static Optional getVariant(ItemStack stack) { - return Optional.ofNullable(stack.get(PortalCubedDataComponents.PROP_VARIANT)); + @Nullable + public static Integer getVariant(ItemStack stack) { + return stack.get(PortalCubedDataComponents.PROP_VARIANT); } } diff --git a/src/main/java/io/github/fusionflux/portalcubed/content/prop/PropType.java b/src/main/java/io/github/fusionflux/portalcubed/content/prop/PropType.java index 2eb5e26f..8a0f223f 100644 --- a/src/main/java/io/github/fusionflux/portalcubed/content/prop/PropType.java +++ b/src/main/java/io/github/fusionflux/portalcubed/content/prop/PropType.java @@ -3,6 +3,8 @@ import java.util.Locale; import java.util.function.Consumer; +import net.minecraft.Util; + import org.apache.commons.lang3.stream.IntStreams; import org.jetbrains.annotations.Nullable; @@ -92,19 +94,26 @@ public EntityType entityType() { } @Nullable - public Prop spawn(ServerLevel world, BlockPos pos, @Nullable ItemStack stack, @Nullable Player player, int variant, boolean randomizeVariant) { + public Prop spawn(ServerLevel level, BlockPos pos, @Nullable ItemStack stack, @Nullable Player player, + EntitySpawnReason reason, @Nullable Integer variant, boolean offsetY, boolean offsetYMore) { Consumer consumer = prop -> { - prop.setVariantFromItem(variant); - prop.setVariant(!(randomizeVariant && randomVariantOnSpawn) ? variant : world.random.nextInt(variants.length - 1) + 1); + prop.setVariantFromItem(variant != null ? variant : 0); + boolean randomize = variant == null; + if (randomize && this.randomVariantOnSpawn) { + int randomVariant = Util.getRandom(this.variants, prop.getRandom()); + prop.setVariant(randomVariant); + } else { + prop.setVariant(variant != null ? variant : 0); + } }; return this.entityType().spawn( - world, - stack != null ? EntityType.appendDefaultStackConfig(consumer, world, stack, player) : consumer, + level, + stack != null ? EntityType.appendDefaultStackConfig(consumer, level, stack, player) : consumer, pos, - EntitySpawnReason.SPAWN_ITEM_USE, - true, - true + reason, + offsetY, + offsetYMore ); }