Added jars, empty jars, lightning in a jar, and various storms in a jar

This commit is contained in:
Sollace 2021-02-14 17:53:44 +02:00
parent 82393eedef
commit a130087d5d
19 changed files with 270 additions and 31 deletions

View file

@ -3,11 +3,13 @@ package com.minelittlepony.unicopia.ability.magic;
import javax.annotation.Nullable;
import com.minelittlepony.unicopia.Affinity;
import com.minelittlepony.unicopia.UEntities;
import com.minelittlepony.unicopia.ability.magic.spell.SpellRegistry;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
@ -15,23 +17,25 @@ import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
/**
* Magic effects that can be thrown.
*/
public interface Thrown extends Spell {
public interface Thrown extends Spell, ProjectileDelegate {
/**
* Called once the projectile lands either hitting the ground or an entity.
*/
default void onImpact(Caster<?> caster, BlockPos pos, BlockState state) {
if (!caster.isClient()) {
update(caster);
@Override
default void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {
if (!projectile.isClient()) {
update(projectile);
}
}
@Override
default void onImpact(MagicProjectileEntity projectile, Entity entity) {
}
/**
* The amount of damage to be dealt when the projectile collides with an entity.
*/
@ -64,24 +68,18 @@ public interface Thrown extends Spell {
default MagicProjectileEntity toss(Caster<?> caster) {
World world = caster.getWorld();
Entity entity = caster.getMaster();
LivingEntity entity = caster.getMaster();
world.playSound(null, entity.getX(), entity.getY(), entity.getZ(), getThrowSound(caster), SoundCategory.NEUTRAL, 0.7F, 0.4F / (world.random.nextFloat() * 0.4F + 0.8F));
if (!caster.isClient()) {
Vec3d rot = entity.getRotationVec(1);
MagicProjectileEntity projectile = new MagicProjectileEntity(UEntities.THROWN_ITEM, world, caster.getMaster(), entity.getRotationVec(1));
MagicProjectileEntity projectile = new MagicProjectileEntity(world, entity);
projectile.setItem(getCastAppearance(caster));
projectile.setThrowDamage(getThrowDamage(caster));
projectile.setSpell(this);
projectile.setHydrophobic();
projectile.updatePosition(
entity.getX() + rot.x * 4,
entity.getBodyY(0.5D) + 0.5,
projectile.getZ() + rot.z * 4
);
projectile.setProperties(entity, entity.pitch, entity.yaw, 0, 1.5F, 1);
world.spawnEntity(projectile);

View file

@ -6,6 +6,7 @@ import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.Magical;
import com.minelittlepony.unicopia.ability.magic.Thrown;
import com.minelittlepony.unicopia.block.state.StateMaps;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.util.MagicalDamageSource;
import com.minelittlepony.unicopia.util.PosHelper;
import com.minelittlepony.unicopia.util.VecHelper;
@ -55,9 +56,9 @@ public class FireSpell extends AbstractRangedAreaSpell implements Thrown {
}
@Override
public void onImpact(Caster<?> caster, BlockPos pos, BlockState state) {
if (!caster.isClient()) {
caster.getWorld().createExplosion(caster.getMaster(), pos.getX(), pos.getY(), pos.getZ(), 2, DestructionType.DESTROY);
public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {
if (!projectile.isClient()) {
projectile.getWorld().createExplosion(projectile.getMaster(), pos.getX(), pos.getY(), pos.getZ(), 2, DestructionType.DESTROY);
}
}

View file

@ -1,11 +1,14 @@
package com.minelittlepony.unicopia.entity;
import java.util.Optional;
import javax.annotation.Nullable;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.util.NbtSerialisable;
import net.minecraft.entity.Entity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.util.Tickable;
@ -38,7 +41,6 @@ public interface Equine<T extends Entity> extends NbtSerialisable, Tickable {
return false;
}
/**
* Event triggered when this entity is hit by a projectile.
*/
@ -53,6 +55,13 @@ public interface Equine<T extends Entity> extends NbtSerialisable, Tickable {
}
/**
* Called when an entity is harmed.
*/
default Optional<Boolean> onDamage(DamageSource source, float amount) {
return Optional.empty();
}
@Nullable
static <T extends Equine<?>> T of(Entity entity) {
return PonyContainer.<Entity, T>of(entity)

View file

@ -0,0 +1,148 @@
package com.minelittlepony.unicopia.item;
import com.minelittlepony.unicopia.entity.IItemEntity;
import com.minelittlepony.unicopia.entity.ItemImpl;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import com.minelittlepony.unicopia.util.WorldEvent;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.DispenserBlock;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LightningEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ArmorItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.stat.Stats;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.level.ServerWorldProperties;
public class JarItem extends Item implements ProjectileDelegate, ItemImpl.TickableItem {
private final boolean rain;
private final boolean thunder;
private final boolean lightning;
public JarItem(Settings settings, boolean rain, boolean thunder, boolean lightning) {
super(settings);
this.rain = rain;
this.thunder = thunder;
this.lightning = lightning;
DispenserBlock.registerBehavior(this, ArmorItem.DISPENSER_BEHAVIOR);
}
@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(),
SoundEvents.ENTITY_SNOWBALL_THROW, SoundCategory.NEUTRAL,
0.5F,
0.4F / (RANDOM.nextFloat() * 0.4F + 0.8F));
if (!world.isClient) {
MagicProjectileEntity projectile = new MagicProjectileEntity(world, player);
projectile.setItem(stack);
projectile.setThrowDamage(0.5F);
projectile.setProperties(player, player.pitch, player.yaw, 0, 1.5F, 1);
world.spawnEntity(projectile);
}
player.incrementStat(Stats.USED.getOrCreateStat(this));
if (!player.abilities.creativeMode) {
stack.decrement(1);
}
return TypedActionResult.success(stack, world.isClient());
}
@Override
public ActionResult onGroundTick(IItemEntity item) {
ItemEntity entity = item.get().getMaster();
entity.setInvulnerable(true);
if (!lightning
&& !entity.world.isClient
&& !entity.removed
&& entity.getAge() > 100
&& entity.world.isThundering()
&& entity.world.isSkyVisible(entity.getBlockPos())
&& entity.world.random.nextInt(130) == 0) {
LightningEntity lightning = EntityType.LIGHTNING_BOLT.create(entity.world);
lightning.refreshPositionAfterTeleport(entity.getX(), entity.getY(), entity.getZ());
entity.remove();
entity.world.spawnEntity(lightning);
ItemEntity neu = EntityType.ITEM.create(entity.world);
neu.copyPositionAndRotation(entity);
neu.setStack(new ItemStack(this == UItems.RAIN_CLOUD_JAR ? UItems.STORM_CLOUD_JAR : UItems.LIGHTNING_JAR));
neu.setInvulnerable(true);
entity.world.spawnEntity(neu);
ItemEntity copy = EntityType.ITEM.create(entity.world);
copy.copyPositionAndRotation(entity);
copy.setInvulnerable(true);
copy.setStack(entity.getStack());
copy.getStack().decrement(1);
entity.world.spawnEntity(copy);
}
return ActionResult.PASS;
}
@Override
public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {
onImpact(projectile);
}
@Override
public void onImpact(MagicProjectileEntity projectile, Entity entity) {
onImpact(projectile);
}
private void onImpact(MagicProjectileEntity projectile) {
if (!projectile.isClient()) {
ServerWorld world = (ServerWorld)projectile.world;
if (rain || thunder) {
ServerWorldProperties props = ((ServerWorldProperties)world.getLevelProperties());
int time = Math.max(Math.max(props.getRainTime(), props.getThunderTime()), 40);
world.setWeather(0, time, rain, thunder);
}
if (lightning) {
LightningEntity lightning = EntityType.LIGHTNING_BOLT.create(world);
lightning.refreshPositionAfterTeleport(projectile.getX(), projectile.getY(), projectile.getZ());
world.spawnEntity(lightning);
}
}
if (rain || thunder) {
projectile.world.syncWorldEvent(WorldEvent.PROJECTILE_HIT, projectile.getBlockPos(), thunder ? 0x888888 : 0xF8F8F8);
}
WorldEvent.play(WorldEvent.DESTROY_BLOCK, projectile.world, projectile.getBlockPos(), Blocks.GLASS.getDefaultState());
}
}

View file

@ -47,6 +47,12 @@ public interface UItems {
.equipmentSlot(FriendshipBraceletItem::getPreferredEquipmentSlot)
));
Item EMPTY_JAR = register("empty_jar", new JarItem(new Item.Settings().group(ItemGroup.DECORATIONS).maxCount(16).fireproof(), false, false, false));
Item RAIN_CLOUD_JAR = register("rain_cloud_jar", new JarItem(new Item.Settings().group(ItemGroup.DECORATIONS).maxCount(1).fireproof(), true, false, false));
Item STORM_CLOUD_JAR = register("storm_cloud_jar", new JarItem(new Item.Settings().group(ItemGroup.DECORATIONS).maxCount(1).fireproof(), true, true, false));
Item LIGHTNING_JAR = register("lightning_jar", new JarItem(new Item.Settings().group(ItemGroup.DECORATIONS).maxCount(1).fireproof(), false, false, true));
Item ZAP_APPLE_JAM_JAR = register("zap_apple_jam_jar", new JarItem(new Item.Settings().group(ItemGroup.DECORATIONS).maxCount(1).fireproof(), false, false, true));
static <T extends Item> T register(String name, T item) {
ITEMS.add(item);
if (item instanceof BlockItem) {

View file

@ -1,11 +1,11 @@
package com.minelittlepony.unicopia.projectile;
import com.minelittlepony.unicopia.Affinity;
import com.minelittlepony.unicopia.UEntities;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.Levelled;
import com.minelittlepony.unicopia.ability.magic.Magical;
import com.minelittlepony.unicopia.ability.magic.Spell;
import com.minelittlepony.unicopia.ability.magic.Thrown;
import com.minelittlepony.unicopia.ability.magic.spell.SpellRegistry;
import com.minelittlepony.unicopia.entity.EntityPhysics;
import com.minelittlepony.unicopia.entity.Physics;
@ -59,12 +59,8 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Magical,
super(type, world);
}
public MagicProjectileEntity(EntityType<MagicProjectileEntity> type, World world, LivingEntity thrower, Vec3d velocity) {
super(type, world);
refreshPositionAndAngles(thrower.getX(), thrower.getY(), thrower.getZ(), thrower.yaw, thrower.pitch);
refreshPosition();
setVelocity(velocity);
setOwner(thrower);
public MagicProjectileEntity(World world, LivingEntity thrower) {
super(UEntities.THROWN_ITEM, thrower, world);
}
@Override
@ -249,10 +245,14 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Magical,
if (hasSpell()) {
Spell effect = getSpell(true);
if (effect instanceof Thrown) {
((Thrown)effect).onImpact(this, hit.getBlockPos(), world.getBlockState(hit.getBlockPos()));
if (effect instanceof ProjectileDelegate) {
((ProjectileDelegate)effect).onImpact(this, hit.getBlockPos(), world.getBlockState(hit.getBlockPos()));
}
}
if (getItem().getItem() instanceof ProjectileDelegate) {
((ProjectileDelegate)getItem().getItem()).onImpact(this, hit.getBlockPos(), world.getBlockState(hit.getBlockPos()));
}
}
@Override
@ -266,6 +266,10 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Magical,
if (entity != null) {
entity.damage(DamageSource.thrownProjectile(this, getOwner()), getThrowDamage());
}
if (getItem().getItem() instanceof ProjectileDelegate) {
((ProjectileDelegate)getItem().getItem()).onImpact(this, entity);
}
}
@Override

View file

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

View file

@ -16,6 +16,12 @@
"item.unicopia.cooked_zap_apple": "Cooked Zap Apple",
"item.unicopia.zap_apple": "Zap Apple",
"item.unicopia.empty_jar": "Glass Jar",
"item.unicopia.rain_cloud_jar": "Rain Cloud in a Jar",
"item.unicopia.storm_cloud_jar": "Storm Cloud in a Jar",
"item.unicopia.lightning_jar": "Lightning in a Jar",
"item.unicopia.zap_apple_jam_jar": "Zap Apple Jam",
"item.unicopia.music_disc_pet": "Music Disc",
"item.unicopia.music_disc_pet.desc": "Danial Ingram - pet",
"item.unicopia.music_disc_popular": "Music Disc",

View file

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

View file

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

View file

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

View file

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

View file

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -0,0 +1,20 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"*#*",
"* *",
"***"
],
"key": {
"#": {
"tag": "minecraft:planks"
},
"*": {
"item": "minecraft:glass"
}
},
"result": {
"item": "unicopia:empty_jar",
"count": 7
}
}