public static void applyShape(
      IShape shape,
      EntityPlayer player,
      ArrayList<NBTTagCompound> blockDataNbtList,
      byte baseRotation) {
    try {
      ArrayList<BlockData> blockDataList = new ArrayList<>();
      for (NBTTagCompound compound : blockDataNbtList) {
        BlockData blockData = new BlockData(compound);
        for (int i = 0; i <= blockData.weight; i++) blockDataList.add(blockData);
      }

      int x = Helper.round(player.posX),
          y = Helper.round(player.posY + 1),
          z = Helper.round(player.posZ);
      Collection<PointI> points =
          shape
              .rotate(baseRotation)
              .rotate(baseRotation == -1 ? -1 : Helper.getHeading(player))
              .move(x, y, z)
              .getPoints();
      for (PointI p : points) {
        if (!shape.getReplaceableOnly()
            || player
                .worldObj
                .getBlock(p.getX(), p.getY(), p.getZ())
                .isReplaceable(player.worldObj, p.getX(), p.getY(), p.getZ())) {
          BlockData block =
              blockDataList.size() == 1
                  ? blockDataList.get(0)
                  : Helper.getRandomFromSet(blockDataList);
          Block block1 = Block.getBlockById(block.id);
          player.worldObj.setBlock(p.getX(), p.getY(), p.getZ(), block1, block.meta, 2);
          if (block.te != null) {
            TileEntity tileEntity = TileEntity.createAndLoadEntity(block.te);
            tileEntity.setWorldObj(player.worldObj);
            tileEntity.xCoord = p.getX();
            tileEntity.yCoord = p.getY();
            tileEntity.zCoord = p.getZ();
            player.worldObj.setTileEntity(p.getX(), p.getY(), p.getZ(), tileEntity);
          }
        }
      }
    } catch (BlockData.BannedBlockException e) {
      ((EntityPlayerMP) player).playerNetServerHandler.kickPlayerFromServer(e.getMessage());
    } catch (Exception e) {
      e.printStackTrace();
      Pay2Spawn.getLogger().warn("Error spawning in shape.");
      Pay2Spawn.getLogger().warn("Shape: " + shape.toString());
      Pay2Spawn.getLogger().warn("Player: " + player);
      Pay2Spawn.getLogger()
          .warn("BlockData array: " + Arrays.deepToString(blockDataNbtList.toArray()));
    }
  }
  @Override
  public void spawnServerSide(
      EntityPlayerMP player, NBTTagCompound dataFromClient, NBTTagCompound rewardData) {
    byte baseRotation =
        dataFromClient.getBoolean(ROTATE_KEY) ? dataFromClient.getByte(BASEROTATION_KEY) : -1;
    NBTTagList list = dataFromClient.getTagList(SHAPES_KEY, COMPOUND);
    for (int i = 0; i < list.tagCount(); i++) {
      NBTTagCompound shapeNbt = list.getCompoundTagAt(i);

      ArrayList<NBTTagCompound> blockDataList = new ArrayList<>();
      NBTTagList blockDataNbt = shapeNbt.getTagList(BLOCKDATA_KEY, COMPOUND);
      for (int j = 0; j < blockDataNbt.tagCount(); j++)
        blockDataList.add(blockDataNbt.getCompoundTagAt(j));

      applyShape(Shapes.loadShape(shapeNbt), player, blockDataList, baseRotation);
    }
  }