Added muffins

This commit is contained in:
Sollace 2022-03-27 16:02:14 +02:00
parent 83b110a8d3
commit 2c77cfb4c3
18 changed files with 358 additions and 68 deletions

View file

@ -87,17 +87,19 @@ public abstract class AbstractDelegatingSpell implements ProjectileSpell {
return execute(getDelegates().stream(), spell -> spell.tick(source, situation)); return execute(getDelegates().stream(), spell -> spell.tick(source, situation));
} }
@SuppressWarnings("unchecked")
@Override @Override
public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) { public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {
getDelegates().stream().filter(a -> a instanceof ProjectileDelegate).forEach(a -> { getDelegates().stream().filter(a -> a instanceof ProjectileDelegate).forEach(a -> {
((ProjectileDelegate)a).onImpact(projectile, pos, state); ((ProjectileDelegate<MagicProjectileEntity>)a).onImpact(projectile, pos, state);
}); });
} }
@SuppressWarnings("unchecked")
@Override @Override
public void onImpact(MagicProjectileEntity projectile, Entity entity) { public void onImpact(MagicProjectileEntity projectile, Entity entity) {
getDelegates().stream().filter(a -> a instanceof ProjectileDelegate).forEach(a -> { getDelegates().stream().filter(a -> a instanceof ProjectileDelegate).forEach(a -> {
((ProjectileDelegate)a).onImpact(projectile, entity); ((ProjectileDelegate<MagicProjectileEntity>)a).onImpact(projectile, entity);
}); });
} }

View file

@ -10,7 +10,7 @@ import net.minecraft.util.math.BlockPos;
/** /**
* Magic effects that can be thrown. * Magic effects that can be thrown.
*/ */
public interface ProjectileSpell extends Spell, ProjectileDelegate { public interface ProjectileSpell extends Spell, ProjectileDelegate<MagicProjectileEntity> {
@Override @Override
default void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) { default void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {

View file

@ -24,6 +24,7 @@ import net.minecraft.entity.FallingBlockEntity;
import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.PersistentProjectileEntity; import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtCompound;
import net.minecraft.particle.ParticleTypes; import net.minecraft.particle.ParticleTypes;
@ -197,6 +198,7 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileSpell
return 10 + Math.min(15, Math.min(0.5F + pulse, (float)Math.exp(age) / 8F - 90) + accumulatedMass / 10F) + pulse; return 10 + Math.min(15, Math.min(0.5F + pulse, (float)Math.exp(age) / 8F - 90) + accumulatedMass / 10F) + pulse;
} }
@SuppressWarnings("unchecked")
@Override @Override
protected void applyRadialEffect(Caster<?> source, Entity target, double distance, double radius) { protected void applyRadialEffect(Caster<?> source, Entity target, double distance, double radius) {
@ -213,7 +215,7 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileSpell
if (target instanceof MagicProjectileEntity) { if (target instanceof MagicProjectileEntity) {
Item item = ((MagicProjectileEntity)target).getStack().getItem(); Item item = ((MagicProjectileEntity)target).getStack().getItem();
if (item instanceof ProjectileDelegate && master != null) { if (item instanceof ProjectileDelegate && master != null) {
((ProjectileDelegate) item).onImpact(((MagicProjectileEntity)target), master); ((ProjectileDelegate<ProjectileEntity>) item).onImpact(((ProjectileEntity)target), master);
} }
} else if (target instanceof PersistentProjectileEntity) { } else if (target instanceof PersistentProjectileEntity) {
if (master != null) { if (master != null) {

View file

@ -71,6 +71,7 @@ public interface URenderers {
AccessoryFeatureRenderer.register(BatWingsFeatureRenderer::new); AccessoryFeatureRenderer.register(BatWingsFeatureRenderer::new);
EntityRendererRegistry.register(UEntities.THROWN_ITEM, FlyingItemEntityRenderer::new); EntityRendererRegistry.register(UEntities.THROWN_ITEM, FlyingItemEntityRenderer::new);
EntityRendererRegistry.register(UEntities.MUFFIN, FlyingItemEntityRenderer::new);
EntityRendererRegistry.register(UEntities.MAGIC_BEAM, MagicBeamEntityRenderer::new); EntityRendererRegistry.register(UEntities.MAGIC_BEAM, MagicBeamEntityRenderer::new);
EntityRendererRegistry.register(UEntities.BUTTERFLY, ButterflyEntityRenderer::new); EntityRendererRegistry.register(UEntities.BUTTERFLY, ButterflyEntityRenderer::new);
EntityRendererRegistry.register(UEntities.FLOATING_ARTEFACT, FloatingArtefactEntityRenderer::new); EntityRendererRegistry.register(UEntities.FLOATING_ARTEFACT, FloatingArtefactEntityRenderer::new);

View file

@ -0,0 +1,147 @@
package com.minelittlepony.unicopia.entity;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.ability.magic.Caster;
import net.minecraft.block.BlockState;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.FlyingItemEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.MovementType;
import net.minecraft.entity.data.DataTracker;
import net.minecraft.entity.data.TrackedData;
import net.minecraft.entity.data.TrackedDataHandlerRegistry;
import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.GameRules;
import net.minecraft.world.World;
import net.minecraft.world.event.GameEvent;
public class PhysicsBodyProjectileEntity extends PersistentProjectileEntity implements FlyingItemEntity {
private static final TrackedData<ItemStack> ITEM = DataTracker.registerData(PhysicsBodyProjectileEntity.class, TrackedDataHandlerRegistry.ITEM_STACK);
private static final TrackedData<Boolean> BOUNCY = DataTracker.registerData(PhysicsBodyProjectileEntity.class, TrackedDataHandlerRegistry.BOOLEAN);
public PhysicsBodyProjectileEntity(EntityType<PhysicsBodyProjectileEntity> type, World world) {
super(type, world);
}
public PhysicsBodyProjectileEntity(World world) {
this(UEntities.MUFFIN, world);
}
public PhysicsBodyProjectileEntity(World world, @Nullable LivingEntity thrower) {
super(UEntities.MUFFIN, thrower, world);
}
@Override
protected void initDataTracker() {
super.initDataTracker();
getDataTracker().startTracking(ITEM, ItemStack.EMPTY);
getDataTracker().startTracking(BOUNCY, false);
}
public void setStack(ItemStack stack) {
getDataTracker().set(ITEM, stack);
}
@Override
public ItemStack getStack() {
return getDataTracker().get(ITEM);
}
@Override
protected ItemStack asItemStack() {
return getStack();
}
public void setBouncy() {
getDataTracker().set(BOUNCY, true);
}
public boolean isBouncy() {
return getDataTracker().get(BOUNCY);
}
@Override
public void tick() {
super.tick();
if (inGround) {
Vec3d vel = getVelocity();
vel = vel.multiply(0, 1, 0);
move(MovementType.SELF, vel);
setVelocity(vel.multiply(0.3));
addVelocity(0, -0.025, 0);
}
}
@Override
protected void onBlockHit(BlockHitResult hit) {
BlockState state = world.getBlockState(hit.getBlockPos());
if (getVelocity().length() > 0.2F) {
boolean ownerCanModify = Caster.of(getOwner()).filter(pony -> pony.canModifyAt(hit.getBlockPos())).isPresent();
if (ownerCanModify && world.getGameRules().getBoolean(GameRules.DO_MOB_GRIEFING)) {
if ((!isBouncy() || world.random.nextInt(200) == 0) && state.isIn(UTags.FRAGILE)) {
world.breakBlock(hit.getBlockPos(), true);
}
}
if (isBouncy()) {
Direction.Axis side = hit.getSide().getAxis();
if (side == Direction.Axis.X) {
setVelocity(getVelocity().multiply(-0.4, 0.3, 0.3));
}
if (side == Direction.Axis.Y) {
setVelocity(getVelocity().multiply(0.3, -0.4, 0.3));
}
if (side == Direction.Axis.Z) {
setVelocity(getVelocity().multiply(0.3, 0.3, -0.4));
}
} else {
super.onBlockHit(hit);
}
} else {
super.onBlockHit(hit);
}
setSound(state.getSoundGroup().getStepSound());
world.playSoundFromEntity(null, this, state.getSoundGroup().getStepSound(), SoundCategory.BLOCKS, 1, 1);
emitGameEvent(GameEvent.STEP);
}
@Override
protected SoundEvent getHitSound() {
return isBouncy() ? SoundEvents.BLOCK_NOTE_BLOCK_BANJO : SoundEvents.BLOCK_STONE_HIT;
}
@Override
public void writeCustomDataToNbt(NbtCompound nbt) {
super.writeCustomDataToNbt(nbt);
ItemStack stack = getStack();
if (!stack.isEmpty()) {
nbt.put("Item", stack.writeNbt(new NbtCompound()));
}
}
@Override
public void readCustomDataFromNbt(NbtCompound nbt) {
super.readCustomDataFromNbt(nbt);
setStack(ItemStack.fromNbt(nbt.getCompound("Item")));
}
}

View file

@ -25,6 +25,10 @@ public interface UEntities {
.trackRangeBlocks(100) .trackRangeBlocks(100)
.trackedUpdateRate(2) .trackedUpdateRate(2)
.dimensions(EntityDimensions.fixed(0.25F, 0.25F))); .dimensions(EntityDimensions.fixed(0.25F, 0.25F)));
EntityType<PhysicsBodyProjectileEntity> MUFFIN = register("muffin", FabricEntityTypeBuilder.<PhysicsBodyProjectileEntity>create(SpawnGroup.MISC, PhysicsBodyProjectileEntity::new)
.trackRangeBlocks(100)
.trackedUpdateRate(2)
.dimensions(EntityDimensions.fixed(0.25F, 0.25F)));
EntityType<MagicProjectileEntity> MAGIC_BEAM = register("magic_beam", FabricEntityTypeBuilder.<MagicProjectileEntity>create(SpawnGroup.MISC, MagicProjectileEntity::new) EntityType<MagicProjectileEntity> MAGIC_BEAM = register("magic_beam", FabricEntityTypeBuilder.<MagicProjectileEntity>create(SpawnGroup.MISC, MagicProjectileEntity::new)
.trackRangeBlocks(100) .trackRangeBlocks(100)
.trackedUpdateRate(2) .trackedUpdateRate(2)

View file

@ -1,7 +1,6 @@
package com.minelittlepony.unicopia.item; package com.minelittlepony.unicopia.item;
import com.minelittlepony.unicopia.entity.IItemEntity; import com.minelittlepony.unicopia.entity.IItemEntity;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
@ -10,10 +9,12 @@ import net.minecraft.enchantment.Enchantments;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityGroup; import net.minecraft.entity.EntityGroup;
import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.FlyingItemEntity;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.attribute.EntityAttributeInstance; import net.minecraft.entity.attribute.EntityAttributeInstance;
import net.minecraft.entity.attribute.EntityAttributes; import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.particle.ParticleTypes; import net.minecraft.particle.ParticleTypes;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
@ -50,14 +51,14 @@ public class FilledJarItem extends JarItem implements ChameleonItem {
} }
@Override @Override
public void onImpact(MagicProjectileEntity projectile, Entity entity) { public void onImpact(ProjectileEntity projectile, Entity entity) {
super.onImpact(projectile, entity); super.onImpact(projectile, entity);
if (!entity.isAttackable()) { if (!entity.isAttackable() || !(projectile instanceof FlyingItemEntity)) {
return; return;
} }
ItemStack stack = getAppearanceStack(projectile.getStack()); ItemStack stack = getAppearanceStack(((FlyingItemEntity)projectile).getStack());
boolean onFire = false; boolean onFire = false;
@ -119,12 +120,12 @@ public class FilledJarItem extends JarItem implements ChameleonItem {
} }
@Override @Override
protected void onImpact(MagicProjectileEntity projectile) { protected void onImpact(ProjectileEntity projectile) {
ItemStack stack = getAppearanceStack(projectile.getStack()); if (!(projectile instanceof FlyingItemEntity)) {
return;
}
ItemStack stack = getAppearanceStack(((FlyingItemEntity)projectile).getStack());
stack.damage(1, projectile.world.random, null); stack.damage(1, projectile.world.random, null);
projectile.dropStack(stack); projectile.dropStack(stack);
projectile.world.syncWorldEvent(WorldEvents.BLOCK_BROKEN, projectile.getBlockPos(), Block.getRawIdFromState(Blocks.GLASS.getDefaultState())); projectile.world.syncWorldEvent(WorldEvents.BLOCK_BROKEN, projectile.getBlockPos(), Block.getRawIdFromState(Blocks.GLASS.getDefaultState()));
} }

View file

@ -0,0 +1,66 @@
package com.minelittlepony.unicopia.item;
import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.entity.PhysicsBodyProjectileEntity;
import net.minecraft.block.BlockState;
import net.minecraft.block.DispenserBlock;
import net.minecraft.block.dispenser.ProjectileDispenserBehavior;
import net.minecraft.entity.FlyingItemEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Position;
import net.minecraft.world.GameRules;
import net.minecraft.world.World;
public class HeavyProjectileItem extends ProjectileItem {
public HeavyProjectileItem(Settings settings, float projectileDamage) {
super(settings, projectileDamage);
DispenserBlock.registerBehavior(this, new ProjectileDispenserBehavior(){
@Override
protected ProjectileEntity createProjectile(World world, Position position, ItemStack stack) {
ProjectileEntity projectile = HeavyProjectileItem.this.createProjectile(stack, world, null);
projectile.setPosition(position.getX(), position.getY(), position.getZ());
return projectile;
}
});
}
@Override
protected ProjectileEntity createProjectile(ItemStack stack, World world, PlayerEntity player) {
PhysicsBodyProjectileEntity projectile = player == null ? new PhysicsBodyProjectileEntity(world) : new PhysicsBodyProjectileEntity(world, player);
if (player != null) {
projectile.setVelocity(player, player.getPitch(), player.getYaw(), 0, 1.5F, 1);
}
projectile.pickupType = PersistentProjectileEntity.PickupPermission.ALLOWED;
projectile.setStack(stack.copy());
if (this == UItems.MUFFIN) {
projectile.setBouncy();
}
return projectile;
}
@Override
protected SoundEvent getThrowSound(ItemStack stack) {
return USounds.ENTITY_JAR_THROW;
}
@Override
public void onImpact(ProjectileEntity projectile, BlockPos pos, BlockState state) {
if (projectile.world.getGameRules().getBoolean(GameRules.DO_MOB_GRIEFING)) {
float damage = projectile instanceof FlyingItemEntity ? getProjectileDamage(((FlyingItemEntity)projectile).getStack()) : 0;
if (damage > 0 && projectile.world.random.nextInt(90) == 0) {
if (state.isIn(UTags.FRAGILE)) {
projectile.world.breakBlock(pos, true);
}
}
}
}
}

View file

@ -6,9 +6,6 @@ import com.minelittlepony.unicopia.entity.IItemEntity;
import com.minelittlepony.unicopia.entity.ItemImpl; import com.minelittlepony.unicopia.entity.ItemImpl;
import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.particle.UParticles;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
@ -16,67 +13,31 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
import net.minecraft.entity.ItemEntity; import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LightningEntity; import net.minecraft.entity.LightningEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.entity.Entity.RemovalReason; import net.minecraft.entity.Entity.RemovalReason;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundEvent;
import net.minecraft.stat.Stats;
import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkSectionPos; import net.minecraft.util.math.ChunkSectionPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.Heightmap; import net.minecraft.world.Heightmap;
import net.minecraft.world.World;
import net.minecraft.world.WorldEvents; import net.minecraft.world.WorldEvents;
public class JarItem extends Item implements ProjectileDelegate, ItemImpl.GroundTickCallback { public class JarItem extends ProjectileItem implements ItemImpl.GroundTickCallback {
private final boolean rain; private final boolean rain;
private final boolean thunder; private final boolean thunder;
private final boolean lightning; private final boolean lightning;
public JarItem(Settings settings, boolean rain, boolean thunder, boolean lightning) { public JarItem(Settings settings, boolean rain, boolean thunder, boolean lightning) {
super(settings); super(settings, 0.5F);
this.rain = rain; this.rain = rain;
this.thunder = thunder; this.thunder = thunder;
this.lightning = lightning; this.lightning = lightning;
} }
@Override
public TypedActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {
ItemStack stack = player.getStackInHand(hand);
world.playSound(null, player.getX(), player.getY(), player.getZ(),
USounds.ENTITY_JAR_THROW, SoundCategory.NEUTRAL,
0.5F,
0.4F / (world.random.nextFloat() * 0.4F + 0.8F));
if (!world.isClient) {
MagicProjectileEntity projectile = new MagicProjectileEntity(world, player);
projectile.setItem(stack);
projectile.setThrowDamage(getProjectileDamage(stack));
projectile.setVelocity(player, player.getPitch(), player.getYaw(), 0, 1.5F, 1);
world.spawnEntity(projectile);
}
player.incrementStat(Stats.USED.getOrCreateStat(this));
if (!player.getAbilities().creativeMode) {
stack.decrement(1);
}
return TypedActionResult.success(stack, world.isClient());
}
protected float getProjectileDamage(ItemStack stack) {
return 0.5F;
}
@Override @Override
public ActionResult onGroundTick(IItemEntity item) { public ActionResult onGroundTick(IItemEntity item) {
ItemEntity entity = item.get().getMaster(); ItemEntity entity = item.get().getMaster();
@ -115,17 +76,22 @@ public class JarItem extends Item implements ProjectileDelegate, ItemImpl.Ground
} }
@Override @Override
public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) { protected SoundEvent getThrowSound(ItemStack stack) {
return USounds.ENTITY_JAR_THROW;
}
@Override
public void onImpact(ProjectileEntity projectile, BlockPos pos, BlockState state) {
onImpact(projectile); onImpact(projectile);
} }
@Override @Override
public void onImpact(MagicProjectileEntity projectile, Entity entity) { public void onImpact(ProjectileEntity projectile, Entity entity) {
onImpact(projectile); onImpact(projectile);
} }
protected void onImpact(MagicProjectileEntity projectile) { protected void onImpact(ProjectileEntity projectile) {
if (!projectile.isClient()) { if (!projectile.world.isClient()) {
ServerWorld world = (ServerWorld)projectile.world; ServerWorld world = (ServerWorld)projectile.world;
if (rain || thunder) { if (rain || thunder) {

View file

@ -0,0 +1,8 @@
package com.minelittlepony.unicopia.item;
public class MuffinItem extends HeavyProjectileItem {
public MuffinItem(Settings settings, float projectileDamage) {
super(settings, projectileDamage);
}
}

View file

@ -0,0 +1,75 @@
package com.minelittlepony.unicopia.item;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.stat.Stats;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.world.World;
abstract class ProjectileItem extends Item implements ProjectileDelegate<ProjectileEntity> {
private final float projectileDamage;
public ProjectileItem(Settings settings, float projectileDamage) {
super(settings);
this.projectileDamage = projectileDamage;
}
@Override
public TypedActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {
if (isFood() && !player.isSneaking()) {
TypedActionResult<ItemStack> eaten = super.use(world, player, hand);
if (eaten.getResult().isAccepted()) {
return eaten;
}
}
ItemStack stack = player.getStackInHand(hand);
world.playSound(null, player.getX(), player.getY(), player.getZ(),
getThrowSound(stack), SoundCategory.NEUTRAL,
0.5F,
0.4F / (world.random.nextFloat() * 0.4F + 0.8F));
if (!world.isClient) {
world.spawnEntity(createProjectile(stack, world, player));
}
player.incrementStat(Stats.USED.getOrCreateStat(this));
if (!player.getAbilities().creativeMode) {
stack.decrement(1);
}
return TypedActionResult.success(stack, world.isClient());
}
protected ProjectileEntity createProjectile(ItemStack stack, World world, @Nullable PlayerEntity player) {
MagicProjectileEntity projectile = player == null ? new MagicProjectileEntity(world) : new MagicProjectileEntity(world, player);
projectile.setItem(stack);
projectile.setThrowDamage(getProjectileDamage(stack));
if (player != null) {
projectile.setVelocity(player, player.getPitch(), player.getYaw(), 0, 1.5F, 1);
}
return projectile;
}
protected abstract SoundEvent getThrowSound(ItemStack stack);
protected float getProjectileDamage(ItemStack stack) {
return projectileDamage;
}
}

View file

@ -67,9 +67,10 @@ public interface UItems {
Item HAY_BURGER = register("hay_burger", new Item(new Item.Settings().group(ItemGroup.FOOD).maxCount(1).food(UFoodComponents.HAY_BURGER))); Item HAY_BURGER = register("hay_burger", new Item(new Item.Settings().group(ItemGroup.FOOD).maxCount(1).food(UFoodComponents.HAY_BURGER)));
Item HAY_FRIES = register("hay_fries", new Item(new Item.Settings().group(ItemGroup.FOOD).maxCount(16).food(UFoodComponents.HAY_FRIES))); Item HAY_FRIES = register("hay_fries", new Item(new Item.Settings().group(ItemGroup.FOOD).maxCount(16).food(UFoodComponents.HAY_FRIES)));
Item WHEAT_WORMS = register("wheat_worms", new Item(new Item.Settings().group(ItemGroup.MISC).maxCount(16).food(UFoodComponents.INSECTS))); Item WHEAT_WORMS = register("wheat_worms", new Item(new Item.Settings().group(ItemGroup.MISC).maxCount(16).food(UFoodComponents.INSECTS)));
Item MUFFIN = register("muffin", new MuffinItem(new Item.Settings().group(ItemGroup.FOOD).maxCount(32).food(FoodComponents.BREAD), 0));
Item PEBBLES = register("pebbles", new RacePredicatedAliasedBlockItem(UBlocks.ROCKS, new Item.Settings().group(ItemGroup.MATERIALS), Race::canUseEarth)); Item PEBBLES = register("pebbles", new RacePredicatedAliasedBlockItem(UBlocks.ROCKS, new Item.Settings().group(ItemGroup.MATERIALS), Race::canUseEarth));
Item ROCK = register("rock", new Item(new Item.Settings().group(ItemGroup.MATERIALS))); Item ROCK = register("rock", new HeavyProjectileItem(new Item.Settings().group(ItemGroup.MATERIALS), 3));
Item WEIRD_ROCK = register("weird_rock", new Item(new Item.Settings().group(ItemGroup.MATERIALS))); Item WEIRD_ROCK = register("weird_rock", new Item(new Item.Settings().group(ItemGroup.MATERIALS)));
Item ROCK_STEW = register("rock_stew", new Item(new Item.Settings().group(ItemGroup.FOOD).food(FoodComponents.MUSHROOM_STEW))); Item ROCK_STEW = register("rock_stew", new Item(new Item.Settings().group(ItemGroup.FOOD).food(FoodComponents.MUSHROOM_STEW)));

View file

@ -69,7 +69,11 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Caster<Li
super(type, world); super(type, world);
} }
public MagicProjectileEntity(World world, @Nullable LivingEntity thrower) { public MagicProjectileEntity(World world) {
this(UEntities.THROWN_ITEM, world);
}
public MagicProjectileEntity(World world, LivingEntity thrower) {
super(UEntities.THROWN_ITEM, thrower, world); super(UEntities.THROWN_ITEM, thrower, world);
} }
@ -281,15 +285,16 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Caster<Li
} }
} }
protected void forEachDelegates(Consumer<ProjectileDelegate> consumer) { @SuppressWarnings("unchecked")
protected void forEachDelegates(Consumer<ProjectileDelegate<MagicProjectileEntity>> consumer) {
getSpellSlot().forEach(spell -> { getSpellSlot().forEach(spell -> {
if (SpellPredicate.HAS_PROJECTILE_EVENTS.test(spell)) { if (SpellPredicate.HAS_PROJECTILE_EVENTS.test(spell)) {
consumer.accept((ProjectileDelegate)spell); consumer.accept((ProjectileDelegate<MagicProjectileEntity>)spell);
} }
return Operation.SKIP; return Operation.SKIP;
}, true); }, true);
if (getItem().getItem() instanceof ProjectileDelegate) { if (getItem().getItem() instanceof ProjectileDelegate) {
consumer.accept(((ProjectileDelegate)getItem().getItem())); consumer.accept(((ProjectileDelegate<MagicProjectileEntity>)getItem().getItem()));
} }
} }

View file

@ -2,16 +2,17 @@ package com.minelittlepony.unicopia.projectile;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
public interface ProjectileDelegate { public interface ProjectileDelegate<T extends ProjectileEntity> {
/** /**
* Called once the projectile lands either hitting the ground or an entity. * Called once the projectile lands either hitting the ground or an entity.
*/ */
default void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {} default void onImpact(T projectile, BlockPos pos, BlockState state) {}
/** /**
* Called once the projectile lands either hitting the ground or an entity. * Called once the projectile lands either hitting the ground or an entity.
*/ */
default void onImpact(MagicProjectileEntity projectile, Entity entity) {} default void onImpact(T projectile, Entity entity) {}
} }

View file

@ -55,6 +55,10 @@ public interface ProjectileUtil {
/** /**
* Reverses a projectile's direction to deflect it off a surface. * Reverses a projectile's direction to deflect it off a surface.
*
* @param projectile The projectile to deflect
* @param post The position the projectile must be deflected away from
* @param absorbtionRate Percentage of the projectile velocity to absorb.
*/ */
static void ricochet(Entity projectile, Vec3d pos, float absorbtionRate) { static void ricochet(Entity projectile, Vec3d pos, float absorbtionRate) {
Vec3d position = projectile.getPos(); Vec3d position = projectile.getPos();

View file

@ -59,6 +59,7 @@
"item.unicopia.hay_burger": "Hay Burger", "item.unicopia.hay_burger": "Hay Burger",
"item.unicopia.hay_fries": "Hay Fries", "item.unicopia.hay_fries": "Hay Fries",
"item.unicopia.wheat_worms": "Wheat Worms", "item.unicopia.wheat_worms": "Wheat Worms",
"item.unicopia.muffin": "Muffin",
"item.unicopia.pegasus_amulet": "Wings of Icarus", "item.unicopia.pegasus_amulet": "Wings of Icarus",
"item.unicopia.pegasus_amulet.lore": "Grants temporary flight to whoever wears it", "item.unicopia.pegasus_amulet.lore": "Grants temporary flight to whoever wears it",

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "unicopia:item/muffin"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B