diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/BlockConverter.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/BlockConverter.java index d60806686..33f91ceeb 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/BlockConverter.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/BlockConverter.java @@ -121,8 +121,7 @@ private void registerNOVAToMinecraft() { public boolean canReplace() { return true; } - }, evt -> { - }); + }, evt -> {}); blockManager.register(airBlock); diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/backward/BWBlock.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/backward/BWBlock.java index bc77bdc03..284017c89 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/backward/BWBlock.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/backward/BWBlock.java @@ -69,9 +69,11 @@ public BWBlock(net.minecraft.block.Block block) { public BWBlock(net.minecraft.block.Block block, World world, Vector3D pos) { this.mcBlock = block; components.add(new BWBlockTransform(this, world, pos)); - components.add(new BlockProperty.Opacity().setOpacity(mcBlock.getMaterial().isOpaque() ? 1 : 0)); - if (mcBlock.isReplaceable(blockAccess(), xi(), yi(), zi())) - components.add(BlockProperty.Replaceable.instance()); + components.add(new BlockProperty.Opacity()).setOpacity(() -> mcBlock.getMaterial().isOpaque() ? 1 : 0); + BlockProperty.Replaceable replaceable = components.add(new BlockProperty.Replaceable()); + if (block != Blocks.air) { + replaceable.setReplaceable(() -> mcBlock.canPlaceBlockAt((net.minecraft.world.World) blockAccess(), xi(), yi(), zi())); + } BlockProperty.BlockSound blockSound = components.add(new BlockProperty.BlockSound()); blockSound.setBlockSound(BlockProperty.BlockSound.BlockSoundTrigger.PLACE, new Sound("", mcBlock.stepSound.func_150496_b())); @@ -147,11 +149,6 @@ public Optional getTileEntity() { return Optional.ofNullable(mcTileEntity); } - @Override - public boolean canReplace() { - return mcBlock.canPlaceBlockAt((net.minecraft.world.World) blockAccess(), xi(), yi(), zi()); - } - @Override public boolean shouldDisplacePlacement() { if (mcBlock == Blocks.snow_layer && (blockAccess().getBlockMetadata(xi(), yi(), zi()) & 7) < 1) { diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/forward/FWBlock.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/forward/FWBlock.java index 0db19bd8d..3b4e8bf29 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/forward/FWBlock.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/forward/FWBlock.java @@ -494,11 +494,34 @@ public void renderItem(ItemRenderType type, ItemStack item, Object... data) { @Override public float getExplosionResistance(Entity expEntity, World world, int x, int y, int z, double explosionX, double p_explosionresistance, double explosionY) { // TODO: Maybe do something withPriority these parameters. - return (float) getBlockInstance(world, new Vector3D(x, y, z)).getResistance() * 30; + + // This number was calculated from the blast resistance of Stone, + // which requires exactly one cubic meter of TNT to get blown up. + // + // 1. During construction, the setResistance method is called + // on minecraft:stone with a value of 10. + // + // 2. The setResistance method multiplies that by 3 and assigns + // the result to the blockResistance instance variable. + // + // 3. Finally, the getExplosionResistance method divides the + // blockResistance instance variable by 5 and returns the result. + // + // From this we see that minecraft:stone’s final blast resistance is 6. + + return (float) getBlockInstance(world, new Vector3D(x, y, z)).getResistance() * 6; } @Override public float getBlockHardness(World world, int x, int y, int z) { return (float) getBlockInstance(world, new Vector3D(x, y, z)).getHardness() * 2; } + + @Override + public boolean isReplaceable(IBlockAccess access, int x, int y, int z) { + return getBlockInstance(access, new Vector3D(x, y, z)) + .components.getOp(BlockProperty.Replaceable.class) + .filter(BlockProperty.Replaceable::isReplaceable) + .isPresent(); + } } diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/forward/FWBlockSound.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/forward/FWBlockSound.java index e88d46624..1c1a872e3 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/forward/FWBlockSound.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/forward/FWBlockSound.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2016 NOVA, All rights reserved. + * This library is free software, licensed under GNU Lesser General Public License version 3 + * + * This file is part of NOVA. + * + * NOVA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * NOVA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NOVA. If not, see . + */ + package nova.core.wrapper.mc.forge.v17.wrapper.block.forward; import net.minecraft.block.Block; diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/forward/ProxyMaterial.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/forward/ProxyMaterial.java index 9dfc41ce6..91361cbf3 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/forward/ProxyMaterial.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/forward/ProxyMaterial.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2016 NOVA, All rights reserved. + * This library is free software, licensed under GNU Lesser General Public License version 3 + * + * This file is part of NOVA. + * + * NOVA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * NOVA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NOVA. If not, see . + */ + package nova.core.wrapper.mc.forge.v17.wrapper.block.forward; import net.minecraft.block.material.MapColor; @@ -17,6 +37,7 @@ public class ProxyMaterial extends Material { * Construct a new proxy material. * @param color The map color. * @param opacity The Opacity to use. + * @param replaceable If this block is replaceable. */ public ProxyMaterial(MapColor color, Optional opacity, Optional replaceable) { super(color); @@ -24,13 +45,18 @@ public ProxyMaterial(MapColor color, Optional opacity, Op this.replaceable = replaceable; } + @Override + public boolean getCanBlockGrass() { + return opacity.isPresent() ? opacity.get().isOpaque() : super.isOpaque(); + } + @Override public boolean isOpaque() { - return opacity.isPresent() ? opacity.get().opacity == 1 : super.isOpaque(); + return opacity.isPresent() ? opacity.get().isOpaque() : super.isOpaque(); } @Override public boolean isReplaceable() { - return replaceable.isPresent() || super.isReplaceable(); + return replaceable.map(BlockProperty.Replaceable::isReplaceable).orElseGet(super::isReplaceable); } } diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/BlockConverter.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/BlockConverter.java index 0bb95ca85..f40bef205 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/BlockConverter.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/BlockConverter.java @@ -121,8 +121,7 @@ private void registerNOVAToMinecraft() { public boolean canReplace() { return true; } - }, evt -> { - }); + }, evt -> {}); blockManager.register(airBlock); diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/backward/BWBlock.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/backward/BWBlock.java index e26e1fb9a..a8c34fc54 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/backward/BWBlock.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/backward/BWBlock.java @@ -74,9 +74,11 @@ public BWBlock(net.minecraft.block.Block block) { public BWBlock(net.minecraft.block.Block block, World world, Vector3D pos) { this.mcBlock = block; components.add(new BWBlockTransform(this, world, pos)); - components.add(new BlockProperty.Opacity().setOpacity(mcBlock.getMaterial().blocksLight() ? 1 : 0)); - if (mcBlock.isReplaceable((net.minecraft.world.World) blockAccess(), new BlockPos(x(), y(), z()))) - components.add(BlockProperty.Replaceable.instance()); + components.add(new BlockProperty.Opacity()).setOpacity(() -> mcBlock.getMaterial().isOpaque() ? 1 : 0); + BlockProperty.Replaceable replaceable = components.add(new BlockProperty.Replaceable()); + if (block != Blocks.air) { + replaceable.setReplaceable(() -> mcBlock.canPlaceBlockAt((net.minecraft.world.World) blockAccess(), blockPos())); + } BlockProperty.BlockSound blockSound = components.add(new BlockProperty.BlockSound()); blockSound.setBlockSound(BlockProperty.BlockSound.BlockSoundTrigger.PLACE, new Sound("", mcBlock.stepSound.getPlaceSound())); @@ -164,18 +166,13 @@ public Optional getTileEntity() { return Optional.ofNullable(mcTileEntity); } - @Override - public boolean canReplace() { - return mcBlock.canPlaceBlockAt((net.minecraft.world.World) blockAccess(), new BlockPos(x(), y(), z())); - } - @Override public boolean shouldDisplacePlacement() { if (mcBlock == Blocks.snow_layer && ((int) blockState().getValue(BlockSnow.LAYERS) < 1)) { return false; } - if (mcBlock == Blocks.vine || mcBlock == Blocks.tallgrass || mcBlock == Blocks.deadbush || mcBlock.isReplaceable((net.minecraft.world.World) WorldConverter.instance().toNative(world()), new BlockPos(x(), y(), z()))) { + if (mcBlock == Blocks.vine || mcBlock == Blocks.tallgrass || mcBlock == Blocks.deadbush || mcBlock.isReplaceable((net.minecraft.world.World) blockAccess(), blockPos())) { return false; } return super.shouldDisplacePlacement(); diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/FWBlock.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/FWBlock.java index 3572c998e..1417d0e38 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/FWBlock.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/FWBlock.java @@ -162,7 +162,7 @@ public void onBlockHarvested(World world, BlockPos pos, IBlockState state, Entit // hack is needed because the player sets the block to air *before* // getting the drops. woo good logic from mojang. if (!player.capabilities.isCreativeMode) { - harvestedBlocks.put(new BlockPosition(world, pos.getX(), pos.getY(), pos.getZ()), getBlockInstance(world, new Vector3D(pos.getX(), pos.getY(), pos.getZ()))); + harvestedBlocks.put(new BlockPosition(world, pos.getX(), pos.getY(), pos.getZ()), getBlockInstance(world, VectorConverter.instance().toNova(pos))); } } @@ -176,7 +176,7 @@ public List getDrops(IBlockAccess world, BlockPos pos, IBlockState st if (harvestedBlocks.containsKey(position)) { blockInstance = harvestedBlocks.remove(position); } else { - blockInstance = getBlockInstance(world, new Vector3D(pos.getX(), pos.getY(), pos.getZ())); + blockInstance = getBlockInstance(world, VectorConverter.instance().toNova(pos)); } Block.DropEvent event = new Block.DropEvent(blockInstance); @@ -260,7 +260,7 @@ public void onEntityCollidedWithBlock(World world, BlockPos pos, Entity entity) @Override public void setBlockBoundsBasedOnState(IBlockAccess access, BlockPos pos) { - Block blockInstance = getBlockInstance(access, new Vector3D(pos.getX(), pos.getY(), pos.getZ())); + Block blockInstance = getBlockInstance(access, VectorConverter.instance().toNova(pos)); if (blockInstance.components.has(Collider.class)) { Cuboid cuboid = blockInstance.components.get(Collider.class).boundingBox.get(); setBlockBounds((float) cuboid.min.getX(), (float) cuboid.min.getY(), (float) cuboid.min.getZ(), (float) cuboid.max.getX(), (float) cuboid.max.getY(), (float) cuboid.max.getZ()); @@ -269,7 +269,7 @@ public void setBlockBoundsBasedOnState(IBlockAccess access, BlockPos pos) { @Override public AxisAlignedBB getSelectedBoundingBox(World world, BlockPos pos) { - Block blockInstance = getBlockInstance(world, new Vector3D(pos.getX(), pos.getY(), pos.getZ())); + Block blockInstance = getBlockInstance(world, VectorConverter.instance().toNova(pos)); if (blockInstance.components.has(Collider.class)) { Cuboid cuboid = blockInstance.components.get(Collider.class).boundingBox.get(); @@ -281,7 +281,7 @@ public AxisAlignedBB getSelectedBoundingBox(World world, BlockPos pos) { @Override @SuppressWarnings({"unchecked", "rawtypes"}) public void addCollisionBoxesToList(World world, BlockPos pos, IBlockState state, AxisAlignedBB mask, List list, Entity entity) { - Block blockInstance = getBlockInstance(world, new Vector3D(pos.getX(), pos.getY(), pos.getZ())); + Block blockInstance = getBlockInstance(world, VectorConverter.instance().toNova(pos)); blockInstance.components.getOp(Collider.class).ifPresent( collider -> { Set boxes = collider.occlusionBoxes.apply(Optional.ofNullable(entity != null ? EntityConverter.instance().toNova(entity) : null)); @@ -332,7 +332,7 @@ public boolean isFullCube() { @Override public int getLightValue(IBlockAccess access, BlockPos pos) { - Block blockInstance = getBlockInstance(access, new Vector3D(pos.getX(), pos.getY(), pos.getZ())); + Block blockInstance = getBlockInstance(access, VectorConverter.instance().toNova(pos)); Optional opEmitter = blockInstance.components.getOp(LightEmitter.class); if (opEmitter.isPresent()) { @@ -349,7 +349,7 @@ public EnumWorldBlockLayer getBlockLayer() { @Override public boolean canConnectRedstone(IBlockAccess access, BlockPos pos, EnumFacing side) { - Block blockInstance = getBlockInstance(access, new Vector3D(pos.getX(), pos.getY(), pos.getZ())); + Block blockInstance = getBlockInstance(access, VectorConverter.instance().toNova(pos)); WrapperEvent.RedstoneConnect event = new WrapperEvent.RedstoneConnect(blockInstance.world(), blockInstance.position(), Direction.fromOrdinal(side.ordinal())); Game.events().publish(event); return event.canConnect; @@ -357,7 +357,7 @@ public boolean canConnectRedstone(IBlockAccess access, BlockPos pos, EnumFacing @Override public int isProvidingWeakPower(IBlockAccess access, BlockPos pos, IBlockState state, EnumFacing side) { - Block blockInstance = getBlockInstance(access, new Vector3D(pos.getX(), pos.getY(), pos.getZ())); + Block blockInstance = getBlockInstance(access, VectorConverter.instance().toNova(pos)); WrapperEvent.WeakRedstone event = new WrapperEvent.WeakRedstone(blockInstance.world(), blockInstance.position(), Direction.fromOrdinal(side.ordinal())); Game.events().publish(event); return event.power; @@ -365,7 +365,7 @@ public int isProvidingWeakPower(IBlockAccess access, BlockPos pos, IBlockState s @Override public int isProvidingStrongPower(IBlockAccess access, BlockPos pos, IBlockState state, EnumFacing side) { - Block blockInstance = getBlockInstance(access, new Vector3D(pos.getX(), pos.getY(), pos.getZ())); + Block blockInstance = getBlockInstance(access, VectorConverter.instance().toNova(pos)); WrapperEvent.StrongRedstone event = new WrapperEvent.StrongRedstone(blockInstance.world(), blockInstance.position(), Direction.fromOrdinal(side.ordinal())); Game.events().publish(event); return event.power; @@ -384,11 +384,34 @@ public String getLocalizedName() { @Override public float getExplosionResistance(World world, BlockPos pos, Entity exploder, Explosion explosion) { // TODO: Maybe do something withPriority these parameters. - return (float) getBlockInstance(world, new Vector3D(pos.getX(), pos.getY(), pos.getZ())).getResistance() * 30; + + // This number was calculated from the blast resistance of Stone, + // which requires exactly one cubic meter of TNT to get blown up. + // + // 1. During construction, the setResistance method is called + // on minecraft:stone with a value of 10. + // + // 2. The setResistance method multiplies that by 3 and assigns + // the result to the blockResistance instance variable. + // + // 3. Finally, the getExplosionResistance method divides the + // blockResistance instance variable by 5 and returns the result. + // + // From this we see that minecraft:stone’s final blast resistance is 6. + + return (float) getBlockInstance(world, VectorConverter.instance().toNova(pos)).getResistance() * 6; } @Override public float getBlockHardness(World world, BlockPos pos) { - return (float) getBlockInstance(world, new Vector3D(pos.getX(), pos.getY(), pos.getZ())).getHardness() * 2; + return (float) getBlockInstance(world, VectorConverter.instance().toNova(pos)).getHardness() * 2; + } + + @Override + public boolean isReplaceable(World world, BlockPos pos) { + return getBlockInstance(world, VectorConverter.instance().toNova(pos)) + .components.getOp(BlockProperty.Replaceable.class) + .filter(BlockProperty.Replaceable::isReplaceable) + .isPresent(); } } diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/FWBlockSound.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/FWBlockSound.java index 812d5cd4e..072c8e599 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/FWBlockSound.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/FWBlockSound.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2016 NOVA, All rights reserved. + * This library is free software, licensed under GNU Lesser General Public License version 3 + * + * This file is part of NOVA. + * + * NOVA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * NOVA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NOVA. If not, see . + */ + package nova.core.wrapper.mc.forge.v18.wrapper.block.forward; import net.minecraft.block.Block; diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/ProxyMaterial.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/ProxyMaterial.java index df9f5a92f..f47888372 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/ProxyMaterial.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/ProxyMaterial.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2016 NOVA, All rights reserved. + * This library is free software, licensed under GNU Lesser General Public License version 3 + * + * This file is part of NOVA. + * + * NOVA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * NOVA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NOVA. If not, see . + */ + package nova.core.wrapper.mc.forge.v18.wrapper.block.forward; import net.minecraft.block.material.MapColor; @@ -17,6 +37,7 @@ public class ProxyMaterial extends Material { * Construct a new proxy material. * @param color The map color. * @param opacity The Opacity to use. + * @param replaceable If this block is replaceable. */ public ProxyMaterial(MapColor color, Optional opacity, Optional replaceable) { super(color); @@ -26,16 +47,16 @@ public ProxyMaterial(MapColor color, Optional opacity, Op @Override public boolean blocksLight() { - return opacity.isPresent() ? opacity.get().opacity == 1 : super.blocksLight(); + return opacity.isPresent() ? opacity.get().isOpaque() : super.blocksLight(); } @Override public boolean isOpaque() { - return opacity.isPresent() ? opacity.get().opacity == 1 : super.isOpaque(); + return opacity.isPresent() ? opacity.get().isOpaque() : super.isOpaque(); } @Override public boolean isReplaceable() { - return replaceable.isPresent() || super.isReplaceable(); + return replaceable.map(BlockProperty.Replaceable::isReplaceable).orElseGet(super::isReplaceable); } } diff --git a/src/main/java/nova/core/block/Block.java b/src/main/java/nova/core/block/Block.java index 682089c6b..59e8b1e80 100644 --- a/src/main/java/nova/core/block/Block.java +++ b/src/main/java/nova/core/block/Block.java @@ -160,7 +160,7 @@ public double getResistance() { * @return True if this block can be replaced. */ public boolean canReplace() { - return false; + return components.getOp(BlockProperty.Replaceable.class).filter(BlockProperty.Replaceable::isReplaceable).isPresent(); } /** diff --git a/src/main/java/nova/core/block/component/BlockProperty.java b/src/main/java/nova/core/block/component/BlockProperty.java index 4999d1088..766368bd1 100644 --- a/src/main/java/nova/core/block/component/BlockProperty.java +++ b/src/main/java/nova/core/block/component/BlockProperty.java @@ -1,13 +1,36 @@ +/* + * Copyright (c) 2016 NOVA, All rights reserved. + * This library is free software, licensed under GNU Lesser General Public License version 3 + * + * This file is part of NOVA. + * + * NOVA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * NOVA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NOVA. If not, see . + */ + package nova.core.block.component; import nova.core.component.Component; import nova.core.component.SidedComponent; import nova.core.component.UnsidedComponent; import nova.core.sound.Sound; +import nova.core.util.math.MathUtil; import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.function.BooleanSupplier; +import java.util.function.DoubleSupplier; /** * Block properties. @@ -19,12 +42,12 @@ public interface BlockProperty { * The breaking difficulty of a block, or how long it takes to break a block. * Tools and armour may make the block break faster or slower than this. *

- * The standard, regular block hardness is 1. {@code Double.POSITIVE_INFINITY} is unbreakable. + * The standard, regular block hardness is 1. {@link Double#POSITIVE_INFINITY} is unbreakable. *

*/ @UnsidedComponent public static class Hardness extends Component implements BlockProperty { - private double hardness = 1.0; + private DoubleSupplier hardness = () -> 1; /** * Sets the breaking difficulty. @@ -32,49 +55,72 @@ public static class Hardness extends Component implements BlockProperty { * @param hardness The breaking difficulty. * @return This instance for chaining if desired. */ - public Hardness setHardness(double hardness) { + public Hardness setHardness(DoubleSupplier hardness) { this.hardness = hardness; return this; } + /** + * Sets the breaking difficulty. + * + * @param hardness The breaking difficulty. + * @return This instance for chaining if desired. + */ + public Hardness setHardness(double hardness) { + return this.setHardness(() -> hardness); + } + /** * Gets the breaking difficulty. * * @return The breaking difficulty. */ public double getHardness() { - return hardness; + return hardness.getAsDouble(); } } /** - * The blast resistance of a block. + * The blast resistance of a block, indicates how many cubic meters of TNT are needed to explode it. *

* The standard, regular block resistance is 1. {@link Double#POSITIVE_INFINITY} is unexplodable. *

*/ @UnsidedComponent public static class Resistance extends Component implements BlockProperty { - private double resistance = 1.0; + private DoubleSupplier resistance = () -> 1; /** - * Sets the blast resistance + * Sets the blast resistance, indicates how many cubic meters + * of TNT are needed to explode it. * * @param resistance The blast resistance. * @return This instance for chaining if desired. */ - public Resistance setResistance(double resistance) { + public Resistance setResistance(DoubleSupplier resistance) { this.resistance = resistance; return this; } /** - * Gets the blast resistance. + * Sets the blast resistance, indicates how many cubic meters + * of TNT are needed to explode it. + * + * @param resistance The blast resistance. + * @return This instance for chaining if desired. + */ + public Resistance setResistance(double resistance) { + return this.setResistance(() -> resistance); + } + + /** + * Gets the blast resistance, indicates how many cubic meters + * of TNT are needed to explode it. * * @return The blast resistance. */ public double getResistance() { - return resistance; + return resistance.getAsDouble(); } } @@ -152,11 +198,15 @@ public enum BlockSoundTrigger { * @author winsock */ @SidedComponent + @SuppressWarnings("deprecation") public static class Opacity extends Component implements BlockProperty { + private static final DoubleSupplier TRANSPARENT = () -> 0; + private static final DoubleSupplier OPAQUE = () -> 1; + /** * This value determines if the block should allow light through itself or not. */ - public double opacity = 1; + private DoubleSupplier opacity = OPAQUE; /** * Sets that the block should allow light through @@ -164,7 +214,17 @@ public static class Opacity extends Component implements BlockProperty { * @return This instance for chaining if desired. */ public Opacity setTransparent() { - opacity = 0; + opacity = TRANSPARENT; + return this; + } + + /** + * Sets that the block should disallow light through + * + * @return This instance for chaining if desired. + */ + public Opacity setOpaque() { + opacity = OPAQUE; return this; } @@ -174,39 +234,78 @@ public Opacity setTransparent() { * @param opacity The block's opacity * @return This instance for chaining if desired. */ - public Opacity setOpacity(double opacity) { + public Opacity setOpacity(DoubleSupplier opacity) { this.opacity = opacity; return this; } + + /** + * Sets if light should be transmitted through this block + * + * @param opacity The block's opacity + * @return This instance for chaining if desired. + */ + public Opacity setOpacity(double opacity) { + return this.setOpacity(opacity <= 0 ? TRANSPARENT : (opacity >= 1 ? OPAQUE : () -> opacity)); + } + + /** + * This value determines if the block should allow light through itself or not. + * + * @return The block's opacity + */ + public double getOpacity() { + return MathUtil.clamp(opacity.getAsDouble(), 0, 1); + } + + /** + * Checks if the block should allow light through + * + * @return If the block should allow light through + */ + public boolean isTransparent() { + return getOpacity() < 1; + } + + /** + * Checks if the block should disallow light through + * + * @return If the block should disallow light through + */ + public boolean isOpaque() { + return getOpacity() == 1; + } } /** * Indicates whether the block is replaceable. + * + * @author ExE Boss */ @UnsidedComponent - public static final class Replaceable extends Component implements BlockProperty { - private static final Replaceable instance = new Replaceable(); + public static class Replaceable extends Component implements BlockProperty { + private BooleanSupplier replaceable = () -> true; + + public Replaceable() {} /** - * Gets the singleton for Replaceable. + * Set the boolean supplier that is used to check if this block is replaceable. * - * @return The singleton for Replaceable. + * @param replaceable The replacement boolean supplier. + * @return This instance for chaining if desired. */ - public static Replaceable instance() { - return instance; - } - - private Replaceable() { - } - - @Override - public boolean equals(Object o) { - return this == o || o instanceof Replaceable; + public Replaceable setReplaceable(BooleanSupplier replaceable) { + this.replaceable = replaceable; + return this; } - @Override - public int hashCode() { - return Replaceable.class.hashCode(); + /** + * Check if this block can be replaced. + * + * @return if this block can be replaced. + */ + public boolean isReplaceable() { + return this.replaceable.getAsBoolean(); } } } diff --git a/src/test/java/nova/core/block/component/BlockPropertyTest.java b/src/test/java/nova/core/block/component/BlockPropertyTest.java new file mode 100644 index 000000000..ced3e6c1b --- /dev/null +++ b/src/test/java/nova/core/block/component/BlockPropertyTest.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2017 NOVA, All rights reserved. + * This library is free software, licensed under GNU Lesser General Public License version 3 + * + * This file is part of NOVA. + * + * NOVA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * NOVA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NOVA. If not, see . + */ + +package nova.core.block.component; + +import nova.core.sound.Sound; +import org.junit.Test; + +import static nova.testutils.NovaAssertions.assertThat; + +/** + * @author ExE Boss + */ +public class BlockPropertyTest { + + @Test + public void testHardness() { + BlockProperty.Hardness hardness = new BlockProperty.Hardness(); + assertThat(hardness.getHardness()).isEqualTo(1.0); + + hardness.setHardness(10.0); + assertThat(hardness.getHardness()).isEqualTo(10.0); + } + + @Test + public void testResistance() { + BlockProperty.Resistance resistance = new BlockProperty.Resistance(); + assertThat(resistance.getResistance()).isEqualTo(1.0); + + resistance.setResistance(10.0); + assertThat(resistance.getResistance()).isEqualTo(10.0); + } + + @Test + public void testBlockSound() { + BlockProperty.BlockSound sound = new BlockProperty.BlockSound(); + sound.setBlockSound(BlockProperty.BlockSound.BlockSoundTrigger.BREAK, new Sound("test", "break")); + sound.setBlockSound(BlockProperty.BlockSound.BlockSoundTrigger.PLACE, new Sound("test", "place")); + sound.setBlockSound(BlockProperty.BlockSound.BlockSoundTrigger.WALK, new Sound("test", "walk")); + sound.setBlockSound(BlockProperty.BlockSound.BlockSoundTrigger.CUSTOM_TRIGGER, new Sound("test", "custom")); + sound.setCustomBlockSound("test:custom", new Sound("test", "custom")); + + assertThat(sound.getSound(BlockProperty.BlockSound.BlockSoundTrigger.BREAK)).contains(new Sound("test", "break")); + assertThat(sound.getSound(BlockProperty.BlockSound.BlockSoundTrigger.PLACE)).contains(new Sound("test", "place")); + assertThat(sound.getSound(BlockProperty.BlockSound.BlockSoundTrigger.WALK)).contains(new Sound("test", "walk")); + assertThat(sound.getSound(BlockProperty.BlockSound.BlockSoundTrigger.CUSTOM_TRIGGER)).isEmpty(); + assertThat(sound.getCustomSound("test:custom")).contains(new Sound("test", "custom")); + } + + @Test + public void testOpacity() { + BlockProperty.Opacity opacity = new BlockProperty.Opacity().setOpaque(); + assertThat(opacity.getOpacity()).isEqualTo(1.0); + assertThat(opacity.isOpaque()).isTrue(); + assertThat(opacity.isTransparent()).isFalse(); + + opacity.setTransparent(); + assertThat(opacity.getOpacity()).isEqualTo(0.0); + assertThat(opacity.isOpaque()).isFalse(); + assertThat(opacity.isTransparent()).isTrue(); + + opacity.setOpacity(0.5); + assertThat(opacity.getOpacity()).isEqualTo(0.5); + assertThat(opacity.isOpaque()).isFalse(); + assertThat(opacity.isTransparent()).isTrue(); + + opacity.setOpacity(-0.5); + assertThat(opacity.getOpacity()).isEqualTo(0.0); + assertThat(opacity.isOpaque()).isFalse(); + assertThat(opacity.isTransparent()).isTrue(); + + opacity.setOpacity(1.5); + assertThat(opacity.getOpacity()).isEqualTo(1.0); + assertThat(opacity.isOpaque()).isTrue(); + assertThat(opacity.isTransparent()).isFalse(); + } + + @Test + public void testReplaceable() { + BlockProperty.Replaceable replaceable = new BlockProperty.Replaceable(); + assertThat(replaceable.isReplaceable()).isTrue(); + + replaceable.setReplaceable(() -> false); + assertThat(replaceable.isReplaceable()).isFalse(); + } +}