mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-12-02 17:08:00 +01:00
Added muffins
This commit is contained in:
parent
83b110a8d3
commit
2c77cfb4c3
18 changed files with 358 additions and 68 deletions
|
@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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")));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
|
|
@ -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()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.minelittlepony.unicopia.item;
|
||||||
|
|
||||||
|
public class MuffinItem extends HeavyProjectileItem {
|
||||||
|
|
||||||
|
public MuffinItem(Settings settings, float projectileDamage) {
|
||||||
|
super(settings, projectileDamage);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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)));
|
||||||
|
|
||||||
|
|
|
@ -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()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "item/generated",
|
||||||
|
"textures": {
|
||||||
|
"layer0": "unicopia:item/muffin"
|
||||||
|
}
|
||||||
|
}
|
BIN
src/main/resources/assets/unicopia/textures/item/muffin.png
Normal file
BIN
src/main/resources/assets/unicopia/textures/item/muffin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 389 B |
Loading…
Reference in a new issue