Unicopia/src/main/java/com/minelittlepony/unicopia/spell/SpellIce.java

172 lines
6 KiB
Java

package com.minelittlepony.unicopia.spell;
import javax.annotation.Nullable;
import com.minelittlepony.unicopia.init.UMaterials;
import com.minelittlepony.util.MagicalDamageSource;
import com.minelittlepony.util.PosHelper;
import com.minelittlepony.util.collection.IStateMapping;
import com.minelittlepony.util.collection.StateMapList;
import com.minelittlepony.util.shape.IShape;
import com.minelittlepony.util.shape.Sphere;
import com.minelittlepony.util.vector.VecHelper;
import net.minecraft.block.Block;
import net.minecraft.block.BlockBush;
import net.minecraft.block.BlockLeaves;
import net.minecraft.block.BlockRedstoneWire;
import net.minecraft.block.BlockSnow;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.dispenser.IBlockSource;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityTNTPrimed;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.world.World;
public class SpellIce extends AbstractSpell.RangedAreaSpell implements IUseAction, IDispenceable {
public final StateMapList affected = new StateMapList();
public SpellIce() {
affected.add(IStateMapping.build(
s -> s.getMaterial() == Material.WATER,
s -> Blocks.ICE.getDefaultState()));
affected.add(IStateMapping.build(
s -> s.getMaterial() == Material.LAVA,
s -> Blocks.OBSIDIAN.getDefaultState()));
affected.add(IStateMapping.build(
s -> s.getBlock() == Blocks.SNOW_LAYER,
s -> {
s = s.cycleProperty(BlockSnow.LAYERS);
if (s.getValue(BlockSnow.LAYERS) >= 7) {
return Blocks.SNOW.getDefaultState();
}
return s;
}));
affected.replaceBlock(Blocks.FIRE, Blocks.AIR);
affected.setProperty(Blocks.REDSTONE_WIRE, BlockRedstoneWire.POWER, 0);
}
private final int rad = 3;
private final IShape effect_range = new Sphere(false, rad);
@Override
public String getName() {
return "ice";
}
@Override
public SpellAffinity getAffinity() {
return SpellAffinity.GOOD;
}
@Override
public int getTint() {
return 0xBDBDF9;
}
@Override
public boolean update(ICaster<?> source) {
return false;
}
@Override
public void render(ICaster<?> source) {
}
@Override
public SpellCastResult onDispenced(BlockPos pos, EnumFacing facing, IBlockSource source, SpellAffinity affinity) {
return applyBlocks(null, source.getWorld(), pos.offset(facing, rad)) ? SpellCastResult.NONE : SpellCastResult.DEFAULT;
}
@Override
public SpellCastResult onUse(ItemStack stack, SpellAffinity affinity, EntityPlayer player, World world, BlockPos pos, EnumFacing side, float hitX, float hitY, float hitZ) {
if (player != null && player.isSneaking()) {
applyBlockSingle(world, pos);
} else {
applyBlocks(player, world, pos);
}
return SpellCastResult.DEFAULT;
}
@Override
public SpellCastResult onUse(ItemStack stack, SpellAffinity affinity, EntityPlayer player, World world, @Nullable Entity hitEntity) {
if (hitEntity != null && applyEntitySingle(player, hitEntity)) {
return SpellCastResult.DEFAULT;
}
return SpellCastResult.NONE;
}
private boolean applyBlocks(EntityPlayer owner, World world, BlockPos pos) {
for (BlockPos i : PosHelper.getAllInRegionMutable(pos, effect_range)) {
applyBlockSingle(world, i);
}
return applyEntities(owner, world, pos);
}
protected boolean applyEntities(EntityPlayer owner, World world, BlockPos pos) {
return VecHelper.findAllEntitiesInRange(owner, world, pos, 3).filter(i ->
applyEntitySingle(owner, i)
).count() > 0;
}
protected boolean applyEntitySingle(EntityPlayer owner, Entity e) {
if (e instanceof EntityTNTPrimed) {
e.setDead();
e.getEntityWorld().setBlockState(e.getPosition(), Blocks.TNT.getDefaultState());
} else if (e.isBurning()) {
e.extinguish();
} else {
e.attackEntityFrom(MagicalDamageSource.causePlayerDamage("cold", owner), 2);
}
return true;
}
private void applyBlockSingle(World world, BlockPos pos) {
IBlockState state = world.getBlockState(pos);
Block id = state.getBlock();
IBlockState converted = affected.getConverted(state);
if (!state.equals(converted)) {
world.setBlockState(pos, converted, 3);
} else if (state.getMaterial() != UMaterials.cloud && state.isSideSolid(world, pos, EnumFacing.UP)
|| (id == Blocks.SNOW)
|| (id instanceof BlockLeaves)) {
incrementIce(world, pos.up());
} else if (state.getMaterial() == Material.ICE && world.rand.nextInt(10) == 0) {
if (isSurroundedByIce(world, pos)) {
world.setBlockState(pos, Blocks.PACKED_ICE.getDefaultState());
}
}
world.spawnParticle(EnumParticleTypes.WATER_SPLASH, pos.getX() + world.rand.nextFloat(), pos.getY() + 1, pos.getZ() + world.rand.nextFloat(), 0, 0, 0);
}
public static boolean isSurroundedByIce(World w, BlockPos pos) {
return !PosHelper.adjacentNeighbours(pos).stream().anyMatch(i ->
w.getBlockState(i).getMaterial() == Material.ICE
);
}
private void incrementIce(World world, BlockPos pos) {
IBlockState state = world.getBlockState(pos);
Block id = state.getBlock();
if (id == Blocks.AIR || (id instanceof BlockBush)) {
world.setBlockState(pos, Blocks.SNOW_LAYER.getDefaultState(), 3);
}
}
}