Search in sources :

Example 1 with BlockStateCache

use of com.teamwizardry.wizardry.api.spell.SpellDataTypes.BlockStateCache in project Wizardry by TeamWizardry.

the class ModuleInstance method getCachableBlockstate.

/**
 * Convenience method for renderVisualization
 */
@Nonnull
public final IBlockState getCachableBlockstate(@Nonnull World world, @Nonnull BlockPos targetBlock, @Nonnull SpellData data) {
    BlockStateCache cacheData = data.getData(SpellData.DefaultKeys.BLOCKSTATE_CACHE);
    Map<BlockPos, IBlockState> cache;
    IBlockState state;
    if (cacheData != null && cacheData.getBlockStateCache() != null) {
        cache = cacheData.getBlockStateCache();
        if (cache.containsKey(targetBlock)) {
            return cache.get(targetBlock);
        } else {
            cache.put(targetBlock, state = world.getBlockState(targetBlock));
            data.addData(BLOCKSTATE_CACHE, new BlockStateCache(cache));
        }
    } else {
        cache = new HashMap<>();
        cache.put(targetBlock, state = world.getBlockState(targetBlock));
        data.addData(BLOCKSTATE_CACHE, new BlockStateCache(cache));
    }
    return state;
}
Also used : IBlockState(net.minecraft.block.state.IBlockState) BlockStateCache(com.teamwizardry.wizardry.api.spell.SpellDataTypes.BlockStateCache) BlockPos(net.minecraft.util.math.BlockPos) Nonnull(javax.annotation.Nonnull)

Example 2 with BlockStateCache

use of com.teamwizardry.wizardry.api.spell.SpellDataTypes.BlockStateCache in project Wizardry by TeamWizardry.

the class ModuleEffectPhase method run.

@Override
public boolean run(@NotNull World world, ModuleInstanceEffect instance, @Nonnull SpellData spell, @Nonnull SpellRing spellRing) {
    Entity caster = spell.getCaster(world);
    Entity targetEntity = spell.getVictim(world);
    BlockPos targetPos = spell.getTargetPos();
    EnumFacing faceHit = spell.getFaceHit();
    double duration = spellRing.getAttributeValue(world, AttributeRegistry.DURATION, spell) * 20;
    double area = spellRing.getAttributeValue(world, AttributeRegistry.AREA, spell);
    double range = spellRing.getAttributeValue(world, AttributeRegistry.RANGE, spell);
    if (!spellRing.taxCaster(world, spell, true))
        return false;
    if (targetEntity instanceof EntityLivingBase) {
        EntityLivingBase entity = (EntityLivingBase) targetEntity;
        entity.addPotionEffect(new PotionEffect(ModPotions.PHASE, (int) duration, 0, true, false));
        world.playSound(null, targetEntity.getPosition(), ModSounds.ETHEREAL, SoundCategory.NEUTRAL, 1, 1);
    }
    if (targetPos != null && faceHit != null) {
        world.playSound(null, targetPos, ModSounds.ETHEREAL, SoundCategory.NEUTRAL, 1, 1);
        NemezTracker nemezDrive = WizardryNemezManager.getOrCreateNemezDrive(world, targetPos);
        BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos(targetPos);
        faceHit = faceHit.getOpposite();
        IBlockState targetState = world.getBlockState(mutable);
        if (BlockUtils.isAnyAir(targetState))
            return true;
        Set<BlockPos> poses = new HashSet<>();
        HashMap<BlockPos, IBlockState> stateCache = new HashMap<>();
        int rangeTick = 0;
        while (rangeTick <= (int) range) {
            AxisAlignedBB bb = new AxisAlignedBB(mutable, mutable);
            switch(faceHit) {
                case DOWN:
                case UP:
                    bb = bb.grow(area + 1, 0, area + 1);
                    break;
                case NORTH:
                case SOUTH:
                    bb = bb.grow(area + 1, area + 1, 0);
                    break;
                case WEST:
                case EAST:
                    bb = bb.grow(0, area + 1, area + 1);
                    break;
            }
            Set<BlockPos> edges = new HashSet<>();
            switch(faceHit) {
                case DOWN:
                case UP:
                    for (int x = (int) bb.minX; x <= (int) bb.maxX; x++) {
                        for (int z = (int) bb.minZ; z <= (int) bb.maxZ; z++) {
                            if (x == (int) bb.maxX || x == (int) bb.minX) {
                                edges.add(new BlockPos(x, mutable.getY(), z));
                            } else if (z == (int) bb.minZ || z == (int) bb.maxZ) {
                                edges.add(new BlockPos(x, mutable.getY(), z));
                            }
                        }
                    }
                    break;
                case NORTH:
                case SOUTH:
                    for (int x = (int) bb.minX; x <= (int) bb.maxX; x++) {
                        for (int y = (int) bb.minY; y <= (int) bb.maxY; y++) {
                            if (y == (int) bb.maxY || y == (int) bb.minY) {
                                edges.add(new BlockPos(x, y, mutable.getZ()));
                            } else if (x == (int) bb.minX || x == (int) bb.maxX) {
                                edges.add(new BlockPos(x, y, mutable.getZ()));
                            }
                        }
                    }
                    break;
                case WEST:
                case EAST:
                    for (int z = (int) bb.minZ; z <= (int) bb.maxZ; z++) {
                        for (int y = (int) bb.minY; y <= (int) bb.maxY; y++) {
                            if (y == (int) bb.maxY || y == (int) bb.minY) {
                                edges.add(new BlockPos(mutable.getX(), y, z));
                            } else if (z == (int) bb.minZ || z == (int) bb.maxZ) {
                                edges.add(new BlockPos(mutable.getX(), y, z));
                            }
                        }
                    }
                    break;
            }
            HashMap<BlockPos, IBlockState> tmp = new HashMap<>();
            boolean fullAirPlane = true;
            int edgeAirCount = 0;
            int edgeBlockCount = 0;
            for (BlockPos pos : BlockPos.getAllInBox((int) bb.minX, (int) bb.minY, (int) bb.minZ, (int) bb.maxX, (int) bb.maxY, (int) bb.maxZ)) {
                IBlockState originalState = world.getBlockState(pos);
                Block block = originalState.getBlock();
                if (edges.contains(pos)) {
                    stateCache.put(pos, originalState);
                    if (block == Blocks.AIR)
                        edgeAirCount++;
                    else
                        edgeBlockCount++;
                    continue;
                }
                if (block != Blocks.AIR)
                    fullAirPlane = false;
                if (block == ModBlocks.FAKE_AIR)
                    continue;
                if (world.getTileEntity(pos) != null)
                    continue;
                tmp.put(pos, originalState);
            }
            if (!fullAirPlane) {
                if (edgeAirCount <= edgeBlockCount) {
                    for (Map.Entry<BlockPos, IBlockState> entry : tmp.entrySet()) {
                        nemezDrive.trackBlock(entry.getKey(), entry.getValue());
                        IBlockState state = ModBlocks.FAKE_AIR.getDefaultState();
                        BlockUtils.placeBlock(world, entry.getKey(), state, (EntityPlayerMP) caster);
                        stateCache.put(entry.getKey(), state);
                        nemezDrive.trackBlock(entry.getKey(), state);
                    }
                    poses.addAll(tmp.keySet());
                } else {
                    for (Map.Entry<BlockPos, IBlockState> entry : tmp.entrySet()) {
                        if (entry.getValue().getBlock() == Blocks.AIR) {
                            stateCache.put(entry.getKey(), entry.getValue());
                            continue;
                        }
                        nemezDrive.trackBlock(entry.getKey(), entry.getValue());
                        IBlockState state = ModBlocks.FAKE_AIR.getDefaultState();
                        BlockUtils.placeBlock(world, entry.getKey(), state, (EntityPlayerMP) caster);
                        stateCache.put(entry.getKey(), state);
                        nemezDrive.trackBlock(entry.getKey(), state);
                        poses.add(entry.getKey());
                    }
                }
            } else
                break;
            mutable.move(faceHit);
            rangeTick++;
        }
        nemezDrive.endUpdate();
        nemezDrive.collapse();
        // spell.addData(SpellData.DefaultKeys.NEMEZ, nemezDrive.serializeNBT());
        spell.addData(SpellData.DefaultKeys.BLOCK_SET, new BlockSet(poses));
        spell.addData(SpellData.DefaultKeys.BLOCKSTATE_CACHE, new BlockStateCache(stateCache));
        addDelayedSpell(world, spellRing, spell, (int) duration);
    }
    return true;
}
Also used : AxisAlignedBB(net.minecraft.util.math.AxisAlignedBB) Entity(net.minecraft.entity.Entity) IBlockState(net.minecraft.block.state.IBlockState) PotionEffect(net.minecraft.potion.PotionEffect) NemezTracker(com.teamwizardry.wizardry.common.core.nemez.NemezTracker) HashMap(java.util.HashMap) EnumFacing(net.minecraft.util.EnumFacing) BlockSet(com.teamwizardry.wizardry.api.spell.SpellDataTypes.BlockSet) BlockStateCache(com.teamwizardry.wizardry.api.spell.SpellDataTypes.BlockStateCache) EntityLivingBase(net.minecraft.entity.EntityLivingBase) Block(net.minecraft.block.Block) BlockPos(net.minecraft.util.math.BlockPos) Map(java.util.Map) HashMap(java.util.HashMap) HashSet(java.util.HashSet)

Example 3 with BlockStateCache

use of com.teamwizardry.wizardry.api.spell.SpellDataTypes.BlockStateCache in project Wizardry by TeamWizardry.

the class ModuleEffectPhase method renderSpell.

@Override
@SideOnly(Side.CLIENT)
public void renderSpell(World world, ModuleInstanceEffect instance, @Nonnull SpellData spell, @Nonnull SpellRing spellRing) {
    EnumFacing faceHit = spell.getFaceHit();
    Set<BlockPos> blockSet = spell.getDataWithFallback(SpellData.DefaultKeys.BLOCK_SET, new BlockSet(new HashSet<>())).getBlockSet();
    Map<BlockPos, IBlockState> blockStateCache = spell.getDataWithFallback(SpellData.DefaultKeys.BLOCKSTATE_CACHE, new BlockStateCache(new HashMap<>())).getBlockStateCache();
    HashMap<BlockPos, IBlockState> tmpCache = new HashMap<>(blockStateCache);
    double duration = spellRing.getAttributeValue(world, AttributeRegistry.DURATION, spell) * 20;
    PhasedBlockRenderer.addPhase(world, blockSet, (int) duration);
    if (faceHit != null) {
        for (Map.Entry<BlockPos, IBlockState> entry : tmpCache.entrySet()) {
            IBlockState thisState = entry.getValue();
            if (thisState.getBlock() != ModBlocks.FAKE_AIR)
                continue;
            ParticleBuilder glitter2 = new ParticleBuilder(10);
            glitter2.setRenderNormalLayer(new ResourceLocation(Wizardry.MODID, NBTConstants.MISC.SPARKLE_BLURRED));
            glitter2.disableRandom();
            ParticleSpawner.spawn(glitter2, world, new StaticInterp<>(new Vec3d(entry.getKey()).add(0.5, 0.5, 0.5)), 5, (int) duration, (aFloat, build) -> {
                build.setColor(Color.CYAN);
                // build.setAlphaFunction(new InterpFloatInOut(1f, 0.1f));
                build.setAlpha(RandUtil.nextFloat(0.05f, 0.2f));
                build.setPositionOffset(new Vec3d(RandUtil.nextDouble(-0.5, 0.5), RandUtil.nextDouble(-0.5, 0.5), RandUtil.nextDouble(-0.5, 0.5)));
                build.setMotion(new Vec3d(RandUtil.nextDouble(-0.001, 0.001), RandUtil.nextDouble(-0.001, 0.001), RandUtil.nextDouble(-0.001, 0.001)));
                build.setLifetime(RandUtil.nextInt(20, 40));
                build.setScaleFunction(new InterpFloatInOut(0.9f, 0.9f));
                build.setScale(RandUtil.nextFloat(0.1f, 0.3f));
            });
            BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos(entry.getKey());
            for (EnumFacing facing : EnumFacing.VALUES) {
                mutable.move(facing);
                IBlockState adjState;
                if (!blockStateCache.containsKey(mutable)) {
                    adjState = world.getBlockState(mutable);
                    blockStateCache.put(mutable.toImmutable(), adjState);
                } else
                    adjState = blockStateCache.get(mutable);
                if (adjState.getBlock() != Blocks.AIR && adjState.getBlock() != ModBlocks.FAKE_AIR) {
                    Vec3d directionOffsetVec = new Vec3d(facing.getOpposite().getDirectionVec()).scale(0.5);
                    Vec3d adjPos = new Vec3d(mutable).add(0.5, 0.5, 0.5).add(directionOffsetVec);
                    for (EnumFacing subFacing : getPerpendicularFacings(facing)) {
                        mutable.move(subFacing);
                        IBlockState subState;
                        if (!blockStateCache.containsKey(mutable)) {
                            subState = world.getBlockState(mutable);
                            blockStateCache.put(mutable.toImmutable(), subState);
                        } else
                            subState = blockStateCache.get(mutable);
                        if (BlockUtils.isAnyAir(subState)) {
                            Vec3d subPos = new Vec3d(mutable).add(0.5, 0.5, 0.5).add(directionOffsetVec);
                            Vec3d midPointVec = new Vec3d((adjPos.x + subPos.x) / 2.0, (adjPos.y + subPos.y) / 2.0, (adjPos.z + subPos.z) / 2.0);
                            Vec3d sub = subPos.subtract(adjPos);
                            EnumFacing adjSubFacing = EnumFacing.getFacingFromVector((float) sub.x, (float) sub.y, (float) sub.z);
                            Vec3d cross = new Vec3d(adjSubFacing.getDirectionVec()).crossProduct(new Vec3d(facing.getDirectionVec())).normalize().scale(0.5);
                            ParticleBuilder glitter = new ParticleBuilder(10);
                            glitter.setRenderNormalLayer(new ResourceLocation(Wizardry.MODID, NBTConstants.MISC.SPARKLE_BLURRED));
                            glitter.disableRandom();
                            ParticleSpawner.spawn(glitter, world, new StaticInterp<>(midPointVec), 50, (int) duration, (aFloat, build) -> {
                                build.setColor(Color.CYAN);
                                // build.setAlphaFunction(new InterpFloatInOut(1f, 0.1f));
                                build.setAlpha(RandUtil.nextFloat(0.3f, 0.7f));
                                build.setPositionOffset(cross.scale(RandUtil.nextFloat(-1, 1)));
                                build.setLifetime(RandUtil.nextInt(20, 40));
                                build.setScaleFunction(new InterpFloatInOut(0.9f, 0.9f));
                                build.setScale(RandUtil.nextFloat(0.2f, 0.5f));
                            });
                        }
                        mutable.move(subFacing.getOpposite());
                    }
                }
                mutable.move(facing.getOpposite());
            }
        }
    }
}
Also used : IBlockState(net.minecraft.block.state.IBlockState) HashMap(java.util.HashMap) EnumFacing(net.minecraft.util.EnumFacing) BlockSet(com.teamwizardry.wizardry.api.spell.SpellDataTypes.BlockSet) ParticleBuilder(com.teamwizardry.librarianlib.features.particle.ParticleBuilder) Vec3d(net.minecraft.util.math.Vec3d) InterpFloatInOut(com.teamwizardry.librarianlib.features.math.interpolate.numeric.InterpFloatInOut) BlockStateCache(com.teamwizardry.wizardry.api.spell.SpellDataTypes.BlockStateCache) ResourceLocation(net.minecraft.util.ResourceLocation) BlockPos(net.minecraft.util.math.BlockPos) Map(java.util.Map) HashMap(java.util.HashMap) SideOnly(net.minecraftforge.fml.relauncher.SideOnly)

Aggregations

BlockStateCache (com.teamwizardry.wizardry.api.spell.SpellDataTypes.BlockStateCache)3 IBlockState (net.minecraft.block.state.IBlockState)3 BlockPos (net.minecraft.util.math.BlockPos)3 BlockSet (com.teamwizardry.wizardry.api.spell.SpellDataTypes.BlockSet)2 HashMap (java.util.HashMap)2 Map (java.util.Map)2 EnumFacing (net.minecraft.util.EnumFacing)2 InterpFloatInOut (com.teamwizardry.librarianlib.features.math.interpolate.numeric.InterpFloatInOut)1 ParticleBuilder (com.teamwizardry.librarianlib.features.particle.ParticleBuilder)1 NemezTracker (com.teamwizardry.wizardry.common.core.nemez.NemezTracker)1 HashSet (java.util.HashSet)1 Nonnull (javax.annotation.Nonnull)1 Block (net.minecraft.block.Block)1 Entity (net.minecraft.entity.Entity)1 EntityLivingBase (net.minecraft.entity.EntityLivingBase)1 PotionEffect (net.minecraft.potion.PotionEffect)1 ResourceLocation (net.minecraft.util.ResourceLocation)1 AxisAlignedBB (net.minecraft.util.math.AxisAlignedBB)1 Vec3d (net.minecraft.util.math.Vec3d)1 SideOnly (net.minecraftforge.fml.relauncher.SideOnly)1