From 9dbdd2b830e7b4442b6c5a85a6cde43456ec36a1 Mon Sep 17 00:00:00 2001 From: Electroblob77 <35599699+Electroblob77@users.noreply.github.com> Date: Sat, 13 Jun 2020 17:23:50 +0100 Subject: [PATCH] Sort out various problems with freezing things, fixes #460 --- .../wizardry/potion/PotionFrostStep.java | 3 +- .../electroblob/wizardry/spell/Freeze.java | 17 ++---- .../electroblob/wizardry/spell/IceAge.java | 22 +++----- .../wizardry/util/WizardryUtilities.java | 53 +++++++++++++++++-- 4 files changed, 63 insertions(+), 32 deletions(-) diff --git a/src/main/java/electroblob/wizardry/potion/PotionFrostStep.java b/src/main/java/electroblob/wizardry/potion/PotionFrostStep.java index 44377266..57057cd9 100644 --- a/src/main/java/electroblob/wizardry/potion/PotionFrostStep.java +++ b/src/main/java/electroblob/wizardry/potion/PotionFrostStep.java @@ -7,6 +7,7 @@ import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.block.BlockLiquid; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; @@ -103,7 +104,7 @@ public class PotionFrostStep extends PotionMagicEffect implements ICustomPotionP IBlockState state2 = world.getBlockState(pos2); - if(state2.getMaterial() == Material.LAVA && (state2.getBlock() == Blocks.LAVA || state2.getBlock() == Blocks.FLOWING_LAVA) && state2.getValue(BlockLiquid.LEVEL) == 0 && world.mayPlace(WizardryBlocks.obsidian_crust, pos2, false, EnumFacing.DOWN, null)){ + if(WizardryUtilities.isLavaSource(state2) && world.mayPlace(WizardryBlocks.obsidian_crust, pos2, false, EnumFacing.DOWN, null)){ world.setBlockState(pos2, WizardryBlocks.obsidian_crust.getDefaultState()); world.scheduleUpdate(pos2.toImmutable(), WizardryBlocks.obsidian_crust, MathHelper.getInt(living.getRNG(), 60, 120)); } diff --git a/src/main/java/electroblob/wizardry/spell/Freeze.java b/src/main/java/electroblob/wizardry/spell/Freeze.java index 3d0b1cf2..6f026dc8 100644 --- a/src/main/java/electroblob/wizardry/spell/Freeze.java +++ b/src/main/java/electroblob/wizardry/spell/Freeze.java @@ -9,6 +9,8 @@ import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.monster.EntityBlaze; @@ -29,6 +31,7 @@ public class Freeze extends SpellRay { this.soundValues(1, 1.4f, 0.4f); addProperties(DAMAGE, EFFECT_DURATION, EFFECT_STRENGTH); this.hitLiquids(true); + this.ignoreUncollidables(false); } @Override @@ -61,18 +64,8 @@ public class Freeze extends SpellRay { @Override protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){ - if(WizardryUtilities.canDamageBlocks(caster, world)){ - - if(world.getBlockState(pos).getBlock() == Blocks.WATER && !world.isRemote){ - world.setBlockState(pos, Blocks.ICE.getDefaultState()); - }else if(world.getBlockState(pos).getBlock() == Blocks.LAVA && !world.isRemote){ - world.setBlockState(pos, Blocks.OBSIDIAN.getDefaultState()); - }else if(world.getBlockState(pos).getBlock() == Blocks.FLOWING_LAVA && !world.isRemote){ - world.setBlockState(pos, Blocks.COBBLESTONE.getDefaultState()); - }else if(side == EnumFacing.UP && !world.isRemote && world.isSideSolid(pos, EnumFacing.UP) - && WizardryUtilities.canBlockBeReplaced(world, pos.up())){ - world.setBlockState(pos.up(), Blocks.SNOW_LAYER.getDefaultState()); - } + if(!world.isRemote && WizardryUtilities.canDamageBlocks(caster, world)){ + WizardryUtilities.freeze(world, pos, true); } return true; // Always succeeds if it hits a block diff --git a/src/main/java/electroblob/wizardry/spell/IceAge.java b/src/main/java/electroblob/wizardry/spell/IceAge.java index 3d399ac0..5e09ed8c 100644 --- a/src/main/java/electroblob/wizardry/spell/IceAge.java +++ b/src/main/java/electroblob/wizardry/spell/IceAge.java @@ -11,10 +11,10 @@ import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; +import electroblob.wizardry.util.WizardryUtilities.SurfaceCriteria; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.Blocks; import net.minecraft.potion.PotionEffect; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; @@ -64,30 +64,22 @@ public class IceAge extends Spell { } if(!world.isRemote && WizardryUtilities.canDamageBlocks(caster, world)){ - for(int i = -(int)radius; i < (int)radius + 1; i++){ - for(int j = -(int)radius; j < (int)radius + 1; j++){ + for(int i = -(int)radius; i <= (int)radius; i++){ + for(int j = -(int)radius; j <= (int)radius; j++){ BlockPos pos = new BlockPos(caster).add(i, 0, j); - Integer y = WizardryUtilities.getNearestSurface(world, new BlockPos(pos), EnumFacing.UP, (int)radius, true, WizardryUtilities.SurfaceCriteria.BUILDABLE); + Integer y = WizardryUtilities.getNearestSurface(world, new BlockPos(pos), EnumFacing.UP, (int)radius, true, SurfaceCriteria.SOLID_LIQUID_TO_AIR); if(y != null){ pos = new BlockPos(pos.getX(), y, pos.getZ()); - double dist = caster.getDistance((int)caster.posX + i, y, (int)caster.posZ + j); + double dist = caster.getDistance(caster.posX + i, y, caster.posZ + j); // Randomised with weighting so that the nearer the block the more likely it is to be snowed. - if(y != -1 && world.rand.nextInt((int)dist * 2 + 1) < radius && dist < radius){ - if(world.getBlockState(pos.down()) == Blocks.WATER.getDefaultState()){ - world.setBlockState(pos.down(), Blocks.ICE.getDefaultState()); - }else if(world.getBlockState(pos.down()) == Blocks.LAVA.getDefaultState()){ - world.setBlockState(pos.down(), Blocks.OBSIDIAN.getDefaultState()); - }else if(world.getBlockState(pos.down()) == Blocks.FLOWING_LAVA.getDefaultState()){ - world.setBlockState(pos.down(), Blocks.COBBLESTONE.getDefaultState()); - }else if(Blocks.SNOW_LAYER.canPlaceBlockAt(world, pos)){ - world.setBlockState(pos, Blocks.SNOW_LAYER.getDefaultState()); - } + if(y != -1 && world.rand.nextInt((int)(dist * 2) + 1) < radius && dist < radius){ + WizardryUtilities.freeze(world, pos.down(), true); } } } diff --git a/src/main/java/electroblob/wizardry/util/WizardryUtilities.java b/src/main/java/electroblob/wizardry/util/WizardryUtilities.java index be7203d3..433c10bf 100644 --- a/src/main/java/electroblob/wizardry/util/WizardryUtilities.java +++ b/src/main/java/electroblob/wizardry/util/WizardryUtilities.java @@ -7,10 +7,8 @@ import electroblob.wizardry.data.WizardData; import electroblob.wizardry.entity.living.ISpellCaster; import electroblob.wizardry.item.ISpellCastingItem; import electroblob.wizardry.spell.Spell; -import net.minecraft.block.Block; -import net.minecraft.block.BlockCactus; -import net.minecraft.block.BlockChest; -import net.minecraft.block.BlockLog; +import net.minecraft.block.*; +import net.minecraft.block.material.Material; import net.minecraft.block.properties.IProperty; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.Entity; @@ -21,6 +19,7 @@ import net.minecraft.entity.monster.EntityCreeper; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.projectile.EntityArrow; import net.minecraft.entity.projectile.EntityThrowable; +import net.minecraft.init.Blocks; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.inventory.EntityEquipmentSlot.Type; import net.minecraft.item.Item; @@ -331,6 +330,52 @@ public final class WizardryUtilities { return null; } + /** + * Returns true if the given block is a water source block (specifically, water or flowing water with a level of 0). + * @param state The block state to query + * @return True if the given block state is a water source block, false otherwise. + */ + public static boolean isWaterSource(IBlockState state){ + return state.getMaterial() == Material.WATER && (state.getBlock() == Blocks.WATER || state.getBlock() == Blocks.FLOWING_WATER) && state.getValue(BlockLiquid.LEVEL) == 0; + } + + /** + * Returns true if the given block is a lava source block (specifically, lava or flowing lava with a level of 0). + * @param state The block state to query + * @return True if the given block state is a lava source block, false otherwise. + */ + public static boolean isLavaSource(IBlockState state){ + return state.getMaterial() == Material.LAVA && (state.getBlock() == Blocks.LAVA || state.getBlock() == Blocks.FLOWING_LAVA) && state.getValue(BlockLiquid.LEVEL) == 0; + } + + /** + * Freezes the given block, either by turning water to ice, lava to obsidian/cobblestone or by placing snow on top + * of it if possible. + * @param world The world the block is in + * @param pos The position of the block to freeze + * @param freezeLava True to freeze lava into obsidian or cobblestone, false to leave it unchanged + * @return True if any blocks were changed, false if not. + */ + public static boolean freeze(World world, BlockPos pos, boolean freezeLava){ + + IBlockState state = world.getBlockState(pos); + Block block = state.getBlock(); + + if(WizardryUtilities.isWaterSource(state)){ + world.setBlockState(pos, Blocks.ICE.getDefaultState()); + }else if(freezeLava && WizardryUtilities.isLavaSource(state)){ + world.setBlockState(pos, Blocks.OBSIDIAN.getDefaultState()); + }else if(freezeLava && (block == Blocks.LAVA || block == Blocks.FLOWING_LAVA)){ + world.setBlockState(pos, Blocks.COBBLESTONE.getDefaultState()); + }else if(block.isReplaceable(world, pos.up()) && Blocks.SNOW_LAYER.canPlaceBlockAt(world, pos.up())){ + world.setBlockState(pos.up(), Blocks.SNOW_LAYER.getDefaultState()); + }else{ + return false; + } + + return true; + } + /** * Finds the nearest floor level in the given direction from the given position, * within the range specified. This is a shorthand for