Steel mesh fence added, Broad Windowsill added, Tree Cutter can chop DyncmicTrees (issue #52).

This commit is contained in:
stfwi 2019-10-05 14:13:08 +02:00
parent 1eeaa1229e
commit 1b0a84ae7f
119 changed files with 3399 additions and 133 deletions

View file

@ -26,7 +26,6 @@ import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@ -229,6 +228,13 @@ public class ModContent
//--------------------------------------------------------------------------------------------------------------------
public static final BlockDecorFence STEEL_MESH_FENCE = new BlockDecorFence(
"steel_mesh_fence",
BlockDecor.CFG_DEFAULT, Material.IRON, 2f, 15f, SoundType.METAL
);
//--------------------------------------------------------------------------------------------------------------------
public static final BlockDecor TREATED_WOOD_TABLE = new BlockDecor(
"treated_wood_table",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT,
@ -250,13 +256,20 @@ public class ModContent
ModAuxiliaries.getPixeledAABB(2,0,2, 14,15.9,14)
);
public static final BlockDecorDirected TREATED_WOOD_WINDOWSILL = new BlockDecorDirected(
public static final BlockDecorWindowSill TREATED_WOOD_WINDOWSILL = new BlockDecorWindowSill(
"treated_wood_windowsill",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_FACING_PLACEMENT,
Material.WOOD, 1.0f, 10f, SoundType.WOOD,
ModAuxiliaries.getPixeledAABB(0.5,15,10.5, 15.5,16,16)
);
public static final BlockDecorWindowSill TREATED_WOOD_BROAD_WINDOWSILL = new BlockDecorWindowSill(
"treated_wood_broad_windowsill",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_FACING_PLACEMENT,
Material.WOOD, 1.0f, 10f, SoundType.WOOD,
ModAuxiliaries.getPixeledAABB(0,14.5,4, 16,16,16)
);
public static final BlockDecorDirected INSET_LIGHT_IRON = new BlockDecorDirected(
"iron_inset_light",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_OPPOSITE_PLACEMENT|(14<<BlockDecor.CFG_LIGHT_VALUE_SHIFT),
@ -491,6 +504,7 @@ public class ModContent
TREATED_WOOD_WINDOW,
STEEL_FRAMED_WINDOW,
TREATED_WOOD_WINDOWSILL,
TREATED_WOOD_BROAD_WINDOWSILL,
INSET_LIGHT_IRON,
TREATED_WOOD_POLE_SUPPORT,
TREATED_WOOD_POLE_HEAD,
@ -500,6 +514,7 @@ public class ModContent
THICK_STEEL_POLE_HEAD,
STEEL_DOUBLE_T_SUPPORT,
STEEL_FLOOR_GRATING,
STEEL_MESH_FENCE,
SIGN_HOTWIRE, SIGN_DANGER, SIGN_DEFENSE, SIGN_FACTORY_AREA, SIGN_EXIT, SIGN_MODLOGO,
TREATED_WOOD_SIDE_TABLE,
HALFSLAB_REBARCONCRETE, HALFSLAB_CONCRETE, HALFSLAB_TREATEDWOOD,
@ -563,7 +578,7 @@ public class ModContent
public static final void registerBlocks(RegistryEvent.Register<Block> event)
{
// Config based registry selection
final boolean ie_installed = Loader.isModLoaded("immersiveengineering");
final boolean ie_installed = ModAuxiliaries.isModLoaded("immersiveengineering");
int num_block_registrations_skipped = 0;
int num_block_registrations_skipped_noie = 0;
final boolean woor = ModConfig.isWithoutOptOutRegistration();

View file

@ -116,6 +116,7 @@ public class ModEngineersDecor
if(RecipeCondModSpecific.num_skipped > 0) logger.info("Excluded " + RecipeCondModSpecific.num_skipped + " recipes due to config opt-out.");
if(ModConfig.zmisc.with_experimental) logger.info("Included experimental features due to mod config.");
ExtItems.onPostInit();
TreeCutting.reload();
}
@Mod.EventBusSubscriber

View file

@ -0,0 +1,75 @@
/*
* @file BlockDecorFence.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Fence blocks.
*/
package wile.engineersdecor.blocks;
import net.minecraft.block.*;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
public class BlockDecorFence extends BlockDecorWall
{
protected static final AxisAlignedBB[] AABB_BY_INDEX = mkAABBs (1.5d, 0.5d, 16d);
protected static final AxisAlignedBB[] CLIP_AABB_BY_INDEX = mkAABBs (1.5d, 0.5d, 24d);
protected static final AxisAlignedBB[][] AABB_LIST_BY_INDEX = mkCAABBs(1.5d, 0.5d, 16d);
protected static final AxisAlignedBB[][] CLIP_AABB_LIST_BY_INDEX = mkCAABBs(1.5d, 0.5d, 24d);
public BlockDecorFence(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound)
{
super(registryName, config, material, hardness, resistance, sound);
setDefaultState(blockState.getBaseState().withProperty(UP, false).withProperty(NORTH, false).withProperty(EAST, false).withProperty(SOUTH, false).withProperty(WEST, false));
}
@Override
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
{ return AABB_BY_INDEX[getAABBIndex(getActualState(state, source, pos))]; }
@Override
@SuppressWarnings("deprecation")
public void addCollisionBoxToList(IBlockState state, World world, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, @Nullable Entity entityIn, boolean isActualState)
{
final AxisAlignedBB[] bbs = CLIP_AABB_LIST_BY_INDEX[getAABBIndex(isActualState ? state : getActualState(state, world, pos))];
for(int i=0; i<bbs.length;++i) addCollisionBoxToList(pos, entityBox, collidingBoxes, bbs[i]);
}
@Override
public AxisAlignedBB getCollisionBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos)
{ return CLIP_AABB_BY_INDEX[getAABBIndex(getActualState(state, world, pos))]; }
@Override
public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
{ return (face==EnumFacing.UP) ? (BlockFaceShape.SOLID) : ((face!=EnumFacing.DOWN) ? (BlockFaceShape.MIDDLE_POLE_THIN) : (BlockFaceShape.CENTER_SMALL)); }
@Override
protected BlockStateContainer createBlockState()
{ return new BlockStateContainer(this, new IProperty[] {UP, NORTH, EAST, WEST, SOUTH}); }
@Override
public IBlockState getActualState(IBlockState state, IBlockAccess world, BlockPos pos)
{
boolean n = canWallConnectTo(world, pos, EnumFacing.NORTH);
boolean e = canWallConnectTo(world, pos, EnumFacing.EAST);
boolean s = canWallConnectTo(world, pos, EnumFacing.SOUTH);
boolean w = canWallConnectTo(world, pos, EnumFacing.WEST);
boolean nopole = (n && s && !e && !w) || (!n && !s && e && w);
return state.withProperty(UP,!nopole).withProperty(NORTH, n).withProperty(EAST, e).withProperty(SOUTH, s).withProperty(WEST, w);
}
}

View file

@ -8,6 +8,7 @@
*/
package wile.engineersdecor.blocks;
import wile.engineersdecor.detail.ModAuxiliaries;
import net.minecraft.block.*;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
@ -18,6 +19,7 @@ import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.init.Blocks;
import net.minecraft.pathfinding.PathNodeType;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
@ -25,6 +27,7 @@ import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
@ -44,32 +47,72 @@ public class BlockDecorWall extends BlockDecor
public static final PropertyBool WEST = BlockWall.WEST;
public static final PropertyInteger TEXTURE_VARIANT = PropertyInteger.create("tvariant", 0, 7);
private static final double d_0 = 0.0d;
private static final double d_1 = 1.0d;
private static final double d_a = 0.25d;
private static final double d_b = 1.0d-d_a;
private static final double d_k = 0.26d; // 0.3125D;
private static final double d_l = 1.0d-d_k;
protected static final AxisAlignedBB[] AABB_BY_INDEX = new AxisAlignedBB[] {
new AxisAlignedBB(d_a, d_0, d_a, d_b, d_1, d_b),
new AxisAlignedBB(d_a, d_0, d_a, d_b, d_1, d_1),
new AxisAlignedBB(d_0, d_0, d_a, d_b, d_1, d_b),
new AxisAlignedBB(d_0, d_0, d_a, d_b, d_1, d_1),
new AxisAlignedBB(d_a, d_0, d_0, d_b, d_1, d_b),
new AxisAlignedBB(d_k, d_0, d_0, d_l, d_1, d_1),
new AxisAlignedBB(d_0, d_0, d_0, d_b, d_1, d_b),
new AxisAlignedBB(d_0, d_0, d_0, d_b, d_1, d_1),
new AxisAlignedBB(d_a, d_0, d_a, d_1, d_1, d_b),
new AxisAlignedBB(d_a, d_0, d_a, d_1, d_1, d_1),
new AxisAlignedBB(d_0, d_0, d_k, d_1, d_1, d_l),
new AxisAlignedBB(d_0, d_0, d_a, d_1, d_1, d_1),
new AxisAlignedBB(d_a, d_0, d_0, d_1, d_1, d_b),
new AxisAlignedBB(d_a, d_0, d_0, d_1, d_1, d_1),
new AxisAlignedBB(d_0, d_0, d_0, d_1, d_1, d_b),
new AxisAlignedBB(d_0, d_0, d_0, d_1, d_1, d_1)
};
private static final double clip_height = 1.8d;
protected static final AxisAlignedBB[] CLIP_AABB_BY_INDEX = new AxisAlignedBB[] { AABB_BY_INDEX[0].setMaxY(clip_height), AABB_BY_INDEX[1].setMaxY(clip_height), AABB_BY_INDEX[2].setMaxY(clip_height), AABB_BY_INDEX[3].setMaxY(clip_height), AABB_BY_INDEX[4].setMaxY(clip_height), AABB_BY_INDEX[5].setMaxY(clip_height), AABB_BY_INDEX[6].setMaxY(clip_height), AABB_BY_INDEX[7].setMaxY(clip_height), AABB_BY_INDEX[8].setMaxY(clip_height), AABB_BY_INDEX[9].setMaxY(clip_height), AABB_BY_INDEX[10].setMaxY(clip_height), AABB_BY_INDEX[11].setMaxY(clip_height), AABB_BY_INDEX[12].setMaxY(clip_height), AABB_BY_INDEX[13].setMaxY(clip_height), AABB_BY_INDEX[14].setMaxY(clip_height), AABB_BY_INDEX[15].setMaxY(clip_height) };
protected static final AxisAlignedBB[] mkAABBs(double pole_thickness_px, double wall_thickness_px, double height_px)
{
final double d_0 = 0.0d;
final double d_1 = 16.0d;
final double d_a = (8d-pole_thickness_px);
final double d_b = 16.0d-d_a;
final double d_k = (8d-wall_thickness_px);
final double d_l = 16.0d-d_k;
return new AxisAlignedBB[] { // ENWS P
ModAuxiliaries.getPixeledAABB(d_a, d_0, d_a, d_b, height_px, d_b), // 0000 1
ModAuxiliaries.getPixeledAABB(d_a, d_0, d_a, d_b, height_px, d_1), // 0001 1
ModAuxiliaries.getPixeledAABB(d_0, d_0, d_a, d_b, height_px, d_b), // 0010 1
ModAuxiliaries.getPixeledAABB(d_0, d_0, d_a, d_b, height_px, d_1), // 0011 1
ModAuxiliaries.getPixeledAABB(d_a, d_0, d_0, d_b, height_px, d_b), // 0100 1
ModAuxiliaries.getPixeledAABB(d_k, d_0, d_0, d_l, height_px, d_1), // 0101 0
ModAuxiliaries.getPixeledAABB(d_0, d_0, d_0, d_b, height_px, d_b), // 0110 1
ModAuxiliaries.getPixeledAABB(d_0, d_0, d_0, d_b, height_px, d_1), // 0111 1
ModAuxiliaries.getPixeledAABB(d_a, d_0, d_a, d_1, height_px, d_b), // 1000 1
ModAuxiliaries.getPixeledAABB(d_a, d_0, d_a, d_1, height_px, d_1), // 1001 1
ModAuxiliaries.getPixeledAABB(d_0, d_0, d_k, d_1, height_px, d_l), // 1010 0
ModAuxiliaries.getPixeledAABB(d_0, d_0, d_a, d_1, height_px, d_1), // 1011 1
ModAuxiliaries.getPixeledAABB(d_a, d_0, d_0, d_1, height_px, d_b), // 1100 1
ModAuxiliaries.getPixeledAABB(d_a, d_0, d_0, d_1, height_px, d_1), // 1101 1
ModAuxiliaries.getPixeledAABB(d_0, d_0, d_0, d_1, height_px, d_b), // 1110 1
ModAuxiliaries.getPixeledAABB(d_0, d_0, d_0, d_1, height_px, d_1) // 1111 1
};
}
protected static final AxisAlignedBB[][] mkCAABBs(double pole_thickness_px, double wall_thickness_px, double height_px)
{
final double d_0 = 0.0d;
final double d_1 = 16.0d;
final double d_a = (8d-pole_thickness_px);
final double d_b = 16.0d-d_a;
final double d_k = (8d-wall_thickness_px);
final double d_l = 16.0d-d_k;
final AxisAlignedBB bb_p = ModAuxiliaries.getPixeledAABB(d_a, d_0, d_a, d_b, height_px, d_b); // 0000
final AxisAlignedBB bb_s = ModAuxiliaries.getPixeledAABB(d_k, d_0, d_k, d_l, height_px, d_1); // 0001
final AxisAlignedBB bb_w = ModAuxiliaries.getPixeledAABB(d_0, d_0, d_k, d_l, height_px, d_l); // 0010
final AxisAlignedBB bb_n = ModAuxiliaries.getPixeledAABB(d_k, d_0, d_0, d_l, height_px, d_l); // 0100
final AxisAlignedBB bb_e = ModAuxiliaries.getPixeledAABB(d_k, d_0, d_k, d_1, height_px, d_l); // 1000
return new AxisAlignedBB[][] { // ENWS P
new AxisAlignedBB[]{ bb_p }, // 0000 1
new AxisAlignedBB[]{ bb_s }, // 0001 1
new AxisAlignedBB[]{ bb_w }, // 0010 1
new AxisAlignedBB[]{ bb_s,bb_w }, // 0011 1
new AxisAlignedBB[]{ bb_n }, // 0100 1
new AxisAlignedBB[]{ bb_n,bb_s }, // 0101 0
new AxisAlignedBB[]{ bb_n,bb_w }, // 0110 1
new AxisAlignedBB[]{ bb_n,bb_w,bb_s }, // 0111 1
new AxisAlignedBB[]{ bb_e }, // 1000 1
new AxisAlignedBB[]{ bb_e,bb_s }, // 1001 1
new AxisAlignedBB[]{ bb_e,bb_w }, // 1010 0
new AxisAlignedBB[]{ bb_e,bb_w,bb_s }, // 1011 1
new AxisAlignedBB[]{ bb_e,bb_n }, // 1100 1
new AxisAlignedBB[]{ bb_e,bb_n,bb_s }, // 1101 1
new AxisAlignedBB[]{ bb_e,bb_n,bb_w }, // 1110 1
new AxisAlignedBB[]{ bb_e,bb_n,bb_w,bb_s } // 1111 1
};
}
protected static final AxisAlignedBB[] AABB_BY_INDEX = mkAABBs(4d, 3.84, 16d);
protected static final AxisAlignedBB[] CLIP_AABB_BY_INDEX = mkAABBs(4d, 3.84, 24d);
protected static final AxisAlignedBB[][] AABB_LIST_BY_INDEX = mkCAABBs(4d, 3.84, 16d);
protected static final AxisAlignedBB[][] CLIP_AABB_LIST_BY_INDEX = mkCAABBs(4d, 3.84, 24d);
protected static final AxisAlignedBB SELECTION_AABB = ModAuxiliaries.getPixeledAABB(0, 0, 0, 0.01, 0.01, 0.01);
public BlockDecorWall(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound)
{
@ -84,18 +127,27 @@ public class BlockDecorWall extends BlockDecor
@Override
@SuppressWarnings("deprecation")
public void addCollisionBoxToList(IBlockState state, World world, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, @Nullable Entity entityIn, boolean isActualState)
{ addCollisionBoxToList(pos, entityBox, collidingBoxes, CLIP_AABB_BY_INDEX[getAABBIndex(isActualState ? state : getActualState(state, world, pos))]); }
{
final AxisAlignedBB[] bbs = CLIP_AABB_LIST_BY_INDEX[getAABBIndex(isActualState ? state : getActualState(state, world, pos))];
for(int i=0; i<bbs.length;++i) addCollisionBoxToList(pos, entityBox, collidingBoxes, bbs[i]);
}
@Nullable
@Override
public AxisAlignedBB getCollisionBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos)
{ return CLIP_AABB_BY_INDEX[getAABBIndex(getActualState(state, world, pos))]; }
private static int getAABBIndex(IBlockState state)
{ return ((!(state.getValue(NORTH))) ? 0 : (1<<EnumFacing.NORTH.getHorizontalIndex()))
| ((!(state.getValue( EAST))) ? 0 : (1<<EnumFacing.EAST.getHorizontalIndex()))
| ((!(state.getValue(SOUTH))) ? 0 : (1<<EnumFacing.SOUTH.getHorizontalIndex()))
| ((!(state.getValue( WEST))) ? 0 : (1<<EnumFacing.WEST.getHorizontalIndex()));
@Override
@SideOnly(Side.CLIENT)
@SuppressWarnings("deprecation")
public AxisAlignedBB getSelectedBoundingBox(IBlockState state, World world, BlockPos pos)
{ return SELECTION_AABB; }
protected static int getAABBIndex(IBlockState state)
{ return ((!(state.getValue(SOUTH))) ? 0 : (1<<EnumFacing.SOUTH.getHorizontalIndex())) // 0
| ((!(state.getValue( WEST))) ? 0 : (1<<EnumFacing.WEST.getHorizontalIndex())) // 1
| ((!(state.getValue(NORTH))) ? 0 : (1<<EnumFacing.NORTH.getHorizontalIndex())) // 2
| ((!(state.getValue( EAST))) ? 0 : (1<<EnumFacing.EAST.getHorizontalIndex())); // 3
}
@Override
@ -122,11 +174,11 @@ public class BlockDecorWall extends BlockDecor
public boolean canSpawnInBlock()
{ return false; }
private boolean canConnectTo(IBlockAccess world, BlockPos pos, BlockPos other, EnumFacing facing)
protected boolean canConnectTo(IBlockAccess world, BlockPos pos, BlockPos other, EnumFacing facing)
{
final IBlockState state = world.getBlockState(other);
final Block block = state.getBlock();
if((block instanceof BlockDecorWall) || (block instanceof BlockFenceGate)) return true;
if((block instanceof BlockDecorWall) || (block instanceof BlockFenceGate) || (block instanceof BlockDecorFence)) return true;
if(world.getBlockState(pos.offset(facing)).getBlock()!=this) return false;
if(block instanceof BlockFence) return true;
final BlockFaceShape shp = state.getBlockFaceShape(world, other, facing);
@ -173,11 +225,15 @@ public class BlockDecorWall extends BlockDecor
public boolean canBeConnectedTo(IBlockAccess world, BlockPos pos, EnumFacing facing)
{ return canConnectTo(world, pos, pos.offset(facing), facing.getOpposite()); }
private boolean canWallConnectTo(IBlockAccess world, BlockPos pos, EnumFacing facing)
protected boolean canWallConnectTo(IBlockAccess world, BlockPos pos, EnumFacing facing)
{ return canConnectTo(world, pos, pos.offset(facing), facing.getOpposite()); }
@Override
public boolean canPlaceTorchOnTop(IBlockState state, IBlockAccess world, BlockPos pos)
{ return true; }
@Override
public net.minecraft.pathfinding.PathNodeType getAiPathNodeType(IBlockState state, IBlockAccess world, BlockPos pos)
{ return PathNodeType.FENCE; }
}

View file

@ -0,0 +1,43 @@
/*
* @file BlockDecorWindowSill.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Block for windowsills to allow placing things on top
* (top side solid).
*/
package wile.engineersdecor.blocks;
import net.minecraft.block.material.Material;
import net.minecraft.block.SoundType;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BlockDecorWindowSill extends BlockDecorDirected
{
public BlockDecorWindowSill(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{ super(registryName, config|CFG_HORIZIONTAL, material, hardness, resistance, sound, unrotatedAABB); }
@Override
public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
{ return (face==EnumFacing.UP) ? BlockFaceShape.SOLID : BlockFaceShape.UNDEFINED; }
@Override
@SuppressWarnings("deprecation")
public boolean isSideSolid(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing side)
{ return side==EnumFacing.UP; }
@Override
@SuppressWarnings("deprecation")
public boolean isTopSolid(IBlockState state)
{ return true; }
}

View file

@ -9,6 +9,7 @@
package wile.engineersdecor.detail;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.fml.common.Loader;
import wile.engineersdecor.ModEngineersDecor;
import net.minecraft.world.World;
import net.minecraft.item.ItemStack;
@ -154,6 +155,9 @@ public class ModAuxiliaries
if(!s.isEmpty()) player.sendMessage(new TextComponentTranslation(s));
}
public static boolean isModLoaded(String id)
{ return Loader.isModLoaded(id); }
@SuppressWarnings("unused")
public interface IExperimentalFeature{}
}

View file

@ -8,25 +8,100 @@
*/
package wile.engineersdecor.detail;
import com.google.common.collect.ImmutableList;
import wile.engineersdecor.ModEngineersDecor;
import net.minecraft.init.Blocks;
import net.minecraft.block.Block;
import net.minecraft.block.BlockVine;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import com.google.common.collect.ImmutableList;
import java.util.*;
public class TreeCutting
{
private static org.apache.logging.log4j.Logger LOGGER = ModEngineersDecor.logger;
private static class Compat
{
enum ChoppingMethod { None, RootBlockBreaking }
private static final HashMap<IBlockState, ChoppingMethod> choppable_states = new HashMap<IBlockState, ChoppingMethod>();
public static long num_breaking_exceptions = 0;
static void reload()
{
try {
choppable_states.clear();
if(ModAuxiliaries.isModLoaded("dynamictrees")) {
ForgeRegistries.BLOCKS.getKeys().forEach((regname)->{
if("dynamictrees".equals(regname.getNamespace())) {
if(!regname.getPath().contains("branch")) return;
try {
Block block = ForgeRegistries.BLOCKS.getValue(regname);
IBlockState state = block.getDefaultState();
for(IProperty<?> vaprop: state.getProperties().keySet()) {
if(!("radius".equals(vaprop.getName())) || (vaprop.getValueClass() != Integer.class)) continue;
@SuppressWarnings("unchecked")
IProperty<Integer> prop = (IProperty<Integer>)vaprop;
Integer max = ((Collection<Integer>)prop.getAllowedValues()).stream().max(Integer::compare).orElse(0);
if(max<7) continue;
for(int r=7; r<=max; ++r) choppable_states.put(state.withProperty(prop, r), ChoppingMethod.RootBlockBreaking);
}
} catch(Throwable e) {
LOGGER.warn("Failed to register chopping for " + regname.toString());
return;
}
}
});
}
LOGGER.info("Dynamic Trees chopping compat: " + choppable_states.size() + " choppable states found.");
} catch(Throwable e) {
choppable_states.clear();
LOGGER.warn("Failed to determine choppings for dynamic trees compat, skipping that:" + e);
}
}
private static boolean canChop(IBlockState state)
{ return choppable_states.containsKey(state); }
private static int chop(World world, IBlockState state, BlockPos pos, int max_blocks_to_break, boolean without_target_block)
{
final int default_expense = 5;
switch(choppable_states.getOrDefault(state, ChoppingMethod.None)) {
case None:
return 0;
case RootBlockBreaking: {
if(num_breaking_exceptions < 16) {
try {
world.setBlockState(pos, Blocks.AIR.getDefaultState(), 1);
state.getBlock().breakBlock(world, pos, state);
} catch(Throwable e) {
if(++num_breaking_exceptions == 1) LOGGER.warn("Tree Chopper: There was an exception while trying to break a tree trunk ("+state.getBlock().getRegistryName()+"): " + e);
if(num_breaking_exceptions == 16) LOGGER.warn("Tree Chopper: There were 16 exceptions in total trying to chop modded trees. Feature has been disabled.");
}
}
return 5;
}
default:
return 0;
}
}
}
private static final List<Vec3i> hoffsets = ImmutableList.of(
new Vec3i( 1,0, 0), new Vec3i( 1,0, 1), new Vec3i( 0,0, 1),
new Vec3i(-1,0, 1), new Vec3i(-1,0, 0), new Vec3i(-1,0,-1),
new Vec3i( 0,0,-1), new Vec3i( 1,0,-1)
);
public static void reload()
{ Compat.reload(); }
private static List<BlockPos> findBlocksAround(final World world, final BlockPos centerPos, final IBlockState leaf_type_state, final Set<BlockPos> checked, int recursion_left)
{
ArrayList<BlockPos> to_decay = new ArrayList<BlockPos>();
@ -47,13 +122,14 @@ public class TreeCutting
}
public static boolean canChop(IBlockState state)
{ return BlockCategories.isLog(state); }
{ return BlockCategories.isLog(state) || Compat.canChop(state); }
/**
* Chops a tree, returns the damage that the cutting tool shall take
*/
public static int chopTree(World world, IBlockState broken_state, BlockPos startPos, int max_blocks_to_break, boolean without_target_block)
{
if((Compat.canChop(broken_state))) return Compat.chop(world, broken_state, startPos, max_blocks_to_break, without_target_block);
if(!BlockCategories.isLog(broken_state)) return 0;
final long ymin = startPos.getY();
final long max_leaf_distance = 6;